美文网首页
canvas 配合 zrender 绘制椭圆布局

canvas 配合 zrender 绘制椭圆布局

作者: 纯爱枫若情 | 来源:发表于2019-04-28 18:13 被阅读0次

    前言

    最近碰到个用 canvas 绘制椭圆形的问题,研究了一下,发现挺有意思的。

    在经过一顿摸索以后,实现的效果,也还是挺不错的,在这个过程中也学到了不少东西吧。

    ellipse 方法兼容性问题

    之前没绘制过椭圆,上手,当然是想找找 canvas 原生有没有类似的 api 了。

    于是就上 mdn 搜索一番,这一找,还真的发现有类似的 api,不得不感概,这就太巧了,这问题不就不算问题了么。

    但是一看浏览器兼容性,不禁让人愁绪顿生,这么好的方法,怎么很多浏览器都不支持呢?

    image.png

    对应的代码可以写成下面这样:

    const twoPI = Math.PI * 2;
    
    // n 为想要分的份数
    Array(...Array(n)).forEach((value, index) => {
      let angle = ( twoPI * index) / n;
      
      // center 为中心点坐标位置,r 为半径
      let x = center.x + r * Math.cos(angle);   
      let y = center.y + r * Math.sin(angle);
    });
    

    但是如果是椭圆呢?

    椭圆也是有计算公式的,如下:


    image.png

    对应的代码可以写成下面这样:

    const twoPI = Math.PI * 2;
    
    // n 为想要分的份数
    Array(...Array(n)).forEach((value, index) => {
      let angle = ( twoPI * index) / n;
      
      // center 为中心点坐标位置,a 为长轴半径,b 为短轴半径
      let x = center.x + a * Math.cos(angle);   
      let y = center.y + b * Math.sin(angle);
    });
    

    用 zrender 开始绘制

    这里之所以用 zrender 绘制,纯粹是由于自己从零开始写太过于麻烦了,zrender 本身就是一款不错的 canvas 2d 开源框架,封装了一些功能,能够帮助我们快捷的进行 canvas 绘制。

    如果还不了解 zrender 的童鞋,可以去 zrender 官网了解一下:https://ecomfe.github.io/zrender-doc/public/

    结合上面的算法,我简单地封装了一个绘制的方法:

    /**
     * 创建圆形布局的算法
     * @paramas {Object} center 中心点坐标
     * @paramas {Number} a 长半轴的长度
     * @paramas {Number} b 短半轴的长度
     * @paramas {Number} n 网元个数
     */
    function createEllipse(center, a, b, n) {
      const tP = 2 * Math.PI;
      Array(...Array(n)).forEach((value, index) => {
        const angle = (tP * index) / n;
        const x = center.x + a * Math.cos(angle);
        const y = center.y + b * Math.sin(angle);
    
        var circle = new zrender.Circle({
          shape: {
            cx: x,
            cy: y,
            r: 20
          },
          style: {
            fill: "#0eafd1"
          },
          z: 1
        });
        zr.add(circle);
      });
    }
    

    现在我们调用一下,看一下结果

    const a = 300;
    const b = 150;
    const o = { x: 400, y: 200 };
    
    createEllipse(o, a, b, 10);
    
    结果如下: image.pngimage.png

    哈哈,效果还是不错的吧。

    嗯,不错,此教程到此结束!

    ......

    等等,我们的弧线还没有绘制上来呢!

    不好意思!差点忘记了本来的目的,汗颜!

    接下来,我们就来加上弧线的效果。

    加上曲线连接效果

    zrender 里面是由直接提供 ellipse 的图形的,我看打开 zrender 源码看看: image.pngimage.png

    可以看出,代码很简洁。

    接下来,我们稍微改改我们的代码,在 createEllipse 方法末尾加上绘制椭圆的逻辑:

    var ellipse = new zrender.Ellipse({
    shape: {
      cx: center.x,
      cy: center.y,
      rx: a,
      ry: b,
      // r: 20
    },
    style: {
      fill: "#0eafd100",
      stroke: "red"
    },
    });
    zr.add(ellipse);
    
    然后效果变成这样了: image.pngimage.png

    说实话,这种效果并不是我想要的效果,我想要的是一段段可以自由加进去的,那么只有自己动手添加了。

    一段段添加

    那么该怎么改呢?首先可以分析下,既然我们拓展了浏览器端绘制椭圆的方法,那么直接采用绘制椭圆的方法绘制进去就行了。

    但是问题是,我们怎么拿到 canvas 画笔,绘制到 canvas 里面去呢?

    1. 创建新的 Ellipse2 对象

    我们可以照着 zrender.Ellipse 的代码,创建一个新的图形,就叫 Ellips2 吧:

    zrender.Ellipse2 = zrender.Path.extend({
      type: "ellipse2",
    
      shape: {
        cx: 0,
        cy: 0,
        rx: 0,
        ry: 0,
        fAngle: 0,
        tAngle: Math.PI*2
      },
    
      buildPath: function(ctx, shape) {
        var x = shape.cx;
        var y = shape.cy;
        var a = shape.rx;
        var b = shape.ry;
        var fAngle = shape.fAngle;
        var tAngle = shape.tAngle;
    
        ctx._ctx.ellipse(x, y, a, b, 0, fAngle, tAngle);
    
      }
    });
    

    可以看到,我们在 shape对象上新增了 fAngle 和 tAngle 属性,用来控制起始和终止的角度。

    2. 调用 zrender.Ellipse2 开始逐段绘制

    添加下面的代码,调用 zrender.Ellipse2 方法,绘制我们的弧线

      
    const collections = [];
    Array(...Array(n)).forEach((value, index) => {
      
        ......
      
        collections.push(angle);
      if(index!==0){
        var ellipse = new zrender.Ellipse2({
          shape: {
            cx: center.x,
            cy: center.y,
            rx: a,
            ry: b,
            fAngle: collections[index-1],
            tAngle: angle
          },
          style: {
            fill: "#0eafd100",
            stroke: "red"
          }
        });
        zr.add(ellipse);
      }
      if(index === n - 1){
        var ellipse = new zrender.Ellipse2({
          shape: {
            cx: center.x,
            cy: center.y,
            rx: a,
            ry: b,
            fAngle: angle,
            tAngle: collections[0]
          },
          style: {
            fill: "#0eafd100",
            stroke: "red"
          }
        });
        zr.add(ellipse);
      }
    
        ......
    });
    

    绘制效果:


    image.pngimage.png

    咋一看,好像跟之前的绘制方式相比,没啥优势啊。

    但是你稍微控制下绘制参数,就可以改变下效果,比如这样:


    image.pngimage.png

    或者这样:


    image.pngimage.png

    后记

    总而言之,用 canvas 绘制椭圆还是挺有意思的吧,我所言非虚吧。

    小伙伴们,赶快学习一波吧。

    相关文章

      网友评论

          本文标题:canvas 配合 zrender 绘制椭圆布局

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