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


相关文章
|
小程序 前端开发
微信小程序中使用画布canvas实现动态心电图绘制
微信小程序中使用画布canvas实现动态心电图绘制
453 0
微信小程序中使用画布canvas实现动态心电图绘制
|
7月前
31Echarts - 柱状图(特性示例:渐变色 阴影 点击缩放)
31Echarts - 柱状图(特性示例:渐变色 阴影 点击缩放)
32 0
|
7月前
|
存储 前端开发
canvas自定义绘制顺序解决遮挡问题
canvas自定义绘制顺序解决遮挡问题
97 0
|
10月前
|
定位技术
Echarts实战案例代码(39):地理坐标整体地图背景色渐变效果和字体随地图缩放的解决方案
Echarts实战案例代码(39):地理坐标整体地图背景色渐变效果和字体随地图缩放的解决方案
192 0
|
前端开发 JavaScript
教你如何利用canvas画布绘制哆啦A梦
订阅专栏 教你如何利用canvas画布绘制哆啦A梦 最近一直在练习使用canvas画布标签,今天教大家如何使用canvas画布绘制哆啦A梦。如图: HTML代码: <canvas id="my_canvas"></canvas> 1 CSS代码: canvas { display:block; margin:0 auto; background: pink } 1 2 3 4 5 JavaScript代码: var oCanvas = document.getEleme
教你如何利用canvas画布绘制哆啦A梦
从一个圆环进度功能来学习SVG
从一个圆环进度功能来学习SVG
115 0
从一个圆环进度功能来学习SVG
|
前端开发 JavaScript
canvas设置像素与画布样式宽高不符的原因及解决办法
canvas设置像素与画布样式宽高不符的原因及解决办法
664 0
|
Web App开发 移动开发 前端开发
H5:画布Canvas基础知识讲解(三)之文字、阴影、颜色渐变
​上一节介绍了H5:画布Canvas基础知识讲解(二)之插入图像、像素级操作,接下来继续讲解H5:画布Canvas基础。
|
前端开发 JavaScript Serverless
在 CSS 中使用三角函数绘制曲线图形及展示动画
在 CSS 中使用三角函数绘制曲线图形及展示动画
318 0
在 CSS 中使用三角函数绘制曲线图形及展示动画
|
前端开发
canvas如何绘制标签,在知识的海洋狗刨(上)
下面总结了一些canvas绘制标签的心得体会,希望能够对你有所帮助。