在我的关闭函数中,我想在css转换完成后完成所有DOM清理工作。但可能没有任何转换正在运行/可能是多阶段的转换-(维护样式表是我无法控制的)。
我该如何写一个函数,比如下面的
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转换
关于transitionStart和transitionEnd事件:
过渡不可能从任何地方开始。通常,转换在某个事件之后开始,在该事件中,您可以通过按类或其他方式更改样式来更改DOM元素的状态。所以您知道转换何时开始,因为您在代码中开始它。
在转换过程中,用户I/O不会阻塞,所以转换是异步的,然后转换就会结束,这是你不知道的。所以您需要transitionEnd
事件来做一些事情,然后在javascript中完成转换。
关于transitionEnd事件:只需查看jsfiddle
到目前为止,这是我的解决方案-有点粗糙,只有在知道哪个元素可能转换时才有效,而不适用于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);
}
(据我所知)如果不知道正在转换的元素,就无法检测转换当前是否在后台工作。
但是,如果您可以从过渡到关键帧动画,那么您就有了所需的事件-animationStart和animationEnd,然后就可以很容易地确定是否有正在运行的动画。
如果您计划进行css转换,您可以查看jQuery Transit插件http://ricostacruz.com/jquery.transit/
非常强大和有用,您可以使用获得变换x值。例如css('x')。
您尝试过JQuery伪":animatized"吗?
if($(elem).is(':animated')){…}
查看更多http://api.jquery.com/animated-selector/
这里有一个等待页面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.dococumentElement.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;
}));
IE10+中存在一个不可修复的transitionstart事件。它甚至可以取消。
https://msdn.microsoft.com/library/dn632683%28v=vs.85%29.aspx
在动画.css上,我发现了这个。
您还可以检测动画何时结束:
$('#yourElement').one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', doSomething);
在此处阅读完整文档
您可以使用Jquery,这将更容易,例如,您可以使用类似的animate
(function(){
var box = $('div.box')
$('button').on('click', function(){
box.animate({ 'font-size' : '40px'})
.animate({'color': 'red'});
})
})();
或者简单地执行回调函数