js+css实现全屏表情掉落动画效果

js+css实现全屏表情掉落动画效果🌈

效果

效果

所有言语都过于苍白,效果直达车

代码已开源,github地址~。如果喜欢这个全屏效果请动动小手点个star⭐,谢谢!

构想

先选一张春节图片

body {
    position: relative;
    width: 100%;
    height: 100vh;
    background: url("../img/bg.png") center no-repeat;
    background-size: cover;
    overflow: hidden;
}

思来想去,决定用emoji,选用了几个有关兔年和春节的小表情。因为是兔年,我也属兔,多加几个小🐇不过分吧~

const emoteList = ['🐰', '🐇', '🧨', '🎉', '🐇', '🏮', '🐰', '💰', '⛄', '🐇', '❄', '🧧']

使用了jquery,因为用到了动画队列。

动画步骤

动画分为三个阶段

  • 从顶部移动到屏幕底部
  • 表情缩放
  • 表情消失

代码

获取视窗可视区域

const innerW = window.innerWidth
const innerH = window.innerHeight

创建表情标签

随机表情大小、位置、透明度、文字阴影以及过渡效果我是吃“随机”长大的吗

在表情数组里随机表情,然后返回dom、随机初始信息。

/**
 * @function 生成随机表情元素
 * @returns {{emoteEl: HTMLDivElement, emoteParams: {left: number, top: number, opacity: number, fs: number, transitionDuration: number}}}
 */
const createEmoteElement = () => {
   const fs = 20 + Math.round(Math.random() * 16)
   const left = Math.round(Math.random() * ((innerW - (fs / 2)) - (fs / 2)))
   const top = -fs - 10
   const opacity = ((Math.random() * 16 + 84) / 100).toFixed(2) - 0
   const transitionDuration = 2000 + Math.round(Math.random() * 2000);

   const emoteEl = $('<div></div>').css({
      position: 'absolute',
      color: '#fff',
      top: `${ top }px`,
      left: `${ left }px`,
      fontSize: `${fs }px`,
      opacity: opacity,
      zIndex: 9999,
      textShadow: `0 0 ${ fs / 4 }px #ffffff80`,
      transition: `transform ${ transitionDuration }ms linear`
   }).html(emoteList[Math.round(Math.random() * (emoteList.length - 1))])

   return { emoteEl, emoteParams: { fs, left, top, opacity, transitionDuration } }
}

设置动画

  • 设置第一阶段动画位移的距离、时间(随机)
  • 设置第二阶段动画的缩放比例(随机)
  • 设置第三阶段动画小时时间(随机)
  • 动画结束后删除dom标签
const setEmoteAnimate = () => {
   const { emoteEl, emoteParams } = createEmoteElement()
   $('body').append(emoteEl)

   const endLeft = emoteParams.left + [-80, 80][Math.round(Math.random())]
   const endTop = innerH - emoteEl.height() + Math.round(Math.random() * 10)
   const moveDuration = innerH * 10 + Math.round(Math.random() * 4000);
   const endScale = 1.2 + ((Math.round(Math.random() * 4) / 10).toFixed(2) - 0);
   const hideDuration = 1200 + Math.round(Math.random() * 2000);

   emoteEl.animate({ left: `${ endLeft }px`, top: `${ endTop }px`, }, moveDuration, 'linear', () => {
      emoteEl.css({ transform: `scale(${ endScale })` })
         .animate({ opacity: 0 }, hideDuration, 'linear', () => (emoteEl.remove()))
   })
}

开始动画

const start = () => setInterval(() => setEmoteAnimate(), 320)

$(document).ready(() => start())

至此,全屏动画已经完成,看看效果。

初版

优化

动画虽然完成,但是还有一些问题需要优化

问题

  • 拖动改变浏览器大小时,innerW、innerH未及时校正,动画落点会有bug。
  • pc端表情应较大、数量应较多;移动端表情应较小,数量也应有所减少。
  • pc端背景图不适合移动端

解决问题

实时更新innerW、innerH

对更新频率做了节流。

let innerW, innerH

const setInnerSize = () => {
   innerW = window.innerWidth
   innerH = window.innerHeight
}

let num = 0
const start = () => setInterval(() => {
   if (num % 10 === 0) setInnerSize()
   num += 1
   setEmoteAnimate()
}, 320)

针对pc端、移动端适配

判断是pc端还是移动端

/**
 * @function JudgePC 判断是当前浏览器信息是否为pc
 * @return { Boolean } 返回是否是pc
 */
const JudgePC = () => {
   let userAgent
   if (window && window.navigator) {
      userAgent = window.navigator.userAgent;
   } else {
      return true;
   }

   const agents = ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPod', 'iPad'];
   for (let i = 0; i < agents.length; i++) {
      if (userAgent.indexOf(agents[i]) >= 0) return false;
   }
   return true;
};

const isPc = JudgePC()

对大小、偏移量、生成频率进行适配

const fsRange = isPc ? [20, 16] : [14, 6]
const fs = fsRange[0] + Math.round(Math.random() * fsRange[1])

const leftRange = isPc ? [-80, 80] : [-40, 40]
const endLeft = emoteParams.left + leftRange[Math.round(Math.random())]

let num = 0
const start = () => setInterval(() => {
   if (num % 6 === 0) {
      setInnerSize()
      isPc = JudgePC()
   }
   num += 1
   setEmoteAnimate()
}, isPc ? 320 : 540)

适配背景图

@media only screen and (max-width: 768px) {
    body {
        background: url("../img/bg-mobile.png") center no-repeat;
        background-size: cover;
    }
}

移动端

资源

该代码已上传至资源上 资源链接

余音

有什么建议可以评论哦,喜欢的话点赞收藏加关注哦~🙏🙏🙏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

采黎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值