使用ZRender画贝塞尔曲线

时间:2023-01-19 05:46:51

背景

最近设计师控制不住自己的洪荒之力,设计图搞得高端大气上档次,各种曲线满天飞。为了更好地实现页面效果,经常需要绘制形如下图的贝塞尔曲线:
使用ZRender画贝塞尔曲线

一般实现这种效果有两种思路:SVG和Canvas。直接使用Canvas去画贝塞尔曲线比较繁琐,故在开发中使用了ZRender.js这款Canvas库。


ZRender简介

ZRender是EChart的底层库,功能十分强大,可以很方便地在Canvas中绘制各种图形。

截止今日(2017-11-16),ZRender的最新版本为3.7.x,而直接在必应上面搜索ZRender搜出来的官网和文档都是几年前的比较老旧的、基于2.x版本资料,但是最新版的3.7.x的API与2.x版本的相比有很多API和使用方法都发生了较大的改变,因此应直接查看新版资料:

github:https://github.com/ecomfe/zrender
文档地址:https://ecomfe.github.io/zrender-doc/public/


贝塞尔曲线的绘制

回过头来看曲线。上面图中的这种曲线有个明显特点就是曲线的起点终点处的切线方向都是水平方向的。绘制这种曲线需要2个控制点。一般地,对于起点坐标为(x1, y1),终点坐标为(x2, y2)的这类曲线,其两个控制点的坐标分别为:

((x1 + x2) / 2, y1)( (x1 + x2) / 2, y2)

知道了这个公式,接下来就可以用ZRender画图了。

首先,访问上文中提到的文档地址,按照里面说明即可下载到ZRender库,并引入到页面里。接下来的代码主要有三步:

  1. 创建一个ZRender实例:
    var zr = zrender.init(document.getElementById('box'))

  2. 本例中以画布的两个对角线为起止点,创建一个贝塞尔曲线实例。
    其中,shape用以配置贝塞尔曲线的起止点坐标和控制点坐标,x1,y1是起始点坐标,x2,y2是结束点坐标,cpx1,cpy1是第一个控制点的坐标,cpx2,cpy2是第二个控制点的坐标。
    style用以配置绘图相关的选项,如stroke是画线的颜色,lineWidth是线的宽度。

var h = zr.getHeight(),
    w = zr.getWidth(),
    line = new zrender.BezierCurve({
    shape: {
        x1: 0,
        y1: h,
        cpx1: w / 2,
        cpy1: h,
        cpx2: w / 2,
        cpy2: 0,
        x2: w,
        y2: 0
    },
    style: {
        stroke: 'green',
        lineWidth: 2
    }
});

3 . 将贝塞尔曲线添加到画布中。
zr.add(line);

至此, 贝塞尔曲线绘制完毕。

附完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="box" style="height:400px;width:600px;border:1px solid black;"></div>

    <script src="./zrender.min.js"></script>
    <script> var zr = zrender.init(document.getElementById('box')), h = zr.getHeight(), w = zr.getWidth(), line = new zrender.BezierCurve({ shape: { x1: 0, y1: h, cpx1: w / 2, cpy1: h, cpx2: w / 2, cpy2: 0, x2: w, y2: 0 }, style: { stroke: 'green', lineWidth: 2 } }); zr.add(line); </script>
</body>
</html>