是否可以通过JavaScript以某种方式验证CSS过渡是否完成而无需预先注册过渡事件?
问题是:
是否有可能通过JavaScript检查元素的CSS转换是否完成?随时吗?
我无法利用javascript事件(例如https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript/)
答案 0 :(得分:2)
您能做的最好的就是查看CSS以查看过渡持续时间。
答案 1 :(得分:0)
不是答案,而是一种快速的POC:
element.onclick = function() {
const color = 0x1000 | (Math.random() * 0x1000);
const prop = Math.random() < .5? "background-color": "color";
element.style[prop] = "#" + color.toString(16).slice(-3);
}
let curr = {};
requestAnimationFrame(function check() {
const prev = curr;
curr = Object.assign({}, getComputedStyle(element));
const changed = Object.keys(curr).filter(key => curr[key] !== prev[key]);
out.innerHTML = changed.map(key => `<li>${key}</li>`).join("\n");
requestAnimationFrame(check);
});
html,
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#element {
cursor: pointer;
width: 100%;
height: 100%;
padding: 20px;
transition: all 1s;
}
<div id="element">
<p>Click somewhere</p>
currently transitioning:
<ul id="out"></ul>
</div>
您会注意到闪烁,这是因为在该插值过程中,两个相邻的帧可能不会有所不同。您想要缓存更多的帧并比较相隔5-10帧;取决于您使用的插值方法和过渡的持续时间。
此外,根据您要检查的属性,还可以将getComputedStyle(element)[key]
与element.style[key]
进行比较,而不必存储多个帧的值。但这不适用于颜色(和其他颜色),因为描述相同颜色的方法很多。
答案 2 :(得分:0)
抱歉,正在开会。搜索了我的一个旧项目,但找不到。我将在这里概述这个想法,最初我想也许我们可以去使用Mutation Observer,但是我们也必须在那里进行定期检查。所以我想这会做。首先,您应该避免一些事情:
第一件事是编写一个辅助函数,该函数将定期运行一些测试函数并在成功后返回:
function watchman(obj,test,action,options){
var currentFrame = {value:undefined};
function watch(){
if(test.call(obj,options)){
action.call(obj,options);
return;
} else {
currentFrame.value = window.requestAnimationFrame(watch);
}
};
currentFrame.value = window.requestAnimationFrame(watch);
return currentFrame;
};
接下来是实际的函数,我会说不需要创建新对象,我们可以创建一个带有3个(2个可选)参数,节点“ functor”,要检查的style属性以及最后要调用的函数的函数
function onTransitionEnd(fNode,prop,f,precision,timeout){
precision = precision || 5;
timeout = timeout || Infinity;
return new Promise(function(res){
var node = fNode(),
oValue = node && getComputedStyle(node)[prop],
currentFrame = watchman(
fNode,
function(counter){
if(counter.counter * 17 >= timeout){
window.cancelAnimationFrame(currentFrame.value);
}
if(++counter.counter % precision === 0) {
if(!this()){return}
var nValue = getComputedStyle(this())[prop];
if(nValue === oValue) {
return true;
}
oValue = nValue;
}
},
function(counter){
res(f.call(fNode(),prop));
},
{counter:0}
);
});
};
默认精度5表示该函数将每5个滴答声(5 * 17毫秒)检查一次值以确定过渡是否结束。超时也是可选的,它会在一段时间后取消运行。
如果节点不存在就没有问题,因为我们传递了一个返回该节点或为null的函数,如果该节点不存在,它将不会执行。
以上是一个承诺,它将返回一个“ thenable”对象,您可以随意链接它。
简单的用例,例如,在更改样式或类之后:
document.getElementById("someDiv").className = "def c1";
onTransitionEnd(
function(){return document.getElementById("someDiv");},
"transform",
function(){alert("heyy!!");}
);
它现在会警告您“嘿”。要将此链接起来:
document.getElementById("someDiv").className = "def c1";
onTransitionEnd(
function(){return document.getElementById("someDiv");},
"transform",
function(prop){alert("heyy!!"); return this;}
).then(function(node){
node.className = "def";
return onTransitionEnd(
function(){return document.getElementById("someDiv");},
"transform",
function(){alert("heyy-2!!"); return this;}
);
}).then(function(node){
alert("id is " + node.id);
});
以下是一些示例:
要使最后一个工作,请打开开发人员控制台,选择蓝色的div并将其ID更改为“ someDiv”,该功能将执行。
您可能想知道每次更改样式时是否都要调用onTransitionEnd,在这种情况下,您可以编写包装器。如果您不知道,请告诉我,我也会写。
很明显,您没有使用包装器,因此这里是一个辅助包装器:
function Select(node){
this.node = node;
};
Select.prototype.style = function(prop,value,f){
var node = this.node;
this.node.style[prop] = value;
f && onTransitionEnd(
function(){return node;},
prop,
f
);
return this;
};
这是您将如何使用它:
var selection = new Select(document.getElementById("someDiv"));
selection
.style("width","100px",function(propName){alert(propName + " changed!");})
.style("height","100px",function(propName){alert(propName + " changed!");})
.style("transform","scale(0.5,0.5)",function(propName){alert(propName + " changed!");});
这是EXAMPLE;