国庆假期将至,做个倒计时动效玩玩吧

496 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

马上就要国庆节了,这是祖国母亲的第73个生日。为了迎接这一盛大节日,程序猿们必须整点活来迎接才行,刚刚在刷碗的时候突发奇想,决定做个国庆倒计时的动效,话不多说,直接开干!

简单布局页面内容

 <div class="container">
    <div class="tip1">现在是北京时间</div>
    <div class="datetime">2022-09-30 21:36</div>
    <div class="tip2">距国庆假期开始还有</div>
    <div class="time">02:23:20</div>
</div>

1664545065878.jpg

加上简单的js逻辑

const datetime = document.querySelector('.datetime');
const time = document.querySelector('.time');
const timeZoneOffset = new Date().getTimezoneOffset(); // 时差
const render = () => {
    datetime.innerHTML = moment().format('YYYY-MM-DD HH:mm');
    time.innerHTML = moment(moment('2022-10-01') - moment(new Date()) + timeZoneOffset * 60 * 1000).format('HH:mm:ss');
}
render();
setInterval(() => {
    render();
}, 1000);

demo112.gif

整活儿~

如果这就结束了,那就没有任何意思了,咱们今天必须整出点东西来,把倒计时做出新的高度!以下动画都是借助gsap实现,感兴趣的小伙伴可以去官网学习学习,真的很香~

给倒计时加上动画

由于要单独控制每个数字,所以必须分开写

 <div class="time">
    <div class="h1">0</div>
    <div class="h2">1</div>
    :
    <div class="m1">5</div>
    <div class="m2">7</div>
    :
    <div class="s1">4</div>
    <div class="s2">2</div>
</div>

由小变大效果

const datetime = document.querySelector('.datetime');
const timeZoneOffset = new Date().getTimezoneOffset();
const time = {};
const render = () => {
    datetime.innerHTML = moment().format('YYYY-MM-DD HH:mm');
    const timeStr = moment(moment('2022-10-01') - moment(new Date()) + timeZoneOffset * 60 * 1000).format('HHmmss');
    const animate1 = {
        duration: 1,
        scale: 0,
        opacity: 0,
        ease: 'back'
    }
    timeStr.split('').forEach((x, i) => {
        time[`t${i + 1}`] = document.querySelector(`.t${i + 1}`);
        if (time[`t${i + 1}`].innerHTML !== timeStr[i]) {
            gsap.from(time[`t${i + 1}`], animate1);
        }
        time[`t${i + 1}`].innerHTML = timeStr[i];
    })
}
render();
setInterval(() => {
    render();
}, 1000);

代码主要逻辑就是当当前对应时间的数字跟我返回的时间不一致的时候唤起动画,最主要逻辑在那个if语句。其他都很简单。缓动函数用back让其有往回收的的感觉 demo11221.gif

由下到上顶

我们将动画配置换成下面这样:

const animate2 = {
    duration: 1,
    y: 60,
    opacity: 0
}
timeStr.split('').forEach((x, i) => {
    time[`t${i + 1}`] = document.querySelector(`.t${i + 1}`);
    if (time[`t${i + 1}`].innerHTML !== timeStr[i]) {
        gsap.from(time[`t${i + 1}`], animate2);
    }
    time[`t${i + 1}`].innerHTML = timeStr[i];
})

demo1122122.gif

这个效果其实不咋地!为啥?因为没有数字顶数字那种效果,我们应该保留原先的数字,让最新的数字顶走原先的数字。安排!

由于需要额外的数字让我们顶上去,所以我们的html结构要变:

<div class="time">
    <div class="t1">
        <div class="num"></div>
        <div class="copy"></div>
    </div>
    <div class="t2">
        <div class="copy"></div>
        <div class="num"></div>
    </div>
    :
    <div class="t3">
        <div class="copy"></div>
        <div class="num"></div>
    </div>
    <div class="t4">
        <div class="copy"></div>
        <div class="num"></div>
    </div>
    :
    <div class="t5">
        <div class="copy"></div>
        <div class="num"></div>
    </div>
    <div class="t6">
        <div class="copy"></div>
        <div class="num"></div>
    </div>
</div>
.time {
    font-size: 60px;
    line-height: 60px;
    display: flex;
}

.t1,
.t2,
.t3,
.t4,
.t5,
.t6 {
    position: relative;
    height: 60px;
    overflow: hidden;
}

.copy {
    position: absolute;
    top: -60px;
}

我们的js代码仅仅是加了个copy的逻辑:

const animate2 = {
    duration: 1,
    y: 60,
    opacity: 0
}
timeStr.split('').forEach((x, i) => {
    time[`t${i + 1}num`] = document.querySelector(`.t${i + 1}`).querySelector('.num');
    time[`t${i + 1}copy`] = document.querySelector(`.t${i + 1}`).querySelector('.copy');
    time[`t${i + 1}copy`].innerHTML = time[`t${i + 1}num`].innerHTML;
    if (time[`t${i + 1}num`].innerHTML !== timeStr[i]) {
        gsap.from(time[`t${i + 1}copy`], animate2);
        gsap.from(time[`t${i + 1}num`], animate2);
    }
    time[`t${i + 1}num`].innerHTML = timeStr[i];
})

最终效果如下:

demo112212222.gif

10月1日更新

由于国庆已来,倒计时就不存在了,咱们开始正计时,国庆已过xx小时xx分xx秒:(另外将定时器换成requestAnimationFrame来执行,性能更加)完整代码看下面码上掘金👇👇👇

码上掘金自己动手试试吧

code.juejin.cn/pen/7149193…

最后祝大家国庆节玩得开心!