在我们做的可视化大屏项目中,经常会遇到飞线的效果。 在我们的大屏编辑器中,可以通过拖拽+配置参数的方式很快就能够实现。下面是我们使用大屏编辑器实现的一个项目效果:

效果

中间地图就有飞线的效果。

抛开编辑器的快速实现不说,我们大致来说下canvas绘制飞线的大致原理。

贝塞尔曲线

飞线的路径主要是一个贝塞尔曲线,canvas绘制贝塞尔曲线比较容易。canvas支持绘制二次和三次,在本次示例中,主要还是绘制二次贝塞尔曲线为主。canvas中指定二次贝塞尔曲线路径的函数如下:

ctx.quadraticCurveTo(cpx, cpy, x, y);

有关贝塞尔曲线的基础知识,读者可以自行学习,此处不再赘述。

渐变实现

从图中,可以看出飞线的效果是淡入的效果,颜色并不是一致的,起点处颜色很淡,终点处颜色就比较浓厚。
怎么样能够实现这种效果呢? 答案就是渐变,我们知道,canvas支持线性渐变和放射渐变。但是这两种渐变似乎都不太适合曲线的路径。

事实上,我们会考虑使用线性渐变。因为飞线效果中,曲线的弯曲程度都不太大,所以使用线性渐变,曲线造成的差异,人眼是感觉不出来的。

嗯嗯,图形学就是欺骗的艺术。

只要在线的起点和终点创建一个线性渐变,起点的颜色非透明度是0,终点的非透明度是1即可达到目标。

示例代码如下:

function createGradient(ctx,p0,p1){var grd = ctx.createLinearGradient(p0.x,p0.y,p1.x,p1.y);grd.addColorStop(0,'rgba(255,0,255,0)');grd.addColorStop(1,'rgba(255,0,255,1)');return grd;}ctx.beginPath();ctx.moveTo(P0.x,P0.y);ctx.quadraticCurveTo(Q01.x,Q01.y,B1.x,B1.y);ctx.lineCap = 'round';ctx.lineWidth =3;ctx.strokeStyle = createGradient(ctx,P0,P2);ctx.shadowColor = 'rgba(255,0,255,1)';ctx.shadowBlur = 5;ctx.stroke();

渐变效果

流动效果

流动效果就是线条从起点开始,慢慢飞到终点的效果。 技术角度来说,就是绘制二次曲线百分之几的一部分,百分比的数值从0增加到1,然后又回到0,周而复始。
代码如下:

let percent = 0.0;       function render(){ctx.save();//按百分比绘制ctx.restore();percent += 0.005;if(percent > 1){percent = 0.;}requestAnimationFrame(render);}

问题的关键在于如何绘制贝塞尔曲线的一部分。 一种思路是使用二次贝塞尔曲线的公式,把曲线分成很多片段来进行模拟,然而这种方式的效率并不高。 其实可以使用插值的方式来获取一段贝塞尔曲线。代码如下:

// 参考https://xiaozhuanlan.com/topic/9506147283#section0tlet P0 = startPoint, P1 = controlPoint,P2 = endPoint;let Q01 = interpolation(P0,P1,percent),Q11 = interpolation(P1,P2,percent),B1 = interpolation(Q01,Q11,percent);
function interpolation(P0,P1,t) {var Q = {x: P0.x * (1 - t) + P1.x * (t),y: P0.y * (1 - t) + P1.y * (t),};return Q;}

有关上面插值的原理,可以参考下面的说明,摘取字文章:https://xiaozhuanlan.com/topic/9506147283#section-5

二次贝塞尔曲线

我们知道二次贝塞尔曲线有三个点P0、P1、P2。二次贝塞尔曲线的表达方程如下:
B(t) = (1-t)2 * P0 + 2t(1-t) * P1 + t2 * P2
其中: t 在0~1之间

借助上面一次贝塞尔曲线的计算方法,可以通过以下步骤来确定二次贝塞尔曲线的B(t)点:

  • 选定 t [0,1]
  • 通过插值运算法则,在P0和P1所组成的线段上,计算出P0和P1点之间的插值点Q0,其中插值的比例值是t。根据插值规则有:length( P0, Q0 ) = length( P0, P1 ) * t
  • 通过插值运算法则,在P1和P2所组成的线段上,计算出P1和P2点之间的插值点Q1,其中插值的比例是t。
  • 通过插值运算法则,在Q1和Q2所组成的线段上,计算出P1和P2点之间的插值点B,其中插值的比例是t。
    上述过程中计算出来的点B就是在曲线上面点。上述过程如下图所示:

二次贝塞尔曲线的计算方法过程

从图中可以得出结论:

  • 直线(Q0,Q1)和曲线相切于B点。

另外还有隐藏的结论:

  • 曲线(P0,B)也是贝塞尔曲线,P0是曲线的起始点,B是曲线的终止点,而Q0是控制点
  • 曲线(B,P2)也是贝塞尔曲线,B是曲线的起始点,P2是曲线的终止点,而Q1是控制点

上面两个结论会很有用,有了这个两个结论,前面“迭代(分片)”绘制部分贝塞尔的方法,可以用更加简单的方法替代,这在稍后详细说明。

如果将t的值从0过渡到1,不断计算点B,这些点的集合就可以组成一条二次贝塞尔曲线。下面图形动画复现了这个效果:

二次贝塞尔曲线的计算方法过程

通过上面的方式,就可以绘制流动的飞线效果了,如下图所示:

流动效果

加上阴影

默认线条的样式并不是很好看,如果加上阴影,可以让效果更加丰满。 加上阴影也很简单,代码如下:

ctx.shadowColor = 'rgba(255,0,255,1)';ctx.shadowBlur = 5;

最终的飞线效果参考下图:

效果

结语

如果对可视化感兴趣,可以和我交流,微信541002349. 如果你对我们的大屏编辑器产品或者3d组态编辑器感兴趣,可以加我微信交流,或者发邮件也可以,terry.tan@servasoft.com。 另外关注公众号“ITMan彪叔” 可以及时收到更多有价值的文章。

canvas 绘制直线 并选中_canvas绘制飞线效果相关推荐

  1. canvas绘制飞线效果

    在我们做的可视化大屏项目中,经常会遇到飞线的效果. 在我们的大屏编辑器中,可以通过拖拽+配置参数的方式很快就能够实现.下面是我们使用大屏编辑器实现的一个项目效果: 中间地图就有飞线的效果. 抛开编辑器 ...

  2. echart实现3d地图_3D飞线效果——让线“飞”起来的秘密

    在城市规划.统计.交通等行业,地图可视化已成为最直接也最吸引眼球的一种表达方式.例如人群迁徙.人口流动.OD出行.职住分析.客流来源等众多场景都需要用到飞线效果呈现. 2D飞线效果图 随着可视化技术的 ...

  3. shader实现飞线效果(three.js练习)

    一.先看看效果 二.实现方法: 1.飞线的相关配置数据准备 // 飞线效果的相关配置数据 const flyData = [{start: { //起始点位置x: 0,y: 0,z: 0},end: ...

  4. Echarts实现3d 地图实现飞线效果

    Echarts实现3d 地图实现飞线效果 注意:重点关注data中的数据格式 在lines3D中symbol不能设置指定样式,echarts官网也没有这个参数,所以对于lines3D飞线如何实现飞机航 ...

  5. canvas 绘制直线 并选中_在画布中使用路径-Canvas的基本操作

    一.在画布中使用路径 beginPath() 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径moveTo(x, y) 把画笔移动到指定的坐标(x, y).相当于设置路径的起始点坐标 ...

  6. canvas 绘制直线 并选中_javascript自学记录:canvas绘图

    由于学习js是为爬虫服务,所以canvas绘图学习并不完整. 第15章 使用Canvas绘图 15.1 基本用法 HTML文件中需要有canvas元素,两标签之间的文字是浏览器不支持时显示的. A d ...

  7. C# 画(绘制)直线 C#如何画直线 C#绘制直线 WPF 画(绘制)直线

    C#画直线 1.winform 使用的是 Graphics private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g ...

  8. python如何绘制直线_成对绘制直线

    我正在做一个网络项目,在这个项目中,我需要在成对的点(节点)之间绘制线(边).目前我正在使用matplotlib.pyplot但问题是pyplot.plot绘图(x,y)从(x[0],y[0])开始, ...

  9. html怎么绘制飞线,绘制飞线,echarts迁徙图原理

    其实是在元素上绘制了一条线,然后利用canvas 的createLinearGradient函数不断移动线段的样式位置来实现. 因此首先绘制线段 ctx.beginPath(); ctx.moveTo ...

  10. - Canvas 简介- 使用 Canvas 绘制图形- Canvas 常用方法- SVG 简介- 使用 SVG 绘制基本图形

    1 Canvas 简介 Canvas 表示画布,现实生活中的画布是用来作画的. HTML5 中的 Canvas :我们可以称它为"网页中的画布".默认情况下,Canvas 是一块 ...

最新文章

  1. OCA读书笔记(6) - 配置Oracle网络环境
  2. ECSHOP删除云服务
  3. 用AI分析食物成分,让你能更好地进行营养搭配!
  4. altium designer 原理图和PCB 多通道设计
  5. ACM_逆序数(归并排序)
  6. 涉及CDI和JSF的过期对话的定制错误页面
  7. 天然气表怎么看多少方_上海考大学难度怎么样?看2019上海高考“成绩分布表”和“本科分数线”就知道了!...
  8. django 定制admin
  9. 微信JS-SDK项目学习 --实现分享样式控制thinkphp
  10. pp助手苹果版本_曾经iOS一代越狱神奇器,PP助手宣布凉凉
  11. VSCode安装教程详细简单版
  12. 在 vue 中基于 tinymce 封装的一个富文本编辑器组件
  13. ASC19 初赛要求自翻译
  14. Android-SEAndroid权限问题指南
  15. 网站推广优化教程100条(完整版)-
  16. 2021年饶州中学高考成绩查询,鄱阳饶州中学2019高考成绩喜报、一本二本上线人数情况...
  17. Foo,getName题解分析
  18. 流程图用什么软件做?这篇文章告诉你(内附详细教程)
  19. stm32 cubemx 新建项目一直报错的问题终于解决了
  20. IT攻城狮常用英文-数据结构篇

热门文章

  1. 【一天一个C++小知识】003.C++中的void指针类型
  2. 线性代数【八】二次型
  3. JAVA RMI远程方法调用简单实例
  4. 机器学习and深度学习学习资料
  5. Tensorflow训练mnist数据集源代码解析
  6. Hard problem CodeForces - 706C
  7. 深入理解javascript函数定义与函数作用域
  8. 个人作业-2016.12.2
  9. RAC以及ASM安装全过程整理
  10. OpenCV中用findContours函数出现的问题和解决方法