本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。
介绍
本期给大家介绍一个十分实用的动画库——anime.js,它拥有简单而强大的API。可对 CSS 属性、 SVG、 DOM 和JavaScript 对象进行动画。它可是法国大神Julian Garnier的佳作。
当然,如果不试试写写,我们很难了解的他是多么的出色。所以今天我们就特地用它来完成一个龙珠里战斗力探测器的动画效果。
我们在这个案例中我们并没有使用任何css动画,而是全是用anime.js去实现的。还挺有意思的,接下来,我们就来实现他。
正文
我们先拆解一下分解这个动画:
- 圆环加载动画
- 战力上升动画
- 指针动画
- 柱状数据动画
不难看出,我们整个战斗力探测动画,是由这四个小动画来组成的。所以,后面我们只针对这四个动画进行讲解。
1.基础结构
我们先用vite搭建,然后使用module模式方便模块引入。
<div id="app">
<div class="hero">
<div class="detector">
<!-- 圆环加载 -->
<div class="wait">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="content">
<!-- 战斗力 -->
<h5 class="power">5</h5>
<!-- 指针 -->
<div class="pointer"></div>
<!-- 柱状数据 -->
<ul class="chart">
<li style="--i:0;--w:50px;"></li>
<li style="--i:1;--w:20px;"></li>
<li style="--i:2;--w:40px;"></li>
<li style="--i:3;--w:80px;"></li>
<li style="--i:4;--w:70px;"></li>
</ul>
</div>
</div>
</div>
</div>
<script type="module" src="./app.js"></script>
这里先写好相关动画结构。再写css。这些样式过于简单又不是本次的重点就不再赘述,直接上代码。
html,body,#app {
width: 100%;
height: 100vh;
overflow: hidden;
background-color: #000;
display: flex;
align-items: center;
justify-content: center;
}
.hero {
position: absolute;
max-width: 597px;
width: 100%;
height: 352px;
background: url("./image/hero.jpeg") center no-repeat;
background-size: cover;
cursor: pointer;
}
.detector {
position: relative;
width: 100%;
height: 100%;
background: rgba(116, 250, 116, 0.5);
}
.pointer {
width: 0;
height: 0;
position: absolute;
border-width: 25px 20px;
left: calc(100% / 2 - 20px);
bottom: 5%;
border-style: solid;
border-color: transparent transparent rgb(255, 205, 66, .9) transparent;
}
.power {
position: absolute;
text-align: center;
font-size: 2.7em;
color: rgb(255, 205, 66, .9);
box-sizing: border-box;
font-family: fantasy, serif;
padding: .3em .5em;
font-weight: bold;
letter-spacing: .07em;
}
.chart {
position: absolute;
right: 20px;
top: 5%;
}
.chart>li {
position: absolute;
top: calc(var(--i) * 22px);
right: 0;
height: 12px;
background-color: rgb(255, 205, 66, .7);
width: var(--w);
}
.wait>div {
border: 2px solid rgb(255, 205, 66, .7);
border-radius: 50%;
position: absolute;
left: 50%;
top: 50%;
box-shadow: 0 0 10px rgb(255, 205, 66, .4);
width: 100px;
height: 100px;
margin-left: -50px;
margin-top: -50px;
}
写完这里,我们具体的界面样式就出来了,接下来就想办法让他动起来~
2.如何使用animejs
我们要想使用先要进行安装
npm install animejs
// 或者
yarn add animejs
然后在主逻辑中引入
/* app.js */
import anime from "animejs";
; (function () {
let $detector = document.querySelector(".detector")
let $content = $detector.querySelector(".content")
$detector.style.display = $content.style.display = "none";
document.querySelector(".hero").addEventListener("click", openDetector, false)
function openDetector() {
// 打开战力探测器
$detector.style.display = "block";
document.querySelector(".hero").removeEventListener("click", openDetector)
// ...
}
function playAnime() {
// 探测数据动画
}
})();
我们先写一下大致的流程,就是一开始将所有的样式全部隐藏起来,当点击界面后,再触发openDetector开启
战力探测器,依次播放圆环加载,战力变化等动画。
3. 圆环加载
我们现在正式开始要使用anime了~
let waitAnime = anime({
targets: '.wait div', // .wait下有五个div圆环
scale: [0, 2], // 缩放大小从0到2
opacity: [1, 0], // 透明度从1到1
loop: true, // 循环播放
easing: 'easeOutCirc', // 时间曲线
duration: 1000, // 播放时间1s
autoplay: false, // 是否立即播放
delay: anime.stagger(300), // 每间隔300ms让下一个元素播放
});
通过上面的注释,可以看出anime是可以设置多个对象操作。可以设置css属性的变化量与时间曲线。是否立即播放,是否循环播放,甚至可以使用函数在里面。可谓是非常强大,后面的可以查anime api文档那里有更详细的描述。
function openDetector() {
// ...
waitAnime.play();
setTimeout(() => {
waitAnime.pause();
waitAnime.reset();
playAnime();
}, 1600)
}
当然,我们在点击的时候,要执行一下,这个动画的播放,因为是等待动画所以我们模拟1.6s后让其暂停重置后消失。然后再播放后面战斗力数据的三种动画。
4. 数值变化与指针动画
let powerAnime = anime({
targets: '.power',
textContent: [5144, 5144 * 3],
round: 1,
easing: 'easeOutCirc',
duration: 5000,
autoplay: false,
delay: 200
});
let pointerAnime = anime({
targets: '.pointer',
opacity: [1, .36],
translateY: (el, i, l) => {
return (l - i) + 12;
},
easing: 'linear',
direction: 'alternate',
loop: true,
autoplay: false,
duration: 500
})
function playAnime() {
$content.style.display = "block";
powerAnime.play();
pointerAnime.play();
}
anime的强大之处是不仅可以改变样式还可以改变dom内容甚至对象。这里我们把战斗力的变化只用了这么一句,就是从数值5144动态变化到他的三倍就这么简单实现了。
而指针动画也大致相同,但是我们可以发现我们还可以在anime里面使用函数来计算。还有direction也可以交替反向播放。
5. 柱状数据动画
function runChart() {
anime({
targets: '.chart li',
width: () => {
return anime.random(20, 100);
},
easing: 'easeInOutCubic',
duration: () => {
return anime.random(100, 200);
},
loopComplete: runChart
});
}
function playAnime() {
$content.style.display = "block";
powerAnime.play();
pointerAnime.play();
runChart()
}
这是我们的最后一组动画,我们仔细观察,这些柱状数据每次变化是不一样的,因此我们不能单纯使用一次,而是当anime监听loopComplete也就是动画完成后,再次执行它。这样每次的值都是不同的。anime也内置了random随机数值方法,可以更方便去完成。
好了,写到现在就大功告成了,在线演示
扩展
看了这个案例,是不是对anime有了大致的了解呢,他是集轻量与强大于一身的动画库。其实还有更多的功能等待你去解锁,当然最后动画好不好看,还是要看你自己的创意和熟练度的。