兔年最可爱的3D时间显示器来了

3,714 阅读2分钟

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

马上新年了,先祝大家钱兔似锦、大展鸿兔。兔子不但是可爱又软萌的动物,而且还是吃货,家里的养兔兔的应该知道,一天可能要炫掉好几根胡萝卜哈。本篇结合3D的css知识做一个可爱的兔兔时间显示器,帮我看看满分5分,你给我做的兔子打几分?

Kapture 2023-01-17 at 17.32.38.gif

1、3D翻转效果

如何用两个面制造不断向上翻转的3D效果?首先要知道3d盒子旋转的中心点,如何布局使得旋转过程中盒子不会变形。

实际要得到的透视图效果图如下:

block和:before,:after三个面的宽度和高度相同,block的面在z=0位置,:before伪类面放置于z=width/2位置,:after伪类向下移动50%后沿x轴旋转-90度。使得3d正方体block的中心点(x,y,z)在(50%, 50%, 0)位置上。

布置好元素后,旋转block,并设置其父元素的透视值perspective。

// block的父元素
.wrapper {
    perspective: calc(var(--w) * 5); // 透视值越大,所看到的元素越小
    transform-style: preserve-3d;
}
.block {
    animation: rotate .5s linear 1;
    animation-fill-mode: forwards;
}

设置透视和不设置透视的区别:

  • 底部90度的面看到的效果不同,有透视看到的是梯形,无透视看到的是一条线
  • 透视后的元素大小随透视值的大小变化,与实际面的大小不同

最终效果如下:


2、时间更新

因为要更新下一秒、下一分、下一个小时、明天、下个月、明年这几个时间值,首先要获取到这几个值并渲染到:after这个面上,等待更新时候翻转。

时间计算:

const newTime = new Date();

const year = newTime.getFullYear(); // 今年

const month = newTime.getMonth() + 1; // 当月
const _month = month < 10 ? "0" + month : month; // 两位数展示
let nMonth = (month + 1) % 12; // 下个月
nMonth = nMonth < 10 ? "0" + nMonth : nMonth;

let day = newTime.getDate(); // 当天
day = day < 10 ? "0" + day : day;
let tomorrow = new Date(
  newTime.getTime() + 24 * 60 * 60 * 1000
).getDate(); // 明天
tomorrow = tomorrow < 10 ? "0" + tomorrow : tomorrow;

const hour = newTime.getHours(); // 当前小时
const _hour = hour < 10 ? "0" + hour : hour;
let nHour = (newTime.getHours() + 1) % 60; // 下一个小时
nHour = nHour < 10 ? "0" + nHour : nHour;

const minute = newTime.getMinutes(); // 当前分钟
const _minute = minute < 10 ? "0" + minute : minute; 
let nMinute = (newTime.getMinutes() + 1) % 60; // 下一分钟
nMinute = nMinute < 10 ? "0" + nMinute : nMinute;

const second = newTime.getSeconds(); // 当前秒钟
const _second = second < 10 ? "0" + second : second;
let nSecond = (newTime.getSeconds() + 1) % 60; // 下一秒钟
nSecond = nSecond < 10 ? "0" + nSecond : nSecond;

计算好之后如何更新到伪类中的content属性里面呢?在block上定义content-before和content-after两个属性,每次更新后修改这两个属性的值。

<div class="block" content-before="21" content-after="22"></div>
.block::before {
    content: attr(content-before);
    ...
}

.block::after {
    content: attr(content-after);
    ...
}

3、设计兔子拔萝卜的动画



几个动画要点:

  • 2023块元素往返旋转,兔子会跟着旋转
  • 兔子手和脚的旋转,手脚向下旋转制造用力的效果
  • 兔子耳朵跟随摆动旋转
  • 萝卜向左移动
  • 兔子眨眼睛