用 Canvas 绘制飞线

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用 Canvas 绘制飞线相关的知识,希望对你有一定的参考价值。

参考技术A 2016-05-12

上一周完成了地图与飞线的实现,使用的是 d3.js + svg,后发现可能存在性能隐患。

当飞线数量多的时候,页面上则有多个 svg <path> 结点,并且每条飞线有头部、结束圆圈、蒙板等效果,则页面上的结点数是 飞线数*其他部件数。将会是一个较大的值。

画布罩在整个 html 上,共两层 Canvas 画布,底层绘制世界地图,表层绘制飞线。

二次贝塞尔曲线公式

(其中 起始点 p0, 控制点 p1, 终点 p2)

t 从 0 变到 1,每个 t 的变化时,就绘制一帧;
飞线的速度就取决于增量变化的大小,增量越小,动画就越细致。

如何表现 t ?
给每一个飞线对象单独一个 t 属性,每绘制完一帧,t = t + 增量(固定值);

requestAnimationFrame 动画

与 SVG 飞线 相比:

渐变消失: ctx.globalAlpha

使用 globalAlpha 和 临时 Canvas;

但有两个弊端:

模拟数据来源于B2B 外贸单日询盘量,总数共 596 条, 单次同时绘制 50 条 飞线情况下:

具体如下:

动画帧数保持在 42-60 左右,动画流畅;

动画帧数保持在 12-43 左右,视觉上仔细看略有卡顿;

CPU 占用率在 20%-30% 浮动

CPU 占用率高于 100%

皆无内存泄漏问题。 SVG 飞线的 JS heap 总大小略高于 Canvas 飞线。

测试了 Canvas 飞线,在同时绘 50 条、100 条、200 条、300 条、400 条 时的动画流畅度。

封装 用canvas绘制直线的函数--面向对象

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>用面向对象的思想 封装 在canvas绘制直线的函数</title>
 6 </head>
 7 <body>
 8     <canvas id="cv"></canvas>
 9 </body>
10 </html>
11 <script>
12     var cv = document.getElementById("cv");
13     cv.width = 600;
14     cv.height = 300;
15     cv.style.border = "1px solid red";
16     var ctx = cv.getContext("2d");
17 
18     //面向对象编程
19     //1 创建构造函数
20     //2 构造函数的原型设置
21     //3 调用的时候,通过 new+构造函数 来创建一个对象(实例)
22 
23     //构造绘制直线的函数
24     function drawLine(parameters) {
25         this.init(parameters);
26     }
27     //替换原型对象实现继承
28     drawLine.prototype = {
29         constructor: drawLine,
30         init: function (parameters) {
31             this.ctx = parameters.ctx;
32             this.startX = parameters.points[0];
33             this.startY = parameters.points[1];
34             this.endX = parameters.points[2];
35             this.endY = parameters.points[3];
36             //以下3个属性,可以不设置,用短路运算实现添加默认属性值
37             this.lineWidth = parameters.lineWidth || 1;
38             this.lineDash = parameters.lineDash || [];
39             this.strokeStyle = parameters.strokeStyle || "#000";
40         },
41         //原型中,一般用来储存对象的方法或者共有的属性
42         stroke: function () {
43             this.ctx.beginPath();
44             this.ctx.moveTo(this.startX, this.startY);
45             this.ctx.lineTo(this.endX, this.endY);
46             this.ctx.lineWidth = this.lineWidth;
47             this.ctx.setLineDash(this.lineDash);
48             this.ctx.strokeStyle = this.strokeStyle;
49             this.ctx.stroke();
50         }
51     };
52 
53     //调用构造函数,传入参数
54     var line = new drawLine({
55         ctx: ctx,
56         points: [100, 100, 300, 100],
57         lineDash: [4, 2],
58         strokeStyle: "red"
59     });
60     line.stroke();
61     var line2 = new drawLine({
62         ctx: ctx,
63         points: [100, 200, 300, 200],
64         lineWidth: 6
65     });
66     line2.stroke();
67 </script>

 效果图:

以上是关于用 Canvas 绘制飞线的主要内容,如果未能解决你的问题,请参考以下文章

canvas 绘制验证码

用Canvas绘制一个钟表

如何用tablea7绘制canvas

android中,如何用canvas绘制透明?

canvas中怎么绘制一个扇形?四分之一圆.

canvas绘制箭头路径效果