c语⾔下雪的动画代码_「实战解析」别⼈⽹页上的下雪效果
前⾔
⼥朋友常逛的设计⽹站这两天页⾯上多了下雪的效果,于是问我我的⽹站能下雪吗,作为⼀个程序员我⼀般会说实现不了,但是作为男朋
友,不能说不⾏。
雪
雪我们可以使⽤span标签和css的径向渐变简单意思⼀下:
.snow { display: block; width: 100px; height: 100px; background-image: radial-gradient(#fff 0%, rgba(255, 255, 255, 0) 60%); border-radius: 50%;}复制代码
效果如下:
很多雪
⼀⽚雪是不够的,成千上万才浪漫,世界上没有两⽚相同的雪花,所以每⽚雪都有⾃⼰的⼤⼩位置速度等属性,为此先创建⼀个雪花类:
class Snow { constructor (opt = {}) { // 元素 this.el = null // 直径 this.width = 0 // 最⼤直径 this.maxWidth = opt.maxWidth || 80 // 最⼩直径 this.minWi init⽅法⽤来⽣成随机的初始⼤⼩、位置、速度等属性,在浏览器窗⼝内new100⽚试试:
let snowList = []for (let i = 0; i
效果如下:
动起来
雪动起来才能叫下雪,动起来很简单,不断改变x和y坐标就可以了,给snow类加个运动的⽅法:
class snow { move () { this.x += this.speed this.y += this.speed this.el.style.left = this.x + 'px' this.p = this.y + 'px' }}复制代码
接下来使⽤requestAnimationFrame不断刷新:
moveSnow () { questAnimationFrame(() => { snowList.forEach((item) => { ve() }) moveSnow() })}复制代码
效果如下,因为速度是正数,所以整体是往右斜的:
可以看到动起来了,但是出屏幕就不见了,所以雪是会消失得对吗?要让雪不停很简单,检测雪的位
置,如果超出屏幕了就让它回到顶部,
修改⼀下move⽅法:
move () { this.x += this.speed this.y += this.speed // 完全离开窗⼝就调⼀下初始化⽅法,另外还需要修改⼀下init⽅法,因为重新出现我们是希望它的y坐标为0或init (reset) { // ... this.width = Math.floor(Math.random() * this.maxWidth + this.minWidth) this.y = reset ? -this.width : Math.floor(Math.random() * this.w
这样就能源源不断地下雪了:
优化
1.⽔平速度
⽔平和垂直⽅向的速度是⼀样的,但是看起来有点太斜了,所以调整⼀下,把⽔平速度和垂直速度区分开来:
class Snow { constructor (opt = {}) { // ... // ⽔平速度 this.sx = 0 // 垂直速度 this.sy = 0 // ... } init (reset) { // ... this.sy = Math.random() * this.maxSp
2.左下⾓没有雪
因为整体向右倾斜,所以左下⾓⼤概率没有雪,这可以通过让雪随机出现在左侧来解决:
init (reset) { // ... this.x = Math.floor(Math.random() * (this.windowWidth - this.width)) this.y = Math.floor(Math.random() * (this.windowHeight - this.width))
3.眼前的雪
随机性的选择⼀点雪给它较⼤的体积、透明度和速度,然后再使⽤css3的3D透视效果,把它的z轴数值调⼤⼀点,这样的感觉就好像是在
眼前划过的⼀样:
复制代码
class Snow { constructor (opt = {}) { // ... // z轴数值 this.z = 0 // 快速划过的最⼤速度 this.quickMaxSpeed = opt.quickMaxSpeed || 10 // 快速划过的最⼩速
4.鹅⽑⼤雪
雪花嘛,轻如鹅⽑,鹅⽑是怎么飘的?是不是左右摆动的飘?那我们也可以选择⼀部分的雪花让它跟鹅⽑⼀样飘,左右摇摆很简单,速度⼀
会加⼀会减就可以了:
class Snow { constructor (opt = {}) { // ... // 是否左右摇摆 this.isSwing = false // 左右摇摆的步
长 this.stepSx = 0.03 // ... } // 随机初始化属性 init (reset)
除了上述这种⽅法,左右摇摆还有⼀种⽅式,就是使⽤正弦或余弦函数,因为它们的曲线翻转90度就是左右摇摆:
img
我们使⽤正弦函数,公式为:y=sin(x),x的值是弧度表⽰,只要⼀直增加就可以了,y的值⽤来修改雪花的⽔平⽅向的速度变化步长:
class Snow { constructor (opt = {}) { // ... // 是否左右摇摆 this.isSwing = false // 左右摇摆的正弦函数x变量 this.swingRadian = 0 // 左右摇摆的正弦x步长
因为正弦函数y的值是从1变化到-1,摆动幅度太了,所以乘了个⼩数0.2缩⼩⼀点,想要幅度⼩⼀点,还有⼀个⽅法是不要使⽤整个正弦曲
canvas动画线,可以从中截取⼀个适合的区间⼤⼩,⽐如就让x的值在0.9π到1.1π之前变化:
class Snow { constructor (opt = {}) { // ... // 是否左右摇摆 this.isSwing = false // 左右摇摆的正弦函数x变量 this.swingRadian = 1// 需要改成⼀个中间值 //
5.下得慢⼀点
既然给⽔平加了曲线,垂直⽅向上是不是也可以改成⾮匀速呢?当然可以,区别是速度得⼀直是正的,不然就要出现反⾃然现象了,改变速
度曲线同样可以使⽤正余弦,上⾯我们使⽤了0.9π到1.1π之间的正弦曲线,根据上图可以发现对应的余弦曲线都是负的,趋势是先慢后
快,所以可以利⽤这⼀段来改变垂直⽅向的速度:
move () { if (this.isSwing) { if (this.swingRadian > 1.1 || this.swingRadian
6.在最上⾯
为了防⽌为页⾯上原本层级更⾼的元素遮挡,给雪花的样式加⼀个很⼤的层级:
render () { this.el = ateElement('div') this.el.style.cssText = ` // ... z-index: 9999999999999; ` document.body.appendChild(th复
7.看不见我
修改了层级,所以雪花会在页⾯的最上层,那么可能会挡住其他元素的⿏标事件,需要禁⽌它响应⿏
标事件:
render () { this.el = ateElement('div') this.el.style.cssText = ` // ... pointer-events: none; ` document.body.appendChild(this.el) }复制代码
8.更好⼀点
使⽤性能更好的transform属性来做动画:
render () { this.el = ateElement('div') this.el.style.cssText = ` left: 0; top: 0; transform: translate(${this.x}px, ${this.y}px); `
move () { // ... // this.el.style.left = this.x + 'px' // this.p = this.y + 'px' this.ansform = `translate(${this.x}px, ${this.y}px)`}复制代码
当然,最好的⽅式是⽤canvas来画。
最终效果:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论