canvas可视化效果之内阴影效果

canvas可视化效果之内阴影效果

楔子

在之前的一个轨道交通可视化项目中,运用到了很多绘制技巧。 可以参考 之前的一篇文章 《利用canvas阴影功能与双线技巧绘制轨道交通大屏项目效果

效果图中的轨道,就同时存在外发光和内发光效果的效果。

外发光效果

我们知道外发光效果是很容易实现的,直接通过设置阴影效果即可达到。比如我们随便绘制一条线段,加上阴影效果,看起来就是外发光的效果:

1 ctx.clearRect(0,0,canvas.width,canvas.height); 2 ctx.shadowBlur= 20; 3 ctx.shadowOffsetX = 0; 4 ctx.shadowOffsetY = 0; 5 ctx.shadowColor="red"; 6 ctx.lineCap = "round"; 7 ctx.lineJoin = "round"; 8 ctx.lineWidth = 10; 9 ctx.strokeStyle = "blue"; 10 ctx.beginPath(); 11 ctx.moveTo(300,300); 12 ctx.lineTo(750,300); 13 ctx.quadraticCurveTo(800,300,800,350); 14 ctx.lineTo(800,450); 15 ctx.quadraticCurveTo(800,500,750,500); 16 ctx.lineTo(300,500); 17 ctx.stroke();

效果图如下:

如果绘制圆形效果如下:

上面的代码都容易理解,就是通过shadowBlur产生渐变阴影的效果。 默认的阴影,我们称之为外阴影,意思都是图像向往展开的阴影效果。

内阴影

接下来的问题可能就变得有点难度。如果我们需要如下的一个内阴影的效果呢?

有人说,简单,一个渐变就搞定了。 那再看看下面这个图像呢?

还是没问题,还是可以通过渐变来搞定,只是渐变的stop设置要麻烦一点罢了。 如果在复杂一些的图形呢,比如下面的线段效果:

对于上面的线段的内阴影效果,就很难使用简单的渐变来实现了。

如何绘制内阴影效果

要实现上面的内阴影效果,首先还是使用shadowBlur参数,然后把ctx的globalCompositeOperation参数设置为“source-out” 即可。 试试如下代码:

1 ctx.globalCompositeOperation = 'source-out'; 2 ctx.beginPath(); 3 ctx.beginPath(); 4 ctx.moveTo(300,300); 5 ctx.lineTo(750,300); 6 ctx.quadraticCurveTo(800,300,800,350); 7 ctx.lineTo(800,450); 8 ctx.quadraticCurveTo(800,500,750,500); 9 ctx.lineTo(300,500); 10 ctx.lineCap = "round"; 11 ctx.shadowBlur =15; 12 ctx.lineWidth = 20; 13 ctx.shadowColor="blue"; 14 ctx.fillStyle = 'red'; 15 ctx.strokeStyle = 'red'; 16 ctx.stroke();

最终绘制的效果就是上面的线段图的效果:

同时绘制内外阴影效果

如果修改globalCompositeOperation为“xor”,我们还可以得到既有内阴影又有外阴影的效果。 代码如下:

1 ctx.globalCompositeOperation = 'xor'; 2 ctx.beginPath(); 3 ctx.beginPath(); 4 ctx.moveTo(300,300); 5 ctx.lineTo(750,300); 6 ctx.quadraticCurveTo(800,300,800,350); 7 ctx.lineTo(800,450); 8 ctx.quadraticCurveTo(800,500,750,500); 9 ctx.lineTo(300,500); 10 ctx.lineCap = "round"; 11 ctx.shadowBlur =15; 12 ctx.lineWidth = 20; 13 ctx.shadowColor="red"; 14 ctx.fillStyle = 'red'; 15 ctx.strokeStyle = 'red'; 16 ctx.stroke();

绘制的效果如下:

内阴影的缺陷

上述方法实现的内阴影颜色的颜色只能和绘制主体一样的颜色,而不能像外阴影的颜色一样,可以自由定义。 比如把上述代码中的shadowColor改成blue,只有外阴影的颜色改变了:

1 ctx.globalCompositeOperation = 'xor'; 2 ctx.beginPath(); 3 ctx.beginPath(); 4 ctx.moveTo(300,300); 5 ctx.lineTo(750,300); 6 ctx.quadraticCurveTo(800,300,800,350); 7 ctx.lineTo(800,450); 8 ctx.quadraticCurveTo(800,500,750,500); 9 ctx.lineTo(300,500); 10 ctx.lineCap = "round"; 11 ctx.shadowBlur =15; 12 ctx.lineWidth = 20; 13 ctx.shadowColor="red"; 14 ctx.fillStyle = 'red'; 15 ctx.strokeStyle = 'red'; 16 ctx.stroke();

最终的效果如下图所示:

从图上可以看出只有外阴影颜色改变了,内阴影使用的本体的颜色。

实现闪烁的效果

基于上面的实现,我们可以实现一个阴影闪烁的效果,只需要不断更改shadowBlur的值,代码如下: ··· setInterval(()=>{ xor(); },10)

1let shadowBlur = 5; 2let offset = 0.5; 3 4 5 6function xor(){ 7 ctx.clearRect(0,0,canvas.width,canvas.height); 8 ctx.globalCompositeOperation = 'xor'; 9 ctx.shadowBlur= shadowBlur; 10 ctx.shadowOffsetX = 0; 11 ctx.shadowOffsetY = 0; 12 ctx.shadowColor="red"; 13 ctx.lineCap = "round"; 14 ctx.lineJoin = "round"; 15 ctx.lineWidth = 10; 16 ctx.strokeStyle = "blue"; 17 ctx.beginPath(); 18 ctx.moveTo(300,300); 19 ctx.lineTo(750,300); 20 ctx.quadraticCurveTo(800,300,800,350); 21 ctx.lineTo(800,450); 22 ctx.quadraticCurveTo(800,500,750,500); 23 ctx.lineTo(300,500); 24 ctx.stroke(); 25 // ctx.stroke(); 26 27 ctx.globalCompositeOperation = 'xor'; 28 ctx.shadowBlur=shadowBlur / 10.0; 29 ctx.shadowOffsetX=0; 30 ctx.shadowOffsetY=0; 31 ctx.shadowColor="blue"; 32 ctx.lineWidth =1; 33 // ctx.stroke(); 34 35 shadowBlur += offset; 36 if(shadowBlur > 15 || shadowBlur < 1){ 37 offset *= -1; 38 } 39}

···

如果做一些叠加绘制,还可以实现如下效果:

1 function xor(){ 2 ctx.clearRect(0,0,canvas.width,canvas.height); 3 ctx.globalCompositeOperation = 'xor'; 4 ctx.shadowBlur= shadowBlur; 5 ctx.shadowOffsetX = 0; 6 ctx.shadowOffsetY = 0; 7 ctx.shadowColor="red"; 8 ctx.lineCap = "round"; 9 ctx.lineJoin = "round"; 10 ctx.lineWidth = 20; 11 ctx.strokeStyle = "red"; 12 ctx.beginPath(); 13 ctx.moveTo(300,300); 14 ctx.lineTo(750,300); 15 ctx.quadraticCurveTo(800,300,800,350); 16 ctx.lineTo(800,450); 17 ctx.quadraticCurveTo(800,500,750,500); 18 ctx.lineTo(300,500); 19 ctx.stroke(); 20 // ctx.stroke(); 21 22 ctx.globalCompositeOperation = 'destination-out'; 23 ctx.shadowBlur=shadowBlur / 10.0; 24 ctx.shadowOffsetX=0; 25 ctx.shadowOffsetY=0; 26 ctx.shadowColor="red"; 27 ctx.lineWidth =5; 28 ctx.stroke(); 29 30 shadowBlur += offset; 31 if(shadowBlur > 15 || shadowBlur < 1){ 32 offset *= -1; 33 } 34 }

结语

至此文章已经到达尾声,我们可以总结一下绘制内阴影效果所用到的技术点

  1. CanvasRenderingContext2D.globalCompositeOperation
  2. CanvasRenderingContext2D.shadowBlur

其中globalCompositeOperation是一个有意思的属性,通过设置不同的参数,可以实现很多不同的效果。比如如下的效果就用到了这个属性: image.png

有兴趣的读者可以关注往期更多的文章。

如果对可视化感兴趣,可以和我交流,微信541002349. 另外关注公众号“ITMan彪叔” 可以及时收到更多有价值的文章。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

java中比较两个时间的差值

项目背景1.某篇文稿的发布时间是publishDate,例如:2020072118:00:41。2.现要求判断该篇文稿的发布时间是否在近30天之内。publicstaticlongdayDiff(DatecurrentDate,DatepublishDate){LongcurrentTimecurrentDat

canvas可视化效果之内阴影效果 - HelloWorld