14

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

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

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

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

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

有没有办法覆盖动画持续时间/动画定时功能以依赖于 JavaScript?我希望能够说一些事情,比如gf.animate("flash-red", "50%")让背景gf变成红色,或者gf.animate("flash-red", "75%")让背景更像rgba(255, 0, 0, .5).

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

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

4

5 回答 5

12

使用内置动画:

抱歉不行

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

但是,您可以进行自己的转换。这涉及到自己的计算转换。

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

current = source + (destination - source) * fraction;

例如,对于颜色,您可以将其与颜色组件一起使用。假设我们有具有属性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

这里当前的 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;

对于职位:

 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;

等等。

通过制作包装函数,您可以轻松计算它们,甚至将它们放入循环中以动画化它们。

用于设置颜色 1 和颜色 2 之间过渡的示例函数。样式可以是 ie。backgroundColorcolor

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) + ')';
}

(这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';
}

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

小提琴

在此处输入图像描述

在源和命运之间的任何点手动设置过渡,或为它们设置动画。

于 2013-06-28T06:33:46.143 回答
4

假设您的元素只有一个动画gf,您可以简单地使用animation-delayand控制它animation-play-state

gf.__proto__.animate = function(percent) {
  this.style["animation-play-state"] = "paused";
  this.style["animation-delay"] = (
    (parseFloat(this.style["animation-duration"] || 1) * -percent) + "s"
  );
};

你可以得到如下计算的样式:

window.getComputedStyle(gf).background

以任何速度通过:

(function animation(time) {
  gf.animate( ((time || 0) % desireSpeed ) / desireSpeed );
  requestAnimationFrame(animation);
})();

注意:这将覆盖 css 中的动画延迟,因此您可能希望将其保留在变量中并将其作为偏移量添加到gf.__proto__.animate().

于 2017-08-23T04:30:23.867 回答
3

你不能随心所欲地这样做。

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

在您的情况下,由于动画持续 0.5 秒,要获得 50% 的动画,您应该设置 0.25 秒的超时,然后设置动画播放状态:暂停。

当然,这不会恰好是 50%,不要相信这种方法的精度。

编辑

为 webkit 添加了演示:

小提琴

HTML 是微不足道的

<div id="goflash">TEST</div>
<input type="button" value="animate" onclick="animate()">

和 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;
    }
}

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);
}

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

于 2013-06-20T20:00:00.383 回答
1

也许使用 CSS DOM 来解析动画的意图(如果这可能吗?),然后在 JavaScript 中重建所有内容。

但这绝非易事!

我想知道 CSS 预处理器是否有助于构建这样的代码。这都是理论上的。

于 2013-06-24T16:44:19.620 回答
0

是的,您可以覆盖动画的持续时间或时间。希望我明白你想要做什么:

http://jsfiddle.net/SEHyW/

var gf = document.querySelector("#goflash"),
    animationDuration = '1s'

gf.classList.remove("anm-flash");
setTimeout(function() {
  gf.classList.add("anm-flash");
  gf.style["-webkit-animation-duration"] = animationDuration;
}, 1000);
于 2013-06-29T19:32:52.113 回答