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

楔子

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

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

外发光效果

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

      ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.shadowBlur= 20;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowColor="red";
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.lineWidth = 10;
ctx.strokeStyle = "blue";
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.stroke();

效果图如下:

如果绘制圆形效果如下:

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

内阴影

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

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

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

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

如何绘制内阴影效果

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

 ctx.globalCompositeOperation = 'source-out';
ctx.beginPath();
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.lineCap = "round";
ctx.shadowBlur =15;
ctx.lineWidth = 20;
ctx.shadowColor="blue";
ctx.fillStyle = 'red';
ctx.strokeStyle = 'red';
ctx.stroke();

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

同时绘制内外阴影效果

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

 ctx.globalCompositeOperation = 'xor';
ctx.beginPath();
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.lineCap = "round";
ctx.shadowBlur =15;
ctx.lineWidth = 20;
ctx.shadowColor="red";
ctx.fillStyle = 'red';
ctx.strokeStyle = 'red';
ctx.stroke();

绘制的效果如下:

内阴影的缺陷

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

 ctx.globalCompositeOperation = 'xor';
ctx.beginPath();
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.lineCap = "round";
ctx.shadowBlur =15;
ctx.lineWidth = 20;
ctx.shadowColor="red";
ctx.fillStyle = 'red';
ctx.strokeStyle = 'red';
ctx.stroke();

最终的效果如下图所示:

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

实现闪烁的效果

基于上面的实现,我们可以实现一个阴影闪烁的效果,只需要不断更改shadowBlur的值,代码如下:

···

setInterval(()=>{

xor();

},10)

let shadowBlur = 5;
let offset = 0.5; function xor(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.globalCompositeOperation = 'xor';
ctx.shadowBlur= shadowBlur;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowColor="red";
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.lineWidth = 10;
ctx.strokeStyle = "blue";
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.stroke();
// ctx.stroke(); ctx.globalCompositeOperation = 'xor';
ctx.shadowBlur=shadowBlur / 10.0;
ctx.shadowOffsetX=0;
ctx.shadowOffsetY=0;
ctx.shadowColor="blue";
ctx.lineWidth =1;
// ctx.stroke(); shadowBlur += offset;
if(shadowBlur > 15 || shadowBlur < 1){
offset *= -1;
}
}

···

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

   function xor(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.globalCompositeOperation = 'xor';
ctx.shadowBlur= shadowBlur;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
ctx.shadowColor="red";
ctx.lineCap = "round";
ctx.lineJoin = "round";
ctx.lineWidth = 20;
ctx.strokeStyle = "red";
ctx.beginPath();
ctx.moveTo(300,300);
ctx.lineTo(750,300);
ctx.quadraticCurveTo(800,300,800,350);
ctx.lineTo(800,450);
ctx.quadraticCurveTo(800,500,750,500);
ctx.lineTo(300,500);
ctx.stroke();
// ctx.stroke(); ctx.globalCompositeOperation = 'destination-out';
ctx.shadowBlur=shadowBlur / 10.0;
ctx.shadowOffsetX=0;
ctx.shadowOffsetY=0;
ctx.shadowColor="red";
ctx.lineWidth =5;
ctx.stroke(); shadowBlur += offset;
if(shadowBlur > 15 || shadowBlur < 1){
offset *= -1;
}
}

结语

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

  1. CanvasRenderingContext2D.globalCompositeOperation
  2. CanvasRenderingContext2D.shadowBlur

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

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

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

canvas可视化效果之内阴影效果的更多相关文章

  1. 【HTML5】Web Audio API打造超炫的音乐可视化效果

    HTML5真是太多炫酷的东西了,其中Web Audio API算一个,琢磨着弄了个音乐可视化的demo,先上效果图: 项目演示:别说话,点我!  源码已经挂到github上了,有兴趣的同学也可以去st ...

  2. 13个可实现超棒数据可视化效果的Javascript框架

    随着商业及其相关需求的发展,数据成为越来越重要的元素之一,为了更加直观和明显的展示商业潜在的趋势和内在的特性,我们需要使用图表和图形的方式来直观动态的展示数据内在秘密,在今天的这篇文章中我们推荐12款 ...

  3. WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形

    原文:WPF,Silverlight与XAML读书笔记第三十九 - 可视化效果之3D图形 说明:本系列基本上是<WPF揭秘>的读书笔记.在结构安排与文章内容上参照<WPF揭秘> ...

  4. BI工具数据可视化效果哪家强?我选这款!

    BI工具是商业智能(Business Intelligence)软件的英文缩写.目前,商业智能通常被理解为将企业中现有的数据转化为知识,帮助企业做出明智的业务经营决策的工具. 企业经常会为如何选择BI ...

  5. CodePen 作品秀:Canvas 粒子效果文本动画

    作品名称——Shape Shifter,基于 Canvas 的粒子图形变换实验.在页面下方的输入框输入文本,上面就会进行变换出对应的粒子效果文本动画. CodePen 作品秀系列向大家展示来自 Cod ...

  6. WPF元素可视化效果

    在WPF中设置元素的可视化效果主要用到BlurEffect类和DropShadowEffect类.(目前只学到这两个,哈哈) 1.BlurEffect类 命名空间: System.Windows.Me ...

  7. HTML5大数据可视化效果(二)可交互地铁线路图

    前言 最近特别忙,承蒙大伙关照,3D机房的项目一个接着一个,领了一帮小弟,搞搞传帮带,乌飞兔走,转眼已经菊黄蟹肥……有个小弟很不错,勤奋好学,很快就把API都摸透了,自己折腾着做了个HTML5的魔都的 ...

  8. HTML5 Canvas动画效果演示

    HTML5 Canvas动画效果演示 主要思想: 首先要准备一张有连续帧的图片,然后利用HTML5 Canvas的draw方法在不同的时间 间隔绘制不同的帧,这样看起来就像动画在播放. 关键技术点: ...

  9. HTML5 Canvas动画效果演示 - 流浪的鱼 - 博客频道 - CSDN.NET

    HTML5 Canvas动画效果演示 - 流浪的鱼 - 博客频道 - CSDN.NET HTML5 Canvas动画效果演示

随机推荐

  1. 从Guarded Block来看Java中的wait和notify方法

    目录 预备知识 概览 线程同步 wait()方法 wait() wait(long timeout) wait(long timeout, int nanos) notify() & noti ...

  2. 用大白话讲大数据HBase,老刘真的很用心(1)

    老刘今天复习HBase知识发现很多资料都没有把概念说清楚,有很多专业名词一笔带过没有解释.比如这个框架高性能.高可用,那什么是高性能高可用?怎么实现的高性能高可用?没说! 如果面试官听了你说的,会有什 ...

  3. go创建动态库

    *nix *nix创建so比较方便,写好go代码之后,直接一条命令搞定. go build -buildmode=c-shared -o libgobblob.so 命令执行之后,会生成libgobb ...

  4. django项目运行步骤

    第一步: 创建gjango项目 django-admin startproject dname python manage.py startapps aname 第二部: 运行 -- 编辑设置 -- ...

  5. 我与PHP,ULM和Vue.js不得不说的故事(我与PHP白月光的那些事儿之第三年的见异思迁番外篇)

    关于PHP的认知 -----恍惚间眸眼像极了一位故人 第一年遇见,那时的它还稚嫩懵懂.像白纸一样的脸,极容易读懂.于是放荡不羁,不放真心.稍微用心,它便能高兴好久.初识它时它叫C语言,浅尝却不觉其难过 ...

  6. 第11.8节 Python正则表达式的重复匹配模式及元字符“?”、 “*”、 “+”功能介绍

    符号"?".""."+"这三个元字符修饰符在Python中都表示重复匹配的模式,即要求匹配的字符串满足重复次数的要求,但具体重复次数要求不同 ...

  7. 问题: 刚安装的PyCharm执行代码报“ModuleNotFoundError: No module named XXXX”错

    老猿刚安装好PyCharm后,直接新建了一个工程文件并导入了一个已有的爬虫程序文件,该文件原来在Python解释器下能执行,但在PyCharm下执行时报错: F:\学习\python\SRC\proj ...

  8. CTF写脚本

    今天总结一下CTF如何写脚本快速得分....(比较菜,能力有限,大佬勿喷) 所谓的写脚本得分,就是利用了 python爬虫的思想,如果之前没有听说过的话,可以去爬虫的相关语法.如果是看网上的视频的话, ...

  9. IntelliJ IDEA2019.3.2破解/永久激活/安装教程

    我想大家用过史上最好的开发工具就是idea了,没有之一!看到大家都在找idea的激活教程,今天我也在这里跟大家分享一下. 本教程针对现在官网针对的版本是idea2019.3.2,为防止以后会更新破解失 ...

  10. 个人项目作业-Word Count

    个人项目作业 1.Github地址 https://github.com/CLSgGhost/SE_work 2.项目相关需求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数. ...