动画文本,向左旋转一次,暂停,然后向右旋转一次,然后在 Javascript 中重复



目前我有这段代码,它以 3d 效果连续旋转文本。但是,我想做的是让文本进行一次完整的旋转或向左旋转 360 度,然后暂停片刻,然后向右执行相同的操作并继续相同的操作。我将不胜感激任何关于如何在Javascript中解决这个问题的建议,而不是Jquery或CSS,因为我特别想练习我的Javascript技能,谢谢。

function spin()
{
document.getElementById("myDIV");
setInterval(function()
{
myDIV.style.transform += "rotate3d(0,10,0,10deg)";
}, 80);
}
spin();
<div style="text-align:center;"><h1 id='myDIV'>my 3d text</h1>

你不需要JS。它可以使用CSS动画来完成。

在下面的代码片段中,我将div 设置为通过定义的关键帧沿一个方向旋转,然后通过指定它animation-direction: alternate;交替方向旋转。

请注意,我将旋转的z分量保持在 0.2,以便我可以想象它正在工作。对于您需要的内容,z分量应为零。

#myDIV {
animation: 5s linear infinite alternate rotate ;
}
@keyframes rotate {
0%,
100% {
transform: rotate3d(0, 1, 0.2, 0deg);
}
50% {
transform: rotate3d(0, 1, 0.2, 360deg)
}
}
<div style="text-align:center;">
<h1 id='myDIV'>my 3d text</h1>
</div>


JS版本:

使用 JS,我认为您需要跟踪当前的旋转角度(以便您可以在下一次迭代中增加它(和当前旋转方向(以便您可以决定是增加角度还是减小角度(。

我选择不附加到样式(myDIV.style.transform += "rotate3d(0,10,0,10deg)";(,因为我怀疑浏览器在某些时候可能会开始变慢。因此,相反,我通过全局变量管理旋转(即,不是有两个 10 度的旋转,而是保持一个 20 度的旋转(。

我相信这可以进一步简化,但希望它展示了一种可能的方法。此外,如果您有兴趣,可以使用requestAnimationFrame来提高动画计时精度(与setInterval相比(。

var currentAngle = 0;
var currentDirection = 0; // 0 - Increasing, 1 - Decreasing
function spin() {
document.getElementById("myDIV");
setInterval(function() {
if(currentDirection == 0) {
// Allow one complete rotation.
if(currentAngle < 360) {
myDIV.style.transform = "rotate3d(0,1,0.2,"+ currentAngle +"deg)";
currentAngle += 10;
} else {
// Change the direction.
currentDirection = 1;
currentAngle -= 10;
myDIV.style.transform = "rotate3d(0,1,0.2,"+ currentAngle +"deg)";
}
} else {
// Allow one complete rotation.
if(currentAngle > 0) {
myDIV.style.transform = "rotate3d(0,1,0.2,"+ currentAngle +"deg)";
currentAngle -= 10;
} else {
// Change the direction.
currentDirection = 0;
currentAngle += 10;
myDIV.style.transform = "rotate3d(0,1,0.2,"+ currentAngle +"deg)";
}
}
}, 80);
}
spin();
<div style="text-align:center;">
<h1 id='myDIV'>my 3d text</h1>
</div>

我想提供一个示例,说明如何使用requestAnimationFrame来提供更流畅,一致的动画。使用requestAnimationFrame时,您不必依靠setInterval有时不一致的间隔来驱动度数的更新频率,而是计算自上次绘制以来应该发生多少变化,然后相应地更新。

我还添加了传入 id 而不是使用固定元素的功能,我的函数返回一个可用于停止动画的函数。

function spin (id) {
// just a flag to allow us to cancel the animation if we want to
let keepGoing = true;
// function that will be returned to allow us to cancel the animation
const stop = () => keepGoing = false;
const el = document.getElementById(id);
let degrees = 0;
let dir = 1; // current direction of animation; 1 === forward, -1 === backward
// your original code moves the animation 10 deg per 80 ms,
// which is equivalent to 8 deg per ms, thus the speed of 8
const speed = 8;
// lastTime will be used to track how many ms have passed since the last time
// the callback was called. Since the first call to the callback will be
// manual instead of via requestAnimationFrame, we need to manually get a
// DOMHighResTimeStamp via performance.now().
let lastTime = performance.now();
// this callback will be used with requestAnimationFrame to run the animation,
// it expects to get the a DOMHighResTimeStamp as its parameter, which
// requestAnimationFrame will provide, on every call after the initial manual
// call to it using the lastTime we generated above.
const callback = currentTime => {
// calculate number of ms between now and the last time this callback ran
const delta = currentTime - lastTime;
lastTime = currentTime;
// calculate how many degrees we should move based on how long it has been
// since the last callback (ms / deg per ms)
const change = delta / speed;
// dir will be either 1 or -1, multiplying by dir will either increase
// or decrease "degrees" by "change" degrees.
degrees += dir * change;
// apply the new transformation
el.style.transform = `rotate3d(0, 1, .2, ${degrees}deg`;
// reverse directions if needed
if (degrees >= 360) {
dir = -1;
} else if (degrees <= 0) {
dir = 1;
}
if (keepGoing) {
requestAnimationFrame(callback);
}
};
// start the animation by manually calling the callback
callback(lastTime);
return stop;
}
let stopMyDivSpinning = spin('my-div');
// stop spinning after 20 seconds
setTimeout(stopMyDivSpinning, 20000);
#my-div {
font-size: 3em;
text-align:center;
background: linear-gradient(0.25turn, #3f87a6, #f69d3c);
background-clip: text;
-webkit-background-clip: text;
color: rgba(0,0,0,0);
}
<div id="my-div">My 3D Text</div>

延伸阅读

  • 请求动画帧
  • 性能.现在
  • DOMHighResTimeStamp
  • 加法分配 (+=(
  • 箭头函数

最新更新