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. window安装elasticsearch和kibana

    本次测试安装5.1.1版本 es下载地址:https://www.elastic.co/downloads/past-releases/elasticsearch-5-1-1 选择zip kibana ...

  2. 接入twitter第三方登陆接口遇到的一个问题

    本地开了 Shadowsocks,然后postman模拟的twitter的接口是请求成功的,然后用php-curl去请求网址,出现以下错误 Failed to connect to api.twitt ...

  3. leetcode116. 填充每个节点的下一个右侧指针

    给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点.二叉树定义如下:struct Node {  int val;  Node *left;  Node *right;  Node ...

  4. Java基础教程——打印流

    打印流 打印流可以把原本输出到控制台的信息输出到文件中.PrintStream是字节打印流(还有个对应的字符打印流是PrintWriter,这里不涉及) System类中有个变量: public fi ...

  5. LaTex中的中文处理方法

    相关代码与注释: 显示效果:

  6. Redis分布式锁—Redisson+RLock可重入锁实现篇

    前言 平时的工作中,由于生产环境中的项目是需要部署在多台服务器中的,所以经常会面临解决分布式场景下数据一致性的问题,那么就需要引入分布式锁来解决这一问题. 针对分布式锁的实现,目前比较常用的就如下几种 ...

  7. 老猿学5G:多量纲计费与QoS的QCI、5QI、ARP、GBR和MBR

    ☞ ░ 前往老猿Python博文目录 ░ 一.多量纲计费 多量纲计费是与传统的计费模式相区别的一种计费模式,传统的计费基本上都是通过使用量.使用时长或包固定时长等方式计费,而多量纲计费是指在考虑以上方 ...

  8. 关于open函数文件打开模式的有意思的一个现象

    老猿前阵子学习了文件IO,最近正在回顾及进行各种验证和总结,老猿在对文件进行打开后的返回值检查属性时,发现文件打开返回的文件对象的读写模式与打开文件的模式并不完全相同,如下案例: fp1 = open ...

  9. Asp.NetCore之AutoMapper进阶篇

    应用场景 在上一篇文章--Asp.NetCore之AutoMapper基础篇中我们简单介绍了一些AutoMapper的基础用法以及如何在.NetCore中实现快速开发.我相信用过AutoMapper实 ...

  10. 冰点文库下载器 v3.2.12(0314) 去广告单文件

    冰点文库,免积分免登陆文档下载神器!付费文档免费下载工具.百度文库免费下载工具.        冰点文库下载器,免费下载文档工具,无需积分也无需登陆就能自由下载百度文库.豆丁网.丁香网.电器网.MBA ...