学妹说她想看雪,我只能写下这个动画!!

简介: 大家好!我是Fly哥,最近做了很多粒子动画, 对canvas 实现粒子动画有了一点小感悟,前几天北方都下雪了, 身在魔都的我们, 一点点雪的影子都没有。而下雪动画作为粒子动画中我觉得算是比较简单的好理解, 先把这篇文章讲完,后面再去给大家讲 酷炫的 canvas 文字烟花动画。本篇文章大概阅读花费7分钟, 你可以学到如何去实现一个粒子动画,我觉得把思路学会了, 后面产品假设提出任何需求你都是可以cover 住的。废话不多说, 直接先看先看效果:图片snow看着是不是像辣么回事,哈哈哈哈, fly哥写的基础版,圣诞节快到了,你可以在我的基础上做下面👇🏻几个优化使用雪花贴图为每一

大家好!我是Fly哥,最近做了很多粒子动画, 对canvas 实现粒子动画有了一点小感悟,前几天北方都下雪了, 身在魔都的我们, 一点点雪的影子都没有。而下雪动画作为粒子动画中我觉得算是比较简单的好理解, 先把这篇文章讲完,后面再去给大家讲 酷炫的 canvas 文字烟花动画。本篇文章大概阅读花费7分钟, 你可以学到如何去实现一个粒子动画,我觉得把思路学会了, 后面产品假设提出任何需求你都是可以cover 住的。废话不多说, 直接先看先看效果:


640 (7).gif


snow


看着是不是像辣么回事,哈哈哈哈, fly哥写的基础版,圣诞节快到了,你可以在我的基础上做下面👇🏻几个优化


  1. 使用雪花贴图


  1. 为每一个粒子增加重力效果


  1. 性能优化的角度考虑下,考虑使用离屏canvas(数量比较多的情况下,可以去使用)



粒子动画



可能有的人到现在还不是很清楚啥是粒子动画:


粒子


粒子是什么?粒子是一种微小的物体,比如像我们周边环境中的雪花,火星等物体。因此在游戏中一般都用粒子特效来模拟咱们现实生活中的许多自然现象。


粒子系统


粒子系统是众多粒子的集合。一般具有具有粒子的更新,显示,销毁及其创建粒子等性质。不同的粒子系统具有不同的粒子行为,所以所具有的性质会略有区别。


综合


粒子动画其实很容易理解了,就是很多个粒子按照某个特定的运动轨迹组合起来的动画,所以做粒子类属性 会带有一些物理属性, 比如重力,风的阻力, 加速度。。。这些东西,其实主要为了更加贴近自然,更加真实。物理比较差的同学记得把物理知识补一下。


雪粒子


简单介绍上面的概念后,大家可以结合上面的动画简单分析一下,雪粒子这个类应该有哪些属性呢???


首先我的雪花粒子是用「ctx.arc」 去画的,所以呢??「肯定有 x 和 y 轴 坐标 ,还有 radius 半径」



这时候有同学开始抢答了?说fly哥,你上面提到了粒子的速度, 雪花肯定每一个下的速度不一样, 「肯定有一个 vx, vy」


哎呦不错哦, 现在已经5个属性了, 还有没有属性呢, 这时候有个细心的妹子站出来了, 我看到了透明度的变化,确实 还是妹子细心哇!!


image.gif小姐姐


大家在思考下, 还有没有什么属性呢?看着同学们鸦雀无声, 我给一个提醒, 如何保持雪一直下,难道我要不断添加粒子嘛, 有没有边界啥的??



有同学就说:不亏是fly哥,思考问题就是全面哇,哈哈哈哈其实这里涉及到 就一个属性 边界检测呗, 不过没辣么夸张, 「就是是一个最大距离 maxDistance」, 如果超过了 最大距离 我们就让它从一开始落呗, 不就实现了永动机的效果!


编码实现



理论说的都差不多了,我这里写的都是伪代码,本着 「授人以鱼不如授人以渔」 的目的, 你如果真的想学, 跟着我的思路做一篇肯定很没问题!


创建canvas


创建canvas 拿到canvas 的上下文 这个应该不用多讲了


const canvas = document.getElementById( 'canvas' );
  const ctx = canvas.getContext( '2d' );


创建snow 类


主要是每一个小的雪花粒子:


class Snow {
  dia: number
  fill: string
  vy: number
  vx: number
  z: number
  y: number
  x: number
  maxDistance: number
  width: number
  height: number
  constructor(width: number, height: number, maxDistance: number) {
    this.x = Math.random() * (width + maxDistance) - maxDistance / 2
    this.y = Math.random() * (height + maxDistance) - maxDistance / 2
    this.maxDistance = maxDistance
    this.width = width
    this.height = height
    this.z = Math.random() * 0.5 + 0.5
    this.vx = (Math.random() * 2 - 0.5) * this.z
    this.vy = (Math.random() * 1.5 + 1.5) * this.z
    this.fill = 'rgba(255,255,255,' + (0.5 * Math.random() + 0.5) + ')'
    this.dia = (Math.random() * 2.5 + 1.5) * this.z
  }
  draw(ctx: CanvasRenderingContext2D) {
    ctx.beginPath()
    ctx.strokeStyle = 'transparent'
    ctx.fillStyle = this.fill
    ctx.arc(this.x, this.y, this.dia, 0, 2 * Math.PI)
    ctx.closePath()
    ctx.stroke()
    ctx.fill()
    return this
  }
  update() {
    this.x += this.vx
    this.y += this.vy
    if (this.x > this.width + this.maxDistance / 2) {
      this.x = -(this.maxDistance / 2)
    } else if (this.x < -(this.maxDistance / 2)) {
      this.x = this.width + this.maxDistance / 2
    }
    if (this.y > this.height + this.maxDistance / 2) {
      this.y = -(this.maxDistance / 2)
    } else if (this.y < -(this.maxDistance / 2)) {
      this.y = this.height + this.maxDistance / 2
    }
  }
}


这里面 把上面的所说的属性 都讲到了, 其实无论你做任何粒子, 他都有一个创建 和 更新 ,因为你是做动画,


比如第一帧画面 是没有雪花粒子的, 所以第一帧 就是创建粒子,然后后面每一帧其实就是改变粒子的位置 就好了,不断重复这样的过程 配合 requestanimation  去实现。后面每一帧 就是更新 「update」 函数,


我这里还是解释下:粒子不断加 一个固定的速度 「vx vy」 ,然后做了边界判断 , 你可以自己去修改的。由于 有不同的粒子, 粒子的大小 透明度 、速度 都是不同的, 所以 使用了「random」


动画实现



动画实现 很简单 就两步骤


  1. 创建粒子


  1. 更新粒子


// 第一帧 创建1000 个
for (let i = 0; i < 1000; i++) {
  points.push(new Snow(100, 100, 100))
}
// 后面都是更新
 ctx.clearRect(0, 0, view.width, view.height)
 ctx.fillStyle = 'rgba(0,128,255,1)'
 ctx.fillRect(0, 0, view.width, view.height)
 // 调用每个粒子的更新 函数
 points.forEach((point) => {
    point.draw(ctx).update()
 })


相关文章
|
数据可视化 前端开发 小程序
中秋节——我给心爱的她做了一个3d月球动画
前言 大家好,又到了周末了,又到了Fly写文章的时候了, 过几天不是中秋节了,想着之前写过一篇从0- 1 实现3D地球的,反响效果特别好, 这次趁着🎑节给大家写了一个月球绕地球的运转的动画。本篇文章还是偏入门级别,重在把简单的知识讲清楚,如果是资深three爱好者,可以直接划走了,不浪费大家时间。ok👌言归正传,读完本篇文章你可以学到什么?至于心爱的她—— 就是学习 本文阅读估计花费 5 分钟 天空盒子的制作 three.js 中的贴图 一个物体绕另一个物体旋转 初始化 这篇文章我不会在从头详细的介绍three.js 的一些要素了,如果小伙伴你不是很清楚的话,你可以直接看下我这篇文章入
中秋节——我给心爱的她做了一个3d月球动画
|
前端开发 JavaScript
#yyds干货盘点# 前端歌谣的刷题之路-第一百题-控制动画
#yyds干货盘点# 前端歌谣的刷题之路-第一百题-控制动画
110 0
#yyds干货盘点# 前端歌谣的刷题之路-第一百题-控制动画
【代码分享】【像极了恋爱】甜甜的汤圆,祝丽姿元宵快乐(表白特效)
【代码分享】【像极了恋爱】甜甜的汤圆,祝丽姿元宵快乐(表白特效)
172 0
|
7月前
|
前端开发 JavaScript
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
HTML+CSS如何打造撒花动画效果?3分钟学会,炫酷到爆!
|
图形学
Unity小游戏——使被砍中的怪物四处飞散
Unity小游戏——使被砍中的怪物四处飞散
119 1
|
数据挖掘 开发者
关于泡泡龙游戏的一点儿总结,以及分享一个好方法
游戏是一种虚拟的产品,它很难被量化,也很难像工厂流水线生产实体产品一样的去生产。因为其中涉及到的情况太多太杂,如何衡量一个游戏的体量?怎样的游戏算是大游戏,怎样的游戏算是小游戏呢?如何判断一个游戏是做完了还是没有做完呢?如何衡量一个游戏开发者的水平呢?……等等等等。这里面的每一个因素都是一个变量,这么多的无法确定的变量合在一起,想要得到一个确定的结果,很显然是不太可能的。
189 0
|
前端开发 容器 流计算
如何用纯 CSS 创作一只徘徊的果冻怪兽
效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。 https://codepen.io/comehope/pen/VdOKQG 可交互视频 此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。
912 0
逐帧动画案例(奔跑的小人)
逐帧动画案例(奔跑的小人)
269 0
逐帧动画案例(奔跑的小人)
|
前端开发 JavaScript 程序员
2023将至,前端程序员们应该一起放个烟花庆祝一下,走起
前言:小时候,在我印象中,每到快过年的时候就有很多卖炮仗的,一般也就是阳历的12月份到明年的正月15号卖炮仗的商家比较多,省下买辣条的钱去买炮仗,在老家也就过年和除夕两天及正月15日这几天放烟花和炮仗比较猛,现在年纪大了,听不得炮仗那种噪声了,也考虑到环保,工作之后的程序员以代码的形式演绎一下烟花的效果。
319 0
2023将至,前端程序员们应该一起放个烟花庆祝一下,走起