canvas实现粒子跟随鼠标动画



canvas是前端绘制图形的好帮手,不少大牛的博客也会精心的用canvas绘制炫酷的背景。图形与可视化界面就是前端最好的名片,泡妞之前尚且知道要梳个靓头精心打扮,而canvas就是你装点门面与大牛平齐,脱颖而出的绝佳神器。

文章目录

  • canvas实现粒子跟随鼠标动画
  • 前言
  • 一、从创建一个canvas元素开始
    • 第一步:初始化一个黑色幕布的canvas,定义类Draw
    • 第二步:创建绘制粒子的类,定义类Particle
    • 第三步:从创建一个Particle元素开始
  • 二、事件绑定产生粒子
  • 三、粒子渐变动效
  • 四、粒子渐变与事件结合
  • 总结

前言

  • 本文意指通过面相对象的方式更优雅的组织canvas相关代码,而不是讲解canvas相关的api

一、从创建一个canvas元素开始

我们假设页面中有一个canvas元素,我们通过一个类的实例来让其产生黑色的幕布以及鼠标滑过粒子的能力。

第一步:初始化一个黑色幕布的canvas,定义类Draw

const canvas = document.getElementById('canvas') as HTMLCanvasElement;class Draw {public ctx: CanvasRenderingContext2Dpublic r: numberconstructor(public canvas: HTMLCanvasElement) {this.canvas = canvas;this.ctx = canvas.getContext('2d')this.ctx.fillRect(0, 0, 300, 150) // 黑色填充}
}new Draw(canvas)

第二步:创建绘制粒子的类,定义类Particle

class Particle {public ctx: CanvasRenderingContext2Dconstructor(public x: number, public y: number) {this.x = x;this.y = y;}draw(ctx: CanvasRenderingContext2D, r: number) {if (r < 0) returnthis.ctx = ctxthis.r = rctx.fillStyle = "rgba(255,255,255, 1)";ctx.shadowBlur = r * 2 / 10;ctx.beginPath();ctx.arc(this.x, this.y, r, 0, 2 * Math.PI, false);ctx.closePath();ctx.fill();return this}}

这里我们定义了Particle类,其中x,y,r用于绘制粒子的坐标点位以及圆的半径,draw是绘制方法的实现,其内部运用了canva绘制圆形的方法不做讲解。

第三步:从创建一个Particle元素开始

现在Draw结合Particle在黑色幕布中绘制一个粒子,给Draw添加一个createCanvas方法

// In the Draw
createCanvas(x: number, y: number) {const particle = new Particle(x, y).draw(this.ctx, 5)}

createCanvas方法内生产了一个粒子,这里我们把Context2D传给了Particle对象,在Particle内部的draw方法内做具体的实现。这么做的好处在于我们不单单可以有Particle,也可以有Square,Triangle,每一个类的内部去做具体的实现。

// In the Drawconstructor(public canvas: HTMLCanvasElement) {/...和之前代码一样/this.createCanvas(50, 50)}createCanvas(x: number, y: number) {const particle = new Particle(x, y).draw(this.ctx, 5)return this}

简单看看效果,在幕布坐标50,50绘制一个半径为5粒子

二、事件绑定产生粒子

聪明如你应该可以想到,只要给canvas绑定鼠标事件,就能通过事件的坐标生产粒子

// In the Draw
constructor(public canvas: HTMLCanvasElement) {/...和之前代码一样/const throttleMousemove= throttle(this.handleMousemove.bind(this), 100)this.canvas.addEventListener('mousemove', throttleMousemove)}handleMousemove(event: MouseEvent) {const { offsetX, offsetY } = event;this.createCanvas(offsetX, offsetY)}

这里的throttle只是一个普通的节流函数
看看效果

事实上你也可以考虑通过判断鼠标的位置与上一次的坐标位置,达到一定的间距之后再产生粒子,这样就不用节流函数了,也不会因为鼠标滑动的速度滑动的快慢而产生间距不同粒子。

三、粒子渐变动效

何为渐变?
渐变是指一个值到另外一个值不断变化的过程,而这个值必然是数值。
回过头看第一张GIF,这里我们渐变的值是粒子的半径,以及颜色,其中颜色随半径的增大而变亮。
所以可以得出结论:Particle.draw()方法里的半径r是唯一需要变化的状态state,而颜色依赖这个state的变化计算即可。

// In the Particle
// 假设外部调用draw方法传入r值不断变化
// 新增public scaleFlagpublic scaleFlag: boolean = falsedraw(ctx: CanvasRenderingContext2D, r: number) {/..其他和之前代码一样/ctx.fillStyle = "rgba(255,255,255," + r / 10 + ")";ctx.shadowBlur = r * 2 / 10;ctx.arc(this.x, this.y, r, 0, 2 * Math.PI, false);}

scaleFlag辅助确认放大还是缩小
定义方法vitalityParticle用于渐变Particle

// In the Particle
vitalityParticle() {if (!this.scaleFlag) {this.r += 2} else {this.r -= 2}this.draw(this.ctx, this.r)if (this.r === 10) {this.scaleFlag = true}return this}

vitalityParticle方法不断修改r值以达到渐变的目的,让我们来演示一下

// In the Draw
constructor(public canvas: HTMLCanvasElement) {/...上面和之前的代码一样/const particle = this.createCanvas(50, 50).draw(this.ctx, 0)let setp = 10;const timer = setInterval(() => {this.ctx.clearRect(0, 0, 300, 150)this.ctx.fillStyle = '#000'this.ctx.fillRect(0, 0, 300, 150)particle.vitalityParticle()setp--if (setp === 0) {clearInterval(timer)}}, 200)}

在幕布坐标50,50创建了一个半径为0的粒子,通过定时器去改变它

四、粒子渐变与事件结合

现在通过定时器驱动以达到时间与运动的结合,上面的例子只是单个渐变,对于所有createCanvas产生的particle我们需要保存在数组中,通过迭代数组的方式运动其每个particle实例。

// In the Draw
public canvasArray: Particle[] = []
public setp: number = 10;
public timer: NodeJS.Timer | null = null;createCanvas(x: number, y: number) {const particle = new Particle(x, y).draw(this.ctx, 0);this.generator(particle)return particle}generator(particle: Particle) {this.canvasArray.push(particle)this.setp = 10if (this.timer) returnthis.timer = setInterval(() => {this.ctx.clearRect(0, 0, 300, 150)this.ctx.fillStyle = '#000'this.ctx.fillRect(0, 0, 300, 150)for (const particle of this.canvasArray) {particle.vitalityParticle()}this.setp--if (this.setp === 0) {clearInterval(this.timer)this.timer = null}}, 100)}

新增了generator方法,并将所有创建的particle实例都push到数组中,在定时器的每一次调度中迭代这个数组,执行每一个particle的vitalityParticle方法。


手速快的话还有可以有这种效果


总结

以上就是今天要讲的内容,本文仅仅简单介绍了canvas的使用,而canvas的实际开发过程需要开发人员灵巧设计实现,通过class或function封装调用。
一个优秀的开发往往还需要考虑内存占用的问题,比如上面的数组不断的push particle,数组越来越大是不是要考虑清除。另外如果通过shift清除数组中已完成运动周期的particle是不是就等于释放了内存也是我们要考虑的问题。

canvas实现粒子跟随鼠标动画相关推荐

  1. 粒子背景php,html5+canvas圆形粒子移动背景动画特效

    html5+canvas圆形粒子移动背景动画特效 this.update = function () { var lastPoint = { x: _this.x, y: _this.y }; // ...

  2. html5教程鼠标,利用HTML5 Canvas制作键盘及鼠标动画的实例分享

    键盘控制小球移动 众所周知,我们所看到的动画实际上就是一系列静态画面快速切换,从而让肉眼因视觉残像产生了「画面在活动」的视觉效果.明白了这一点后,在canvas上绘制动画效果就显得比较简单了.我们只需 ...

  3. 可爱的小幽灵跟随鼠标动画卡片式404页面源码

    简介: 一个卡片式的404页面,非常可爱的小幽灵一上一下飘动,眼睛会随着鼠标的移动而转动. 虽是幽灵,但没有一点恐怖的感觉,更多的只有可爱. 很多萝莉控一定会喜欢的. 这段时间一直坚持每天更新,喜欢的 ...

  4. html飞机动画,html5 canvas纸飞机跟随鼠标飞行动画

    这是一款效果很酷的html5 canvas纸飞机跟随鼠标飞行动画.插件中使用了paper.js来构建场景中的各种元素. HTML html结构只需要一个canvas,并给它一个id triangle- ...

  5. html动态跟随鼠标效果,使用JS实现气泡跟随鼠标移动的动画效果

    气泡跟随鼠标移动,并在每次点击时产生不同的变化 效果如下 简单的气泡效果 body{background-color:#000000;margin:0px;overflow:hidden} var c ...

  6. html5随鼠标移动动画,使用JS实现气泡跟随鼠标移动的动画效果

    气泡跟随鼠标移动,并在每次点击时产生不同的变化 效果如下 简单的气泡效果 body{background-color:#000000;margin:0px;overflow:hidden} var c ...

  7. html canvas粒子线条组合动画背景特效

    代码如下: <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF- ...

  8. html5动态效果随鼠标动,html5跟随鼠标移动银河星系背景动画特效

    特效描述:html5 跟随鼠标移动 银河星系 背景动画特效.html5银河星系背景动画,鼠标的移动.点击会发生相应的变化! 代码结构 1. HTML代码 流星雨 body {margin:0;padd ...

  9. Canvas跟随鼠标炫彩小球

    跟随鼠标炫彩小球 canvas没有让我失望,真的很有意思 实现效果 超级炫酷 实现原理 创建小球 给小球添加随机颜色,随机半径 鼠标移动通过实例化,新增小球 通过调用给原型新增的方法,来实现小球的动画 ...

最新文章

  1. 解惑:学.Net还是学Java?
  2. 成功解决raise XGBoostError(_LIB.XGBGetLastError()) xgboost.core.XGBoostError: b'[22:08:00] C:\\Users\\Ad
  3. LeetCode 904. 水果成篮(滑动窗口)
  4. css基础选择器 1204
  5. TikTok 已经成为影响力营销的新战场
  6. 在 Razor 中注册命名空间
  7. include查找文件路径
  8. 期末作业代码网页设计代码——花店购物网站源码(27页) 学生动花店购物页设计模板下载 植物大学生HTML网页制作作品 简单网页设计成品 dreamweaver学生网站模板
  9. 腾讯云超级播放器实现无直播占位图,有直播播放视频
  10. 2018年12月份计算机,CPU天梯图2018年12月最新版 十二月台式电脑CPU性能排行
  11. 医院预约挂号系统,java医院预约挂号系统,医院预约挂号管理系统毕业设计作品
  12. [JZOJ3385] [NOIP2013模拟] 黑魔法师之门 解题报告(并查集)
  13. 移动端图片居多,加载过慢,使用延迟加载|懒加载( lazyload.js)
  14. linux硬盘添加和挂载(linux硬盘的热插拔)
  15. Java中Number转为百分比
  16. java web聊天室论文_基于Java网页版聊天室的设计与实现毕业论文含开题报告及文献综述(样例3)...
  17. 1.2 引入不定度量空间的动机——有限时域H2/H∞滤波
  18. 选择结构——计算某年某月的天数
  19. SPA,什么是单页面应用,为什么要使用单页面应用,单页面应用有啥好处
  20. 系统集成项目管理工程师报考条件

热门文章

  1. 原画师一般用什么软件画画?
  2. 修复“裸露”的黑莓手机
  3. 作词:符如坤(2018.08.27)
  4. FireFox必备插件(一)
  5. 飞腾S2500平台PCIe SWITCH下热插拔验证
  6. input的几种禁用方法
  7. http状态码有哪些?代表什么意思?(查询手册而已)
  8. 2.CUDA 编程手册中文版---编程模型
  9. 中国广电剑未出鞘,但中国联通和中国电信已吓得瑟瑟发抖
  10. [java] 汇率换算器实现-插曲1-正则表达式(1)