实现迷你趋势图,带渐变色背景,自适应宽度

效果:

迷你趋势图实现参考抛开echarts手动实现迷你趋势图_echarts 趋势图-CSDN博客

渐变色实现如下:

<template>
  <div>
    <div v-html="svg" class="svg"></div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      svg: "",
    };
  },
  mounted() {
    //渲染svg
    const generateSvg = (data, width, height) => {
      const maxValue = Math.max(...data);
      const minValue = Math.min(...data.filter((i) => i !== null));
      const range = maxValue - minValue;
      const margin = 2;
      const points = data.map((value, index) => {
        const x = (index / (data.length - 1)) * width;
        const y =
          height -
            margin -
            ((value - minValue) / range) * (height - 2 * margin) || 0;
        return { x, y, isZero: value == null };
      });

      const pathData = generatePathData(points);
      const pathData2 = generatePathData2(points, height);

      // console.log(points)
      return `<svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" style="width:100%"  preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
            <path d="${pathData}" stroke="#003A90" fill="transparent" stroke-width="2" >

            </path>
            <defs>
              <linearGradient id="areaGradient" x1="50%" y1="0%" x2="0%" y2="100%">
                <stop offset="0%" stop-color="rgba(195,220,254, 0.7)" />
                <stop offset="100%" stop-color="rgba(244,250,254, 0.1)" />
              </linearGradient>
            </defs>
            <path
            d="${pathData2}"
              fill="url(#areaGradient)"
              stroke="none"
              stroke-width="2"
            />
      </svg>
      `;
    };

    const generatePathData = (points) => {
      const pathData = points.reduce((acc, point, i, arr) => {
        if (point.isZero) {
            if (i == points.length - 1) {
            // 到最后一个点时设置最低点
            acc += ` C ${point.x},${height} ${point.x},${height} ${point.x},${height}`
          }
          return acc; // 跳过空点
        }
        const previousPoint = arr[i - 1]; // 上一点
        if (i === 0 || previousPoint.isZero) {
          // 如果是第一个点或前一个点是空的,则移动到当前点
          acc += `M ${point.x},${point.y}`;
        } else {
          // 使用贝塞尔曲线连接非空点
          const controlPointX = (previousPoint.x + point.x) / 2;
          acc += ` C ${controlPointX},${previousPoint.y} ${controlPointX},${point.y} ${point.x},${point.y}`;
        }
        return acc;
      }, "");

      return pathData;
    };
    const generatePathData2 = (points, height) => {
      const pathData = points.reduce((acc, point, i, arr) => {
        if (point.isZero) {
          return acc; // 跳过空点
        }
        const previousPoint = arr[i - 1]; // 上一点
        if (i === 0 || previousPoint.isZero) {
          // 设置最低点
          acc += `M ${point.x},${height}`;
        } else {
          // 使用贝塞尔曲线连接非空点
          const controlPointX = (previousPoint.x + point.x) / 2;
          acc += ` C ${controlPointX},${previousPoint.y} ${controlPointX},${point.y} ${point.x},${point.y}`;
          // acc += ` C ${controlPointX},${previousPoint.y} ${controlPointX},${point.y} ${point.x},${i==points.length-1?height:point.y}`
          if (i == points.length - 1) {
            // 到最后一个点时设置最低点
            acc += ` C ${point.x},${point.y} ${point.x},${point.y} ${point.x},${height}`;
          }
        }
        return acc;
      }, "");

      return pathData;
    };
    const data = [20, 0, 100, 0, 0, 30, 50, 0, 0, 60, 80, 90, 100];
    //const data = [100, 100, 0, 100, 100, 100, 100, 100];
    this.svg = generateSvg(data, 200, 50);
  },
};
</script>
<style lang="less" scoped>
.svg{
  width: 200px;
  height: 50px;
}
</style>
由于画渐变色背景是由开始节点和结束节点决定的,因此需要在generatePathData2函数中的acc变量前后都设置最低点
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值