美文网首页
Echarts二级分类坐标轴的实现

Echarts二级分类坐标轴的实现

作者: Elliott_077d | 来源:发表于2020-11-11 00:23 被阅读0次
    image.png

    在开发的过程中接到这样一个需求,需要画出如上图的一个柱状图,难点就在于分类lable的实现。
    本来打算使用div或者table来进行计算和布局,但是要和原有图表连在一起,所以不是很方便,于是决定用canvas来做。
    在画线的时候发现了一个很坑爹的地方,就是画出来的线比较细,颜色也比较浅,于是去看看echarts怎么做的,发现echarts的canvas实例是将canvas画布放大至容器的二倍,但是样式还是以容器的宽高为主,这样就加重了线条,经过测试果然是可行的。
    另外一点就是canvas画线的位置是以一个像素点的中间线上下各取0.5像素来画线条,所以在处理线条的时候我们一般会加上0.5像素来画起始点,两倍就是加上一个像素。
    总体思路就是在echarts的容器上再画一个canvas,然后设置z-index比echarts的小,之后就是数学方面的计算了。
    附上关键代码

    function addCanvas(el) {
      let canvas = document.createElement('canvas');
      let width = el.offsetWidth;
      let height = el.offsetHeight;
      canvas.width = width * 2;
      canvas.height = height * 2;
      canvas.style = `position:absolute;top:0;left:0;width:${width}px;height:${height}px;z-index:-1`;
      el.appendChild(canvas);
      return {
        context: canvas.getContext('2d'),
        width: width * 2,
        height: height * 2,
      };
    }
    /**
     *
     * @param {*} echartsInstance eCharts实例
     * @param {*} baseLineBottom 分类基线距离echarts容器高度
     * @param {*} tickRates 每条分割线所占的位置
     * @param {*} names 每一个类别的名称
     */
    function splitArea(echartsInstance, baseLineBottom, tickRates, names) {
      let option = echartsInstance.getOption();
      let { context, width, height } = addCanvas(echartsInstance.getDom());
      let { left, right, bottom } = option.grid[0];
      let start, end, tickLength;
      if (typeof left === 'number') {
        start = left * 2 + 1;
      } else {
        start = (parseFloat(left) / 100) * width + 1;
      }
      if (typeof right === 'number') {
        end = width - right * 2 + 1;
      } else {
        end = width - (parseFloat(left) / 100) * width + 1;
      }
      if (typeof bottom === 'number') {
        tickLength = bottom * 2 - baseLineBottom * 2;
      } else {
        tickLength = (parseFloat(bottom) / 100) * height - baseLineBottom * 2;
      }
      context.strokeStyle = 'black';
      context.lineWidth = 2;
      context.font = '24px Arial';
      context.beginPath();
      // context.moveTo(start, height - baseLineBottom * 2);
      // context.lineTo(end, height - baseLineBottom * 2);
      tickRates.forEach((item, index) => {
        console.log(start + (end - start) * item);
        context.moveTo(start + (end - start) * item, height - baseLineBottom * 2);
        context.lineTo(start + (end - start) * item, height - baseLineBottom * 2 - tickLength);
        if (index !== 0) {
          let fontWidth = context.measureText(names[index - 1]).width;
          context.fillText(
            names[index - 1],
            start +
              (tickRates[index - 1] + (item - tickRates[index - 1]) / 2) * (end - start) -
              fontWidth / 2,
            height - baseLineBottom * 2 - tickLength / 2 + 24,
          );
        }
      });
      context.stroke();
    }
    
    // 省略了echarts初始化的代码,调用示例如下。
     splitArea(myChart, 10, [0, 3 / 6, 5 / 6, 1], ['类别一', '类别二', '类别三xxx']);
    

    相关文章

      网友评论

          本文标题:Echarts二级分类坐标轴的实现

          本文链接:https://www.haomeiwen.com/subject/eobsbktx.html