vue实现 2种不同的渐变图例

113 阅读1分钟

第一种效果图:

image.png

vue代码:

 <template>
  <div class="all-legend" ref="allUI">
    <div
      class="each-legend"
      :style="'background-color: rgba(' + item + ');'"
      v-for="(item, index) in legendData.rgbacolors"
      :key="index"
    >
      <span class="val">
        {{ index % interval == 0 ? index : '' }}
      </span>
    </div>
  </div>
</template>

js代码:

<script>
export default {
  components: {},
  props: {},
  data() {
    return {
      legendData: {
        rgbacolors: [
          ['138', '42', '10'],
          ['138', '42', '10'],
          ['142', '43', '11'],
          ['144', '45', '11'],
          ['148', '46', '12'],
          ['150', '47', '12'],
          ['153', '49', '13'],
          ['155', '49', '13'],
          ['159', '51', '13'],
          ['161', '52', '14'],
          ['164', '53', '14'],
          ['166', '54', '14'],
          ['170', '56', '15'],
          ['172', '57', '15'],
          ['175', '59', '16'],
          ['177', '59', '16'],
          ['180', '61', '16'],
          ['183', '62', '17'],
          ['187', '64', '18'],
          ['188', '64', '17'],
          ['191', '66', '18'],
          ['194', '67', '18'],
          ['197', '69', '18'],
          ['199', '70', '17'],
          ['202', '72', '18'],
          ['203', '73', '18'],
          ['206', '75', '19'],
          ['208', '76', '18'],
          ['211', '78', '19'],
          ['213', '79', '19'],
          ['216', '81', '19'],
          ['218', '82', '18'],
          ['221', '84', '19'],
          ['223', '86', '19'],
          ['226', '88', '20'],
          ['227', '89', '19'],
          ['230', '90', '20'],
          ['233', '92', '20'],
          ['236', '94', '20'],
          ['236', '96', '19'],
          ['237', '99', '18'],
          ['237', '102', '17'],
          ['237', '105', '17'],
          ['238', '108', '16'],
          ['238', '111', '16'],
          ['238', '114', '15'],
          ['239', '117', '14'],
          ['239', '120', '13'],
          ['239', '123', '13'],
          ['239', '126', '11'],
          ['240', '129', '11'],
          ['239', '131', '10'],
          ['241', '135', '10'],
          ['241', '138', '9'],
          ['241', '141', '9'],
          ['241', '144', '7'],
          ['242', '147', '7'],
          ['242', '150', '6'],
          ['241', '152', '6'],
          ['239', '152', '5'],
          ['238', '154', '6'],
          ['237', '156', '6'],
          ['237', '157', '6'],
          ['235', '158', '5'],
          ['234', '160', '6'],
          ['233', '161', '6'],
          ['232', '163', '6'],
          ['231', '164', '5'],
          ['231', '166', '6'],
          ['229', '167', '6'],
          ['228', '169', '6'],
          ['226', '170', '5'],
          ['226', '172', '6'],
          ['225', '173', '6'],
          ['224', '175', '6'],
          ['222', '175', '5'],
          ['221', '177', '6'],
          ['218', '175', '7'],
          ['215', '175', '7'],
          ['212', '174', '7'],
          ['210', '173', '8'],
          ['207', '172', '8'],
          ['205', '172', '9'],
          ['201', '170', '9'],
          ['199', '170', '10'],
          ['196', '168', '10'],
          ['194', '167', '11'],
          ['190', '166', '11'],
          ['187', '165', '12'],
          ['184', '164', '12'],
          ['182', '164', '12'],
          ['179', '162', '13'],
          ['176', '162', '13'],
          ['173', '161', '13'],
          ['171', '160', '14'],
          ['168', '159', '14'],
          ['166', '159', '15'],
          ['163', '157', '16'],
          ['161', '157', '17'],
          ['158', '157', '17'],
        ],
        values: [
          40, 39.75, 39.5, 39.25, 39, 38.75, 38.5, 38.25, 38, 37.75, 37.5,
          37.25, 37, 36.75, 36.5, 36.25, 36, 35.75, 35.5, 35.25, 35, 34.75,
          34.5, 34.25, 34, 33.75, 33.5, 33.25, 33, 32.75, 32.5, 32.25, 32,
          31.75, 31.5, 31.25, 31, 30.75, 30.5, 30.25, 30, 29.75, 29.5, 29.25,
          29, 28.75, 28.5, 28.25, 28, 27.75, 27.5, 27.25, 27, 26.75, 26.5,
          26.25, 26, 25.75, 25.5, 25.25, 25, 24.75, 24.5, 24.25, 24, 23.75,
          23.5, 23.25, 23, 22.75, 22.5, 22.25, 22, 21.75, 21.5, 21.25, 21,
          20.75, 20.5, 20.25, 20, 19.75, 19.5, 19.25, 19, 18.75, 18.5, 18.25,
          18, 17.75, 17.5, 17.25, 17, 16.75, 16.5, 16.25, 16, 15.75, 15.5,
          15.25,
        ],
      },
      interval: 1, //控制显示数值内容
    };
  },
  computed: {},
  watch: {},
  created() {},
  mounted() {
    this.setEachHeight();
  },
  methods: {
    /**
     * 图例数据分割
     */
    setEachHeight() {
      if (!this.legendData || !this.legendData.values) return;
      this.interval = Math.ceil(this.legendData.values.length / 10);
      this.$refs.allUI.style.setProperty(
        '--eachHeight',
        100 / this.legendData.rgbacolors.length + '%',
      );
    },
  },
};
</script>
<style scoped lang="less">
.all-legend {
  width: 10rem;
  padding: 3rem;
  background: rgba(255, 255, 255, 0.5);
  margin: 0 auto;
  .each-legend {
    height: var(--eachHeight);
    width: 3rem;
    .val {
      display: block;
      margin-left: 3rem;
      text-align: center;
      width: 3rem;
      z-index: 100;
    }
  }
}
</style>
  1. vue项目里,在方法中控制style的样式需要定义ref
  2. 在setEachHeight方法执行 this.$refs.allUI.style.setPropert(--eachHeight,100 / this.legendData.rgbacolors.length + '%') 给变量赋值(第二个参数是要取得的参数)
  3. style应该写: height:var(--eachHeight)

第二种效果图:

image.png

后台接口形式:

image.png

颜色的格式: image.png

数值的格式: image.png

代码片段:

<template>
  <div class="legends">
    <div class="legend" v-for="(item, index) in legends" :key="index">
      <!-- <div class="name">
        {{ item.name }}<span v-if="item.unit != ''">({{ item.unit }})</span>
      </div> -->
      <div class="name">{{ item.name }}<span>(单位: )</span></div>
      <div
        class="bar"
        :style="{
          background: 'linear-gradient(to right,' + item.bgColors + ')',
        }"
      >
        <div class="number">
          <p v-for="(i, idx) in item.value" :key="idx">{{ i }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    legendData: {
      type: Object,
      default: function () {
        return {};
      },
    },
  },
  mounted() {
    console.log(this.legendData);

    this.createLegend(this.legendData);
  },
  data() {
    return {
      legends: [
        {
          name: '',
          unit: '',
          bgColors: '',
          value: [0, 7.5, 15, 22.5, 30],
        },
      ],
    };
  },
  methods: {
    createLegend(info) {
      this.legends = [];
      let bgColors = info.rgbacolors;
      let values = info.values;
      if (!bgColors) return;
      let arr = [];
      for (let i = 0; i < bgColors.length; i++) {
        let color = bgColors[i];
        arr.push(`rgb(${color[0]},${color[1]},${color[2]})`);
      }
      let bgColorsText = arr.join(',');

      let endValue =
        values.length > bgColors.length
          ? values[values.length - 2]
          : values[values.length - 1];

      let numValue = [];
      if (bgColors.length < 5) {
        numValue = [
          values[0],
          values[parseInt((values.length - 1) / 2)],
          endValue,
        ];
      } else if (bgColors.length == 6) {
        numValue = [
          values[0],
          values[1],
          values[2],
          values[3],
          values[4],
          values[5],
        ];
      } else if (bgColors.length == 5 || bgColors.length > 6) {
        numValue = [
          values[0],
          values[parseInt((values.length - 1) / 2 / 2)],
          values[parseInt((values.length - 1) / 2)],
          values[
            parseInt(
              (values.length - 1 - (values.length - 1) / 2) / 2 +
                (values.length - 1) / 2,
            )
          ],
          endValue,
        ];
      }
      this.legends.push({
        name: name,
        unit: info.unit || '',
        bgColors: bgColorsText,
        value: numValue,
      });
    },
  },
};
</script>
<style lang="scss" scoped>
// .legends {
//   position: absolute;
//   right: 28rem;
//   top: 10rem;
//   width: auto;
//   height: 80%;
// }

.legends {
  position: absolute;
  z-index: 99;
  bottom: 110px;
  left: 28px;

  .legend {
    padding: 4px;
    border-radius: 2px;

    .name {
      padding-left: 1px;
      margin-bottom: 4px;
      font-size: 12px;
      color: #fff;
      text-shadow: 0 0 3px #000;
    }

    .bar {
      width: 280px;
      position: relative;
      height: 14px;
      border-radius: 10px;
      box-shadow: 0 0 4px #252525;

      .number {
        display: flex;
        align-items: center;
        justify-content: space-between;
        position: absolute;
        left: 0;
        right: 0px;
        top: 1px;
        padding: 0 5px;
        box-sizing: border-box;

        p {
          font-size: 12px;
          color: #fff;
          // width: 80px;
          text-align: center;
          text-shadow: -1px 1px #000;
          line-height: 1;
        }

        p:nth-child(1) {
          text-align: left;
        }

        p:nth-child(3) {
          text-align: right;
        }
      }
    }
  }
}
</style>