Могу ли я обнаружить, если начался произвольный переход CSS
В моей закрытой функции я хочу сделать все мое очищающее средство DOM после завершения css-переходов. Но не может быть никаких переходов, выполняемых/может быть многоступенчатым - (сохранение таблиц стилей из моих рук).
Как я могу написать функцию, например следующую
function close () {
myEl.removeClass('open');
if (animation is running/about to be run) {
// wait for transition to end, then recursively check to see if another
// one has started, wait for that ...
// then
cleanUpDOM();
} else {
cleanUpDOM();
}
}
Мои мысли до сих пор состоят в том, чтобы обернуть начальную проверку в timeout/requestAnimationFrame, чтобы дать анимации возможность начать, а затем проверить, не работает ли она. К сожалению, без события transitionstart
я понятия не имею, как проверить, начался переход.
edit Ответы, рекомендующие jquery, неактуальны, поскольку анимация jquery - это анимация javascript, а не переходы CSS
Ответы
Ответ 1
О событиях переходаStart и transitionEnd:
Переход не может начаться нигде. Обычно переход начинается после некоторого события, когда вы меняете состояние элемента DOM, меняя стили по классам или чему-то еще. Поэтому вы знаете, когда переход начинается, потому что вы запускаете его в своем коде.
Во время перехода пользовательский ввод-вывод не блокирует, поэтому переход является асинхронным, а затем переход закончится, вы не знаете правильно. Поэтому вам нужно transitionEnd
событие, чтобы что-то сделать, а затем переход закончился в javascript.
О событии переходаEnd:
Просто посмотрите jsfiddle
Ответ 2
Здесь мое решение до сих пор - немного взломанно и работает только тогда, когда какой-либо элемент может перейти, и не работает с transition-property: all
... но это многообещающий старт
function toCamelStyleProp (str) {
return str.replace(/(?:\-)([a-z])/gi, function ($0, $1) {
return $1.toUpperCase();
});
}
function toHyphenatedStyleProp (str) {
return str.replace(/([A-Z])/g, function (str,m1) {
return '-' + m1.toLowerCase();
}).replace(/^ms-/,'-ms-');
}
function getPrefixedStyleProp (prop) {
prop = toCamelStyleProp(prop);
prop = Modernizr.prefixed(prop);
return toHyphenatedStyleProp(prop);
}
function getStyleProperty (el, prop) {
return getComputedStyle(el,null).getPropertyValue(getPrefixedStyleProp(prop));
}
function doAfterTransition ($wrapper, cssClass, mode, $transitioningEl, callback) {
$transitioningEl = $transitioningEl || $wrapper;
var transitioningEl = $transitioningEl[0],
duration = +getStyleProperty(transitioningEl, 'transition-duration').replace(/[^\.\d]/g, ''),
transitioners = getStyleProperty(transitioningEl, 'transition-property').split(' '),
initialState = [],
changedState = [],
i,
callbackHasRun = false,
//makes sure callback doesn't get called twice by accident
singletonCallback = function () {
if (!callbackHasRun) {
callbackHasRun = true;
callback();
}
};
// if no transition defined just call the callback
if (duration === 0) {
$wrapper[mode + 'Class'](cssClass);
callback();
return;
}
for (i = transitioners.length - 1;i>=0;i--) {
initialState.unshift(getStyleProperty(transitioningEl, transitioners[i]));
}
$wrapper[mode + 'Class'](cssClass);
setTimeout(function () {
for (i = transitioners.length - 1;i>=0;i--) {
changedState.unshift(getStyleProperty(transitioningEl, transitioners[i]));
}
for (i = transitioners.length - 1;i>=0;i--) {
if (changedState[i] !== initialState[i]) {
$transitioningEl.transitionEnd(singletonCallback);
// failsafe in case the transitionEnd event doesn't fire
setTimeout(singletonCallback, duration * 1000);
return;
}
}
singletonCallback();
}, 20);
}
Ответ 3
Нет способа (который я знаю) обнаружить, что переход в настоящее время работает в фоновом режиме, не зная, какой элемент находится в процессе перехода.
Однако, если вы можете перейти от перехода к анимации ключевых фреймов, тогда у вас будет необходимое событие - animationStart и animationEnd, и тогда будет легко выяснить, есть ли анимация.
Ответ 4
Вы пробовали псевдоним ": анимированный" JQuery?
if ($ (elem).is(': animated')) {...}
Подробнее http://api.jquery.com/animated-selector/
Ответ 5
Вот функция, которая ожидает, что страница Html станет стабильной. т.е. когда все анимации закончены. В приведенном ниже примере он ожидает, что Html останется неизменным в течение 200 миллисекунд и максимальный тайм-аут в 2 секунды.
Вызвать функцию с помощью...
waitUntilHtmlStable(yourCallback, 200, 2000);
Функция...
waitUntilHtmlStable = function (callback, unchangedDuration, timeout, unchangedElapsed, html) {
var sleep = 50;
window.setTimeout(function () {
var newHtml = document.documentElement.innerHTML;
if (html != newHtml) unchangedElapsed = 0;
if (unchangedElapsed < unchangedDuration && timeout > 0)
waitUntilHtmlStable(callback, unchangedDuration, timeout - interval, unchangedElapsed + interval, newHtml);
else
callback();
}, sleep);
};
В моем случае я хотел быть уверенным в новых элементах, где они присутствуют. Если вы хотите отслеживать движение анимации, измените document.documentElement.innerHTML на
JSON.stringify(Array.prototype.slice.call(document.documentElement.getElementsByTagName("*"), 0)
.map(function(e) {
var x = e;
var r = x.getBoundingClientRect();
while (r.width == 0 || r.height == 0) {
x = x.parentNode;
r = x.getBoundingClientRect();
}
return r;
}));
Ответ 6
В IE10 + есть незафиксированное событие перехода. Он даже отменяется.
https://msdn.microsoft.com/library/dn632683%28v=vs.85%29.aspx
Ответ 7
Если вы планируете сделать переход css, вы можете проверить плагин jQuery Transit http://ricostacruz.com/jquery.transit/
Очень мощный и полезный, вы можете получить значение преобразования x. css ('x'), например.
Ответ 8
В animation.css я нашел это.
Вы также можете определить, когда заканчивается анимация:
$('#yourElement').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', doSomething);
читайте полный документ здесь
Ответ 9
вы можете использовать Jquery, что было бы намного проще, например, вы могли бы использовать .animate, подобный этому
(function(){
var box = $('div.box')
$('button').on('click', function(){
box.animate({ 'font-size' : '40px'})
.animate({'color': 'red'});
})
})();
или просто выполните функцию обратного вызова