canvas烟雾效果学习
一、学习背景与效果
前些天翻大神blog,看到了张鑫旭大神写的一篇《canvas图形绘制之星空、噪点与烟雾效果》,深受启发。详细了研究了一下烟雾效果的代码,效果如下: 动态效果请点击。(!-- 去掉了原文中的背景图 --!)
效果图:
代码如下:
<!DOCTYPE html>
<html><head><title>canvas实现的烟雾缭绕效果</title><style>.smoke {height: 500px;background: #fff;background-size: cover;position: relative;}.smoke canvas {height: 100%;width: 100%;}</style>
</head><body><div id="main"><h1>canvas实现的烟雾缭绕效果实例页面</h1><div id="body" class="light"><div id="content" class="show"><h3>展示</h3><div class="smoke"><canvas id="smokeCanvas"></canvas></div></div></div></div><script>// canvas烟雾缭绕效果var canvasSmoke = function (canvas, options) {var defaults = {count: 30,velocity: 2,fps: 30,url: 'smoke.png'};options = options || {};// 参数合并var params = {};for (var key in defaults) {params[key] = options[key] || defaults[key];}// 创建存储粒子的数组var particles = [];// 渲染的粒子数目var particleCount = params.count;// 每个方向的最大速度var maxVelocity = params.velocity;// 每秒多少帧var targetFPS = params.fps;// canvas元素var eleCanvas = canvas;if (!eleCanvas) {return this;}// 画布的尺寸var canvasWidth = eleCanvas.clientWidth;var canvasHeight = eleCanvas.clientHeight;eleCanvas.width = canvasWidth;eleCanvas.height = canvasHeight;// 创建图片对象var imageObj = new Image();// 一旦图像被下载,然后在所有的颗粒上设置图像imageObj.onload = function () {particles.forEach(function (particle) {particle.setImage(imageObj);});};// 烟雾图片地址imageObj.src = params.url;// 粒子实例方法function Particle(context) {// 设置初始位置this.x = 0;this.y = 0;// 纵横速度this.xVelocity = 0;this.yVelocity = 0;// 圆角大小this.radius = 2;// 存储上下文,绘制的时候需要this.context = context;// 绘制粒子的具体方法this.draw = function () {// 如果图片,则绘制if (this.image) {this.context.globalAlpha = this.alpha;// 烟雾缭绕就看这里了// 这是宽度,是动态的var fillWidth = canvasWidth / 2,fillHeight = fillWidth - fillWidth * (this.x / canvasWidth * this.y / canvasHeight);this.context.drawImage(this.image, 0, 0, this.imageWidth, this.imageHeight, this.x, this.y, fillWidth,fillHeight);}};// 刷新粒子this.update = function () {// 改变粒子的this.x += this.xVelocity;this.y += this.yVelocity;// 如果到了右边缘if (this.x >= canvasWidth) {this.xVelocity = -this.xVelocity;this.x = canvasWidth;}// 检测是否到了左边缘else if (this.x <= 0) {this.xVelocity = -this.xVelocity;this.x = 0;}// 底边缘if (this.y >= canvasHeight) {this.yVelocity = -this.yVelocity;this.y = canvasHeight;}// 是否上边缘else if (this.y <= 0) {this.yVelocity = -this.yVelocity;this.y = 0;}// 越靠近边缘,透明度越低// 纵向透明度变化要比横向的明显this.alpha = (1 - Math.abs(canvasWidth * 0.5 - this.x) / canvasWidth) * (0.7 - Math.abs(canvasHeight *0.5 - this.y) / canvasHeight);};// 设置粒子位置方法this.setPosition = function (x, y) {this.x = x;this.y = y;};// 设置速度方法this.setVelocity = function (x, y) {this.xVelocity = x;this.yVelocity = y;};this.setImage = function (image) {this.imageWidth = image.width;this.imageHeight = image.height;this.image = image;}}// 生成一个min,max大小之间的随机数function generateRandom(min, max) {return Math.random() * (max - min) + min;}// canvas上下文var context;// 初始化常见function init() {var canvas = eleCanvas;if (canvas.getContext) {// 绘图都需要这条语句context = canvas.getContext('2d');// 创建粒子,并设置他们的位置什么的,当然都是随机的for (var i = 0; i < particleCount; ++i) {var particle = new Particle(context);// 随机位置particle.setPosition(generateRandom(0, canvasWidth), generateRandom(0, canvasHeight));// 设置随机速度particle.setVelocity(generateRandom(-maxVelocity, maxVelocity), generateRandom(-maxVelocity, maxVelocity));particles.push(particle);}}}// 初始化init();// 绘制方法function draw() {// 清除绘制//context.fillStyle = "rgba(0, 0, 0, 0)";context.clearRect(0, 0, canvasWidth, canvasHeight);// 绘制所有粒子particles.forEach(function (particle) {particle.draw();});}// 刷新function update() {particles.forEach(function (particle) {particle.update();});}// 开始绘制if (context) {setInterval(function () {// 绘制前先更新位置什么的update();// 绘制draw();}, 1000 / targetFPS);}};// IE9+烟雾效果走起if ([].map) {canvasSmoke(document.querySelector('#smokeCanvas'));}</script>
</body></html>
效果实现的好不好,关键的代码注释里面已经标出来了,就是这行:
fillHeight = fillWidth - fillWidth * (this.x / canvasWidth * this.y / canvasHeight);
大家进行试验的时候,可以试着修改一下fillHeight
的生成函数,产生的效果会很不同。为什么函数这样取值可以实现好的效果呢?
在坐标系中根据函数取点画图就可以明白,这个函数可以让烟雾图片的实例在面上更加连续的去展示。因为每个实例的取点都是伪随机的,所以很容易点都随机到一条线上,导致动画看起来不真实,即烟雾不是那么飘逸。按这个函数取值,可以大概率的保证烟雾实例的变化,在面上保证实例初始化后的连续性,让效果看着更加飘逸。
大神blog中的几个例子充分说明了,canvas绘图去实现动画效果好与差,与想象力紧密相关呀,数学具象化的能力很重要啊(努力提升中)。大家有时间可以多试试其他不同函数出现的效果,来加深影响。
canvas烟雾效果学习相关推荐
- html真实雾效果图,HTML5 Canvas逼真烟雾效果js插件解析
简要教程 smoke.js是一款基于HTML5 Canvas的逼真烟雾特效js插件.通过该js插件,可以非常轻松的在页面中制作出各种烟雾效果. 使用方法 在页面中引入smoke.js文件. HTML结 ...
- threejs fire 火焰与烟雾效果
在threejs中有一个为我们提供了可以实现火焰和烟雾效果的包,我们可以直接引用这个包,通过设置某些参数实现需要的效果. 第一步引入fire包,可在工程文件夹下的example文件夹中找到 <s ...
- html真实雾效果图,HTML5Canvas逼真烟雾效果js插件
简要教程 smoke.js是一款基于HTML5 Canvas的逼真烟雾特效js插件.通过该js插件,可以非常轻松的在页面中制作出各种烟雾效果. 使用方法 在页面中引入smoke.js文件. HTML结 ...
- 用vite命令搭个react移动端项目,实现canvas碰撞效果(按需导入antd-mobile,pxtorem适配)
前言 最近看见大家都在卷react源码,突然就心慌了.但是自己的操作水平还有待提高,现在看源码也需要循序渐进的,打算还是从写代码慢慢理解功能再去看源码.所以就尝试使用vite这个构建工具进行尝试构建一 ...
- 教你实现一个朴实的Canvas时钟效果
摘要:今天教大家写一个canvas的时钟案例,效果可能看起来比较简单,没有那些花里胡哨的. 本文分享自华为云社区<如何实现一个朴实无华的Canvas时钟效果>,作者: 北极光之夜.. 一. ...
- canvas下雪效果(原生js)
效果展示: 源码展示: <!doctype html> <html> <head><meta charset="utf-8">< ...
- 6 cocos2dx粒子效果,类图关系,系统原生粒子和自定义粒子效果,粒子编译器软件,爆炸粒子效果,烟花效果,火焰效果,流星效果,漩涡粒子效果,雪花效果,烟雾效果,太阳效果,下雨效果
1 粒子 示例 2 类图关系 3 系统原生粒子 CCParticleSystem 所有粒子系统的父类 CCParticleSystemPoint. CCParticleSystemQuad 点粒 ...
- 使用expression design制作silverlight LOGO那种烟雾效果教程(翻译)
很久没有给网站更新东西了,因为很忙,马上又要考四级了,多半又过不了.惨啊....因为英语的原因吧,就翻译了国外的一篇技术文章,这样即更新了网站又学了英语. 原文地址:http://geekswithb ...
- 真实烟雾效果PS笔刷
60 Real Smoke Photoshop Stamp Brushes是一套真实烟雾效果PS笔刷,包含60款不同效果的笔刷样式,内个画笔纹理都是高分辨率的,可与任何photoshop版本配合使用, ...
最新文章
- 2022-2028年中国汽车印制电路板(汽车PCB)产业深度调研及投资前景预测报告
- 【转】为什么有天线的路由器信号还不如没有天线的路由
- 我为什么更喜欢 Mac OS X
- webpack 入口文件 php,webpack,jsx_webpack jsx 找不到入口文件,webpack,jsx - phpStudy
- struct2 开发环境搭建 问题
- linux vlc流媒体服务器,vlc media server rtsp 流媒体服务器搭建成功经验分享
- linux网络编程之字节序
- AT91RM9200Linux移植笔记(三)-移植Linux kernel 2.6.17
- Github Pages建立个人博客
- For input string:
- Yaffs2根文件系统制作
- 爱奇艺、腾讯视频等接连涨价 地主家也没有余粮了?
- 九、注解、有助于更好的理解框架
- mysql查询员工表中所有员工入职20个月之后的日期_新员工入职指南
- 关于第三方支付,看这篇文章就够了!
- 使用内网开发微信公众号
- 每日10行代码82:网上购物活动满减凑单计算器
- 啤酒与尿布:数据分析相关性分析案例一
- 大数据技能修炼的个人道场
- 钱多多的程序猿的2020大计划
热门文章
- jdbc连接mysql工具类_jdbc之工具类DBUtil的使用
- python漂亮gui界面模板下载_Python GUI教程(十六):在PyQt5中美化和装扮图形界面...
- 智慧电子班牌系统源码,家校互联APP源码,SaaS云平台源码
- 如何把数字证书导入到Windows根证书存储区
- 百科词条创建:百科创建词条的规则及具体步骤!
- html5 css橡皮筋效果,阻止移动端浏览器下拉橡皮筋效果(下拉滚动露底)
- [杂想]浑浑噩噩度日
- mysql最大错误连接数_超过mysql最大连接的错误
- Android 升级提示 No space left on device
- 案例:Oracle报错ASM磁盘组不存在或没有mount