使用JavaScript手动逐步执行CSS动画

Aar*_*ken 14 javascript css html5 css3 css-animations

如果我有这样的CSS关键帧动画

@keyframes flash-red {
  50% {
    background: #f00;
  }
}

#goflash.anm-flash {
  animation-name: flash-red;
  animation-duration: .5s;
  background: rgba(255, 0, 0, 0);
}
Run Code Online (Sandbox Code Playgroud)

然后我总是可以像这样触发动画:

var gf = document.querySelector("#goflash");
gf.classList.remove("anm-flash");
setTimeout(function() {
  gf.classList.add("anm-flash");
}, 50);
Run Code Online (Sandbox Code Playgroud)

有没有办法覆盖动画持续时间/动画定时功能依赖于JavaScript?我希望能够说出像红色gf.animate("flash-red", "50%")背景gfgf.animate("flash-red", "75%")让背景更像的东西rgba(255, 0, 0, .5).

理想情况下,相同的技术适用于过渡.gf.transitionTo("new-class", "50%")将元素显示为中途转换.

显然这flash-red只是一个例子 - 我希望能够用任何动画做到这一点.

小智 12

内置动画:

很不幸的是,不行

转换的内部不会暴露给JavaScript,因此您无法利用它来设置或获取数据.这是出于某种目的 - 如果数据暴露,则意味着效率降低,因为必须更新JavaScript事件队列.由于JS是单线程的,并且动画在一个单独的线程上运行,你很快就会失去它在一个单独的线程内部运行在编译代码中的好处.

但是,您可以进行自己的过渡.这涉及计算转换自己.

这并不像听起来那么复杂,因为您只需使用插值公式来制作动画:

current = source + (destination - source) * fraction;
Run Code Online (Sandbox Code Playgroud)

例如,对于颜色,您可以将其与颜色分量一起使用.让我们假设我们有一个特性颜色对象r,g,b:

var color1 = {r: 100, g: 200, b: 55};  //some random color
var color2 = {r: 0,   g: 100, b: 100};

var fraction = 0.5; //0-1
Run Code Online (Sandbox Code Playgroud)

这里当前的RGB将是:

r = color1.r + (color2.r - color1.r) * fraction;
g = color1.g + (color2.g - color1.g) * fraction;
b = color1.b + (color2.b - color1.b) * fraction;
Run Code Online (Sandbox Code Playgroud)

对于职位:

 var pos1x = 100;
 var pos1y = 100;
 var pos2x = 500;
 var pos2y = 250;

var fraction = 1; //0-1

posX = pos1x + (pos2x - pos1x) * fraction;
posY = pos1y + (pos2y - pos1y) * fraction;
Run Code Online (Sandbox Code Playgroud)

等等.

通过创建包装函数,您可以轻松地计算这些函数,甚至将它们放在一个循环中来为它们设置动画.

用于设置颜色1和颜色2之间转换的示例功能.样式可以是ie.backgroundColor,color等:

function setColor(element, style, color1, color2, fraction) {

    var r = color1.r + (color2.r - color1.r) * fraction;
    var g = color1.g + (color2.g - color1.g) * fraction;
    var b = color1.b + (color2.b - color1.b) * fraction;

    element.style[style] = 'rgb(' + (r|0) + ',' + (g|0) + ',' + (b|0) + ')';
}
Run Code Online (Sandbox Code Playgroud)

(这r|0只是截断小数部分).

而对于职位,例如:

var pos1 = {x: 0, y: 0};
var pos2 = {x: 200, y: 0};

function setPosition(element, pos1, pos2, fraction) {

    var x = pos1.x + (pos2.x - pos1.x) * fraction;
    var y = pos1.y + (pos2.y - pos1.y) * fraction;

    element.style.left = x + 'px';
    element.style.top = y + 'px';
}
Run Code Online (Sandbox Code Playgroud)

一个简单的演示(使用Chrome或Aurora 23来查看滑块,滑块出现在FF 23的下一个版本中).

小提琴

在此输入图像描述

在源和命运之间的任何点手动设置转换,或为它们设置动画.


val*_*als 3

你不能如你所愿那样做。

您唯一的可能性是在给定的延迟后更改播放状态。

在您的情况下,由于动画持续 0.5 秒,为了使动画达到 50%,您应该设置 0.25 秒的超时,然后设置animation-play-state : Paused。

当然不会精确到50%,不要相信这个方法的精度。

editing

添加了 webkit 的演示:

小提琴

HTML 很简单

<div id="goflash">TEST</div>
<input type="button" value="animate" onclick="animate()">
Run Code Online (Sandbox Code Playgroud)

CSS 也很简单

#goflash {
    width: 200px;
    height: 200px;
    left: 35px;
    top: 35px;
    position: absolute;
    background-color: red;
}
.anm-flash {
    -webkit-animation-name: flash;
    -webkit-animation-duration: 5s;
    -webkit-animation-timing-function: linear;
    -webkit-animation-iteration-count: 1;
}

@-webkit-keyframes flash {
    from {   -webkit-transform: rotate(0deg);
             background-color: red;        }
    50% {    -webkit-transform: rotate(120deg);
             background-color: yellow;}
    to {    -webkit-transform: rotate(360deg);
            background-color: red;
    }
}
Run Code Online (Sandbox Code Playgroud)

javascript 是您提供的扩展:

function animate () {
    var gf = document.querySelector("#goflash");
    gf.classList.remove("anm-flash");
    setTimeout(function() {
        gf.classList.add("anm-flash");
        gf.style.webkitAnimationPlayState = "running";
    }, 50);
    setTimeout(function() {
        gf.style.webkitAnimationPlayState = "paused";
    }, 2550);
}
Run Code Online (Sandbox Code Playgroud)

您重置类,在短暂的暂停后开始动画,并在开始后计算出延迟,然后停止它。由于动画时间为 5 秒,初始延迟为 50 毫秒,因此第二个延迟必须为 (5000/2) + 50。由于您现在已将播放状态设置为暂停,因此能够重新运行您所拥有的动画再次将状态设置为运行。