🐇年新春,快来领取你的春节全屏动效🌈

🐇年新春,快来领取你的春节全屏动效🌈

🐇年新春,快来领取你的春节全屏动效吧🌈

我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

这算是我的第一篇技术文吧,有什么不对的地方请及时指正,鸣谢。

效果

所有言语都过于苍白,效果直达车(github),进不去github的话点这个👉 码上掘金链接
代码已开源,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())
复制代码

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

初版.jpeg

优化

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

问题

  • 拖动改变浏览器大小时,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;
    }
}
复制代码

移动端.jpeg

码上掘金

这是第一篇技术文,也是正式踏上开源路上的开始。万事开头难,我的第一步足足用了两年。

余音

新春将至,祝大家幸福安康,阖家团圆,把酒言欢!欢迎大家一键三连~🙏🙏🙏

分类:
前端
标签: