Подтвердить что ты не робот

Ручное переключение через анимацию CSS с помощью JavaScript

Если у меня есть анимация ключевого кадра 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 является просто примером - я хотел бы иметь возможность сделать это с любой анимацией.

4b9b3361

Ответ 1

Со встроенной анимацией:

К сожалению, no

Внутренности перехода не отображаются для 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. Стиль может быть то есть. 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) + ')';
}

(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).

Fiddle

enter image description here

Вручную установите переход в любой точке между источником и судьбой или анимируйте их.

Ответ 2

Вы не можете сделать это, как хотите.

Ваша единственная возможность - изменить состояние воспроизведения после заданной задержки.

В вашем случае, так как анимация длится 0,5 секунды, чтобы получить анимацию на 50%, вы должны установить тайм-аут 0,25 секунды, а затем установить режим анимации: приостановлено.

Конечно, это не будет ровно на 50%, не доверяйте точности этого метода.

правка

Добавлена ​​демонстрация для webkit:

fiddle

HTML тривиален

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

И CSS easy

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

Вы reset класс, после небольшой паузы запустите анимацию и вычисленную задержку после запуска, вы ее остановите. Поскольку время анимации составляло 5 с и начальная задержка 50 мс, вторая задержка должна быть (5000/2) + 50. Поскольку вы настроили режим воспроизведения на паузу, чтобы повторно запустить анимацию, вам нужно снова запустить состояние.

Ответ 3

скажем, что у вас есть только одна анимация над вашим элементом gf, вы можете просто управлять ею с помощью animation-delay и 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);
})();

note: это закроет задержку анимации от css, поэтому вы, вероятно, захотите сохранить ее в vairable и добавить ее как смещение в gf.__proto__.animate().

Ответ 4

Возможно, используя CSS DOM для разбора анимации (если это возможно?), а затем для восстановления всего в JavaScript.

Но это не значит, что это умение!

Интересно, поможет ли препроцессор CSS построить такой код. Это очень много в теории.

Ответ 5

Да, Вы можете просто увеличить продолжительность или время анимации. Надеюсь, я понял, что вы хотите сделать:

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