初始实现
想要实现一个类似网易云音乐光碟转动的效果,第一感觉很简单,很快实现如下:
<div
ref="playerDisc"
:class="[
'player-disc absolute inset-0 bg-contain bg-no-repeat',
{
'animation-play': !isPlaying,
},
]"
></div>
<button
type="button"
ref="playerBtn"
:class="[
'player-btn absolute bg-transparent bg-contain bg-center bg-no-repeat',
isPlaying ? 'play' : 'pause',
]"
@click="togglePlay"
>
<span v-if="isPlaying" class="sr-only">暂停</span>
<span v-else class="sr-only">播放</span>
</button>
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.animation-play {
animation: spin 20s linear infinite;
}
CSS 实现很简单。
ChatGPT 实现
在实现暂停、播放功能时,突然发现,暂停之后,光碟 playerDisc 就恢复到了初始位置,那么如何在暂停时,让光碟保留在当前动画的位置呢?
ChatGPT 给出了以下方法:
playerBtn.value?.addEventListener('click', () => {
if (playerDisc.value) {
if (isPlaying.value) {
const computedStyle = window.getComputedStyle(playerDisc.value)
const matrix = computedStyle.transform
if (matrix !== 'none') {
const values = matrix.split('(')[1].split(')')[0].split(',')
const a = Number(values[0])
const b = Number(values[1])
currentRotation.value = Math.round(Math.atan2(b, a) * (180 / Math.PI))
playerDisc.value.style.transform = `rotate(${currentRotation.value}deg)`
}
} else {
playerDisc.value.style.transform = `rotate(${currentRotation.value}deg)`
}
isPlaying.value = !isPlaying.value
}
})
通过 js 获取元素的样式,获取旋转角度。这样在暂停的时候,确实可以保持在当前位置,但是恢复播放时又从初始角度开始了。
继续问 ChatGPT,给出了更复杂的、用 js requestAnimationFrame 实现动画的方案,而不是 CSS 动画。
animation-play-state
简单搜索了一下,原来 CSS 动画还支持这么多属性,其中 animation-play-state
就是设置动画的运动状态:
ChatGPT 其实一开始就给出了方法:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS动画暂停</title>
<style>
.box {
width: 100px;
height: 100px;
background-color: blue;
position: relative;
animation: move 4s linear infinite;
animation-play-state: paused; /* 默认暂停 */
animation-fill-mode: forwards; /* 保持动画最后一帧状态 */
}
@keyframes move {
0% { left: 0; }
100% { left: 300px; }
}
</style>
</head>
<body>
<div class="box"></div>
<button onclick="toggleAnimation()">切换动画状态</button>
<script>
function toggleAnimation() {
const box = document.querySelector('.box');
if (box.style.animationPlayState === 'paused') {
box.style.animationPlayState = 'running';
} else {
box.style.animationPlayState = 'paused';
}
}
</script>
</body>
</html>
只是我错误的运用了,在我给出自己的代码继续让它修改时,它不坚定的给出了复杂的东西。
.animation-play {
animation: spin 20s linear infinite;
animation-fill-mode: forwards;
animation-play-state: running;
}
.animation-pause {
animation-play-state: paused;
}
我在播放时应用 .animation-play
,在暂停时应用 .animation-pause
,但是 .animation-pause
中并没有动画名称。
暂停时,.animation-play .animation-pause
叠加使用就好了,或者 .animation-pause
中写上动画的其他属性。
这样 CSS 动画就轻松的实现暂停和恢复功能。
总结
- 很小的一个问题,记录一下,希望对遇到的人有帮助。
- 主要还是 CSS 基本功问题,(CSS 新内容其实很多)。
- 遇到问题,不要把它复杂化,多想想是不是方法的问题。
- 看文档一定要去理解,才能正确使用。不要忙碌的尝试就放弃。