展示

想想坐在火车上回家的时候,窗外飞舞的雪花,一家人坐在一起吃年夜饭时,漫天飞舞的大雪,怎么样,雪花虽冷,随总是让我们感到一股暖意,自古也有瑞雪兆丰年一说,今天就带大家一起亲手来用代码下一场雪。

首先来看一下成品图,怎么样,还行吧,(因为gif录制原因,这是把屏幕放的比较小录制的)

实现

先来一个背景

首先来一个灰蒙蒙的背景,别问我为啥搞一个这样的背景(问就是这其实是我下一篇文章写的东西)

画一朵雪花

我们这里没有过于追求雪花的精细程度,所以就简单的弄了一个小圆点来模拟雪花,再来一个白色的阴影,给雪花一种朦胧感,是不是就有那么回事了。

生成雪花

上面的雪花我们是写死位置的,仅仅是为了先定义雪花的外形,下面我们就来模拟真实下雪的样子,随机的生成雪花,如果你看过之前的打年兽的文章,你肯定会与生成雪花用的方法了然于胸,没错,我们首先获取屏幕的宽度,然后定时的生成雪花,并给每一篇雪花一个随机的宽度,注意,这个宽度要在屏幕的宽度之内,否则我们下到屏幕外面也没啥意义啊,还浪费性能,之后我们给每一片雪花一个定时器,定时往下移动,然后就成了。

这里我们还用requestAnimationFrame,但是requestAnimationFrame没有定时功能,所以我们要记录最后一次生成雪花的时间,和当前时间对比,如果达到我们想要的间隔了,就创建下一片雪花

    lastSnowTime: '', // 最后一片雪花生成时间snowSpeed: 3, // 雪花下落的速度lastSnowTime: '', // 最后一片雪花生成时间snowFrequency: 4, // 雪花生成的频率snowStart () {// 雪花生成的频率let now = new Date().getTime()if (now - this.lastSnowTime > (1000 / this.snowFrequency)) {console.log(1);// 创建雪花let snowItem = document.createElement('div')snowItem.className = 'snow-item'snowItem.style.top = -snowItem.offsetWidth + 'px'snowItem.style.left = Math.random() * this.screenWidth  + 'px'this.$refs.snowWrap.appendChild(snowItem)// 雪花移动let snowMove = () => {snowItem.style.top = snowItem.offsetTop + this.snowSpeed + 'px'// 如果雪花距离屏幕顶部距离大于等于屏幕高度,则移除此雪花if (snowItem.offsetTop > this.screenHeight) {this.$refs.snowWrap.removeChild(snowItem)} else {requestAnimationFrame(snowMove)}}snowMove()this.lastSnowTime = now}this.createSnowInterval = requestAnimationFrame(this.snowStart)}

是不是有那么点意思了

优化雪花

虽然已经达到了我们的初步目的,但是这雪总看着有那么点假,为什么?因为大自然哪有这么规律的雪,一样大小,一样速度的,所以我们得来给他加入更多的随机性。

首先就是透明度,让每一篇雪花的透明度来一个随机值

snowItem.style.opacity = Math.random()

其次是大小,我们给每一片雪花一个随机的大小

snowItem.snowScale = Math.random() * 0.5 + 0.5
snowItem.style.width = snowItem.offsetWidth* snowItem.snowScale + 'px'
snowItem.style.height = snowItem.offsetHeight* snowItem.snowScale + 'px'

那么问题来了,大的雪花和小的雪花下落速度一样吗?我还真没仔细观察过,不过应该是不一样的吧,大的落的快,小的落的慢?所以这里我们让雪花的下落速度跟他的大小扯上关系,大家可以看到,我们上面给雪花随机大小的时候留了一个snowScale的东西,我们暂且称呼他为缩放系数,那么我们的下落速度就要跟这个缩放系数成正比

  let moveY = this.snowSpeed * snowItem.snowScalesnowItem.style.top = snowItem.offsetTop + moveY + 'px'

这里我们将纵向偏移量记下来,后面有用,现在再来看一下效果,每片雪花都会基于我们设定的基础大小和速度再增加一定的随机变化,是不是好多了。

这里有一个遗留的小问题啊,我们前面定义了一个snowFrequency变量,用来控制雪花的生成频率,乍一看好像没啥问题,但是如果我们在不同的设备上看就会发现,屏幕越大,雪花越稀疏,屏幕越小,雪花越密集,这肯定不对啊,所以这个频率我们要让它随着屏幕的变化而变化,并且同时还要我们可以控制。那么我们就可以设定一个变量,加入它是200,就代表1秒时间,每200像素的区域生成一片雪花,这样屏幕越大,一秒钟生成的雪花越多,屏幕越小,生成的雪花也就越少我也不知道咋称呼,咱们暂且称之为区域密度,我们拿屏幕宽度除以这个区域密度,就得出了最终的雪花生成频率。

  snowFrequencyRatio: 300, // 雪花频率系数,越大雪花越少mounted () {// 根据雪花频率系数和屏幕宽度计算雪花生成的频率this.snowFrequency = Math.floor(this.screenWidth/ this.snowFrequencyRatio)this.createCity()this.snowStart()},

来点风吧

既然是飘舞的雪花,一直垂直降落多没意思啊,不如我们来点风,让它飘起来。

思路分析,既然来电风,那肯定就是让雪花横向移动,那移动多少呢?我们最开始给雪花下落的速度给了一个定值,按照这个想法来,我们给雪花横向的偏移量也来一个定值肯定没问题,但是现在的问题是我们雪花的下降速度是和基础下降速度、自身大小都有关的,我们再设一个横向的偏移距离,再让它也跟大小有关系这就太麻烦了,况且这个值设立多少全凭我们随意,太不严谨了。

那么你有没有什么好的办法呢?哈哈哈,这里我们想象一下雪花下落的样子(不考虑雪花曲线飞舞),考虑一下横向偏移量和纵向偏移量的关系,是不是一个Rt△(部分学渣同学是不是已经忘记这是啥了,没错,这就是直角三角形)

这里∠α是我们设置的偏移量,a就是垂直方向的位移,这两个我们都知道了,那么利用正切公式,tanα = b / a,可以很轻易的算出b的值,也就是横向偏移量的值,在js中我们可以用Math.tan这个方法实现相关的功能,Math.tan方法接收一个弧度值,角度和弧度的转换公式是

弧度=角度∗Math.PI/180弧度 = 角度 * Math.PI / 180 弧度=角度∗Math.PI/180

所以这里我们横向的偏移量就是

let moveX = Math.tan(this.snowAngle * Math.PI / 180) * moveY
snowItem.style.left = snowItem.offsetLeft - moveX + 'px'

这样雪花横向移动的效果就出来了(学霸同学是不是很简单,学渣的我看了好半天的正切东西才迷糊过来)

看起来很美好,但是问题又来了,细心的同学会发现,右下角总是没有雪,那是因为现在雪的轨迹是这样的

我们在屏幕最右边生成的雪花,落到地上就不在最右边了,而是会偏移一个b的距离,那这个问题怎么解决呢,那就是在雪花生成的时候,就把这个b的距离给算进去,就像这样

那这个b怎么求呢?其实跟我们求雪花每一次移动的横向距离的方法是一样的,只不过我们这里的a是屏幕的高度罢了,所以我们生成雪花时给予的随机横向距离应该是这样的

// 在给雪花随机分配横向坐标时,范围应该把雪花的偏移量也算进去,否则屏幕右下角会出现空白
let _left = (this.screenWidth + Math.tan(this.snowAngle *
Math.PI / 180) * this.screenHeight) * Math.random()
snowItem.style.left = _left  + 'px'

这样就没啥问题了,不过这样子会有一定的性能问题,就是我们会多生成很多的雪花,就像图中那样,橙色区域的雪花虽然我们看不到,但是他们都在运动,并且消耗着性能,同时存在的雪花数量越多,性能损耗就越严重

右边的雪花我不知道怎么优化,但是左边的,我们可以加一个判断,当雪花超出左侧屏幕时,将其移除即可。

// 如果雪花偏移角度大于0,则判断雪花是否超出左侧屏幕if (this.snowAngle > 0) {if (snowItem.offsetLeft < (-snowItem.offsetWidth)) {this.$refs.snowWrap.removeChild(snowItem)return}}

好了,本篇文章到这里就结束了,相应的完整代码都会在我下一篇文章诞生的时候贴出来哦(希望能够顺产吧),本人文化水平较低,技术有限,大家如果有什么建议或者指正,欢迎评论区留言

冬天已经过去,春天马上来临,让我用代码再给你下最后一场雪相关推荐

  1. 《少年维特之烦恼》经典语录:残冬行将消失,春天恍若来临。

    作品简介 <少年维特的烦恼>(Die Leiden des jungen Werther)是德国作家歌德创作的中篇小说.小说描写进步青年对当时鄙陋的德国社会的体验和感受,表现了作者对封建道 ...

  2. 2月10日,北京下雪了,今年冬天第一场雪

    早晨起来下雪了,2011年的第一场雪, 今年冬天的第一场雪. 雪非常大,出来的时候一直在下. 地面厚厚的一层. 空气里充满了湿润的气息,有股泥土的味道. 很舒服,久违了的空气. 忘记开窗换气了,真傻. ...

  3. 2019年,P2P的春天会来临吗?

    文|木宇 来源|螳螂财经(原潇湘财经) 2018年过去了,互金行业并不怀念它,从业者们更关心的是,今年会更好吗? 去年P2P的爆雷潮,让互金行业遭遇巨大的信任危机:平台备案没有如期完成,更是为其蒙上了 ...

  4. 冬天到了,分享两款雪花特效代码

    冬天到了,或者圣诞节到了,很多网站会用到雪花特效, 今天我就分享两款觉得比较好的雪花js特效代码给大家, 当然不是小弟原创的,得感谢原创作者的无私奉献 一.下雪特效代码① 该特效的雪花是有雪花的八角形 ...

  5. 雪在第一天的冒险 - 2014 在冬天的第一场雪立场坚定?

    冰雪第一天历险 - 2014 年的冬天第一场站得住的雪? 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致" ...

  6. 雪球python爬虫炒股_雪作文-第一场雪作文、冬天的雪作文

    在生活.工作和学习中,大家都写过作文,肯定对各类作文都很熟悉吧,作文是人们以书面形式表情达意的言语活动.相信许多人会觉得作文很难写吧,下面是小编为大家收集的小学写雪作文700字10篇,欢迎大家借鉴与参 ...

  7. 大春天的,兰州竟然下了一场大雪!

    2008-04-21 11:12 兰州昨天晚上竟下了一场大雪.前两天,温度还挺高的,昨天整个兰州城还在飘柳絮. 这兰州温度变的还真快,说变就变.

  8. 天冷了,有冬天的味道了!

    该穿厚衣服了,记得大一的十月一假期还下了一场雪.今年节气晚,估计也快下了...,冬天就要到了

  9. 喾哲~ (八月最佳)

    <目录> 数学的起源 大数定律: 贝叶斯概率: 傅立叶变换: 哈夫曼编码: 最大熵原理: 幸存者偏差: 丑小鸭定理: 阿姆达尔法则: 马尔可夫模型: 学者存在性定理: 奥卡姆剃刀法则: 柯 ...

最新文章

  1. python+soket实现UDP协议的局域网广播程序
  2. xpath的数据和节点类型以及XPath中节点匹配的基本方法
  3. 谷歌技术主管:当我们选择工作时,什么最重要?
  4. php 8 jit,PHP8正式版发布,带来了注解和JIT
  5. 苹果错误分析报告preferreuserinterface_数据分析的六个步骤,你做到了吗?
  6. python none_None关键字,带Python示例
  7. Page_Load的问题
  8. 华为公开“一种芯片堆叠封装及终端设备”专利
  9. Operating System-进程间互斥的方案-保证同一时间只有一个进程进入临界区(3)- TSL指令...
  10. 数据库操作语句类型(DQL、DML、DDL、DCL)简介
  11. 详解单例模式线程安全
  12. 74HC595在【8x8LED点阵】中的运用
  13. 解密360黑幕:离职奇虎360老员工的告白
  14. 东芝打印机共享怎么设置_东芝 e-studio181怎么设置网络打印机
  15. 解决the application was unable to start correctly(0x000007b)与 缺少VCRUNTIME140.dll
  16. 一道被前端忽略的基础题,不信看你会几题
  17. 如何在Ubuntu下使用全民wifi?
  18. 创意示范:苹果如何使用无线充电技术
  19. HarmonyOS IoT首著,走进万物互联的世界!(附送书)
  20. 读书笔记(三)--世界上最伟大的推销员

热门文章

  1. vue 生命周期 详解
  2. Exchange Server 2010 邮件发送延迟排错
  3. HNOI2011 数学作业
  4. 金山pdf独立版右键菜单
  5. Linux常用命令,vi编辑器命令,Linux软件安装
  6. 为什么有的站点别人能访问但我无法访问
  7. printf的应用脚本
  8. 计算机电缆设计规范,DJYPVP计算机电缆安装规范和设计原则
  9. Revit教程免费下载——Revit建筑施工图高级视频课程
  10. 1.鸡兔同笼(POJ3237)