如果正在对元素应用任何类型的转换,如何通过js检测?
关于我的问题的短篇小说:
我遇到了在transitionend事件上触发函数的情况,但有时元素没有应用* transition * (例如,在Firefox中,用户可能会快速单击某个元素,从而使转换变得疯狂并停止工作),所以我想知道它什么时候不工作,只需要自己启动函数,跳过transitionend。我试图避免丑陋的解决方案..。
发布于 2022-07-11 03:17:56
您可以为此使用Web动画API,特别是Element#getAnimations方法,它将返回应用于元素的动画对象的列表。其中包括网络动画(来自.animate())、CSS @keyframes动画和CSS跃迁。
document.querySelectorAll("a").forEach((el) => {
el.onmouseenter = (evt) => {
const animations = el.getAnimations(); // we could also ask to look in the subtree
// we're only interested in CSS transitions
const transitions = animations.filter((anim) => anim instanceof CSSTransition);
console.log(transitions.length
? transitions.map((anim) => anim.transitionProperty )
: "no transition"
);
};
});a:hover {
color: red;
opacity: 0.5;
}
.color-transition {
transition: color 1s;
}
.color-and-opacity-transition {
transition: color 1s, opacity 5s;
}
/*SO-only*/.as-console-wrapper { max-height: 110px !important }<b>Hover these anchors to log their applied transitions.</b><br>
<a class="color-transition">color transition</a><br>
<a class="color-and-opacity-transition">color & opacity transition</a><br>
<a>no transition</a>
发布于 2022-07-11 02:38:46
您可以收听transitionstart、transitionend和,transitioncancel事件。判断某个元素是否处于过渡状态。但是,您无法知道某个元素是否会使用以下代码启动转换(即使它有transition-delay: 0s):
/** @type {Map<HTMLElement, number>} */
const transitionCounter = new Map();
/** @type {(() => void)[]} */
const waitingTransition = [];
const incReference = (counter, target) => {
if (counter.has(target)) {
counter.set(target, counter.get(target) + 1);
} else {
counter.set(target, 1);
}
};
const desReference = (counter, target) => {
if (!counter.has(target)) {
return;
} else if (counter.get(target) === 1) {
counter.delete(target);
} else {
counter.set(target, counter.get(target) - 1);
}
};
document.addEventListener('transitionstart', event => {
const { target } = event;
incReference(transitionCounter, target);
const onFinish = event => {
if (event.target !== target) return;
desReference(transitionCounter, target);
target.removeEventListener('transitioncancel', onFinish);
target.removeEventListener('transitionend', onFinish);
[...waitingTransition].forEach(listener => { listener(); });
};
target.addEventListener('transitioncancel', onFinish);
target.addEventListener('transitionend', onFinish);
});
/**
* @param {HTMLElement} element
* @returns {boolean}
*/
const isUnderTransition = function (element) {
const parents = [];
for (let i = element; i; i = i.offsetParent) parents.push(i);
return Array.from(transitionCounter.keys()).some(running => parents.includes(running));
};
/**
* @param {HTMLElement} element
* @returns {Promise<void>}
*/
const waitTransitionEnd = async function (element) {
if (!isUnderTransition(element)) return Promise.resolve();
return new Promise(resolve => {
waitingTransition.push(function listener() {
if (isUnderTransition(element)) return;
waitingTransition.splice(waitingTransition.indexOf(listener), 1);
resolve();
});
});
};发布于 2013-01-15 23:57:34
由W3C编辑器的草稿- CSS转换指定
“transitionend”事件发生在转换完成时。在转换在完成之前被移除的情况下,例如迁移属性被移除,则事件将不会触发。
所以,我认为没有一个有效的简单的方法来解决这个问题。解决方案由实现(浏览器)来决定它是呈现还是不呈现转换。
也许,解决方案可以是将侦听器附加到触发转换的元素,并在经过特定时间之后检查转换元素是否具有所需的CSS属性集,如果没有按预期设置这些属性,则可以自己运行函数。
https://stackoverflow.com/questions/14348856
复制相似问题