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

简介: canvas可视化效果之内阴影效果

楔子


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


微信图片_20220425132728.png


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


外发光效果


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


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();


效果图如下:


微信图片_20220425132734.png


如果绘制圆形效果如下:


微信图片_20220425132737.png


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


内阴影


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


微信图片_20220425132740.png


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


微信图片_20220425132743.png


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


微信图片_20220425132746.png


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


如何绘制内阴影效果


要实现上面的内阴影效果,首先还是使用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();


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


微信图片_20220425132750.png


同时绘制内外阴影效果


如果修改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();


绘制的效果如下:


微信图片_20220425132754.png


内阴影的缺陷


上述方法实现的内阴影颜色的颜色只能和绘制主体一样的颜色,而不能像外阴影的颜色一样,可以自由定义。比如把上述代码中的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();


最终的效果如下图所示:


微信图片_20220425132757.png


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


实现闪烁的效果


基于上面的实现,我们可以实现一个阴影闪烁的效果,只需要不断更改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}


···

image.gif微信图片_20220425132801.gif

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


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    }


微信图片_20220425132806.gif


结语


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

  1. CanvasRenderingContext2D.globalCompositeOperation
  2. CanvasRenderingContext2D.shadowBlur


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


微信图片_20220425132809.pngimage.png


相关文章
|
JavaScript
使用nodejs连接ftp上传下载
使用nodejs连接ftp,进行ftp的操作,包括列表、上传、下载以及速率等。
使用nodejs连接ftp上传下载
|
9月前
|
缓存 前端开发 JavaScript
深入了解 Vite:快速、简洁、高效的前端构建工具(上)
深入了解 Vite:快速、简洁、高效的前端构建工具(上)
|
移动开发 前端开发 iOS开发
记录一下前端H5的复制功能在ios端的兼容性问题
记录一下前端H5的复制功能在ios端的兼容性问题
1068 0
|
数据采集 前端开发 开发者
滑动拼图验证码的原理和破解方法~
滑动拼图验证码的原理和破解方法~
2711 0
|
7月前
|
Web App开发 前端开发
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
canvas系列教程04 —— 渐变、阴影、路径、状态、Canvas对象、图形重叠模式
603 0
|
7月前
|
编解码 前端开发 图形学
采用Canvas Scaler与锚点系统实现UI自适应多屏幕分辨率
【7月更文第10天】在游戏开发或应用设计中,确保用户界面(UI)能够在不同屏幕分辨率和纵横比上保持良好显示效果是一项基本要求。Unity 引擎通过其强大的 UI 系统,特别是 Canvas Scaler 和锚点系统,为开发者提供了实现这一目标的高效工具。本文将深入探讨如何结合使用这两个功能来创建自适应UI布局,以适配广泛的设备屏幕。
372 0
|
9月前
|
JavaScript 前端开发 API
Vue 2 vs Vue 3: 深入浅出的优势剖析
Vue 2 vs Vue 3: 深入浅出的优势剖析
|
安全 开发工具 Python
滑动拼图验证,摆脱烦人的验证码输入
你最近是否遇到过令人头疼的验证码?为何不让滑动拼图成为你的新选择呢?通过完成一个有趣的滑动拼图来验证你的身份,既能锻炼大脑,又能保护你的隐私。
滑动拼图验证,摆脱烦人的验证码输入
|
9月前
|
机器学习/深度学习 人工智能 前端开发
探索人工智能在前端开发中的应用
随着人工智能技术的快速发展,其在前端开发领域的应用也日益普及。本文将探讨人工智能如何改变前端开发方式,以及其在网页设计、用户体验优化等方面的具体应用。
集合的自反关系和对称关系
集合的自反关系和对称关系
161 1

热门文章

最新文章