关于svg:记一下漏斗图SVG实现

45次阅读

共计 1563 个字符,预计需要花费 4 分钟才能阅读完成。

最近接的需要里有个漏斗图,比照了下图表库的漏斗,长得有点不大一样,尽管一样有漏斗,然而残余局部看着图表库没法组合实现,于是想想本人简略实现一个。

左边局部其实很好简略,次要是右边的漏斗图实现,漏斗图其实就是几个等腰梯形拼装起来,如果是用 div+css,想到的是利用 border,那么组装起来又略微麻烦的,罗唆用 svg 来做:

  1. polygon 就能够间接画等腰梯形
  2. 固定坐标的形式使得拼接也没多大问题

那么怎么取梯形的坐标点呢?和数据有什么样的法则?


通常来说漏斗都是上宽下窄,每一个梯形的高低边长,其实对应这每一块节点数据的比照。
如上图,假如即为漏斗第一格数据,那么 AB 边长即为漏斗的最大宽度,也映射着第一格数据,而底边 CD 变长则映射为第二格数据。
那么两条边的比例即可确定了,假如漏斗数据为 a1,a2,a3,a4
那么 AB : CD = a1 : a2

A 点坐标为终点,即 (0, 0),假如漏斗图宽为 allWidth,那么 B 点坐标应该就是 (allWidth, 0)
C 点坐标即计算 (CG, AG):

  • 漏斗块咱们固定高度,所以 AG 长固定, 假设为 h
  • CG = (AB – CD)/2; 转为计算数据比例则是 CG = allWidth * (1 – a2/a1)/2

D 点坐标利用等腰梯形对称个性,坐标为 (allWidth – CG, h)

认真一想,每个梯形的顶边坐标即为上一个梯形的底边坐标,而底边坐标只有计算出差值即 CG 边长,即可得出左右两坐标的横坐标。

基于这些总结的关系,假如咱们的数据是这样的 list = [{number: 100}, {number: 60}, {number: 50}, {number: 10}],咱们按上面代码来取出要画的四个 polygon 的四个顶点坐标(0,0)为终点

// BASE_WIDTH 为理论边宽, PER_HEIGHT 为梯形高
// 取出顶边数据(对应 BASE_WIDTH)
    const allWidth = list[0].number;
    // 先计算每一个差值
    const deltas = list
      .slice(1)// 排除掉第一个数据即基准值
      .concat(list[list.length - 1]) // 结尾补充一个,最初一个梯形没有下一个比拟,所以是矩形
      .map((item) => {return ((1 - item.number / allWidth) / 2) * BASE_WIDTH;
      });
    // 遍历数据
    return list.map((item, index) => {
      let points;
      // 独立解决第一个数据
      if (index === 0) {
        points = [[0, 0],// 左上点
          [BASE_WIDTH, 0],// 右上点
          [BASE_WIDTH - deltas[index], PER_HEIGHT],// 右下点 横坐标即全长 - 差值
          [deltas[index], PER_HEIGHT], // 左下点 横坐标即为差值
        ];
      } else {
        points = [[deltas[index - 1], PER_HEIGHT * index], // 左上点,即上一个梯形的左下点,纵坐标为一个 PER_HEIGHT
          [BASE_WIDTH - deltas[index - 1], PER_HEIGHT * index],// 右上点 即上一个梯形的右下点
          [BASE_WIDTH - deltas[index], PER_HEIGHT * (index + 1)],// 右下点
          [deltas[index], PER_HEIGHT * (index + 1)],// 左下点
        ];
      }
      return {
        ...item,
        points,
      };
    });

至此,就整顿出了几个梯形对应的顶点坐标了,接下来只有利用一下 svg 的 polygon 即可。

右边局部漏斗实现后,就剩下后边的了,显然也能够用 polygon 来画,而且还更不便和右边的对齐。

整体成果见 codepen >> https://codepen.io/shellphon-…

正文完
 0