简体   繁体   English

DOM元素的计算样式更改时触发事件?

[英]Fire an event when DOM element's computed style changes?

Is there a non-polling method to listen for changes to an element's computed style ? 是否有非轮询方法来侦听元素的计算样式的更改?

This fantasy code snippet should explain what I mean succinctly: 这个幻想代码段应该简洁地解释我的意思:

var el = document.getElementById('doodad');

el.addComputedStyleChangeListener('width', function (prev, new) {
  alert('Previous width: ' + prev + '; New width: ' + new);
});

I'm aware of the DOMAttrModified mutation event and the upcoming MutationObserver , but neither is sufficient -- they can only be used to watch the style DOM attribute of an element, which doesn't wholly determine an element's computed style. 我知道DOMAttrModified突变事件和即将到来的MutationObserver ,但这还不够-它们只能用于监视元素的style DOM属性,这不能完全确定元素的计算风格。


The use case for this was originally part of this question , which really just lead me down a course of curiosity. 这个用例原本是这个问题的一部分,这确实使我产生了好奇心。

There is no such method. 没有这种方法。 CSS OM is not there yet. CSS OM还不存在。

And it is not clear what "computed style change" means. 尚不清楚“计算样式更改”是什么意思。

In principle you can detect change of used (for eg rendering) style. 原则上,您可以检测所用(例如渲染)样式的更改。 But this will need some event like "paint" or "layout" to happen. 但这需要发生“绘画”或“布局”之类的事件。

The best you can do at the moment is request animation frames. 您目前能做的最好的就是请求动画帧。

getComputedStyle apparently returns a live-updating object of computed properties. getComputedStyle显然返回了一个计算属性的实时更新对象。

You can do a basic animation loop like this: 您可以像这样进行基本的动画循环:

var computedStyle = getComputedStyle(element);
var animate = function () {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = computedStyle.color;
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    requestAnimationFrame(animate);
};
animate();

You could potentially optimize by only updating if any of the used properties have changed: 如果任何使用的属性已更改,则可能仅通过更新来进行优化:

var computedStyle = getComputedStyle(element);
var lastFrameBackground;
var lastFrameColor;
var animate = function () {
    if (
        computedStyle.background !== lastFrameBackground ||
        computedStyle.color !== lastFrameColor
    ) {
       lastFrameBackground = computedStyle.background;
       lastFrameColor = computedStyle.color;

       // assuming expensive drawing code here
       // not like this!
       ctx.clearRect(0, 0, canvas.width, canvas.height);
       ctx.fillStyle = computedStyle.color;
       ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
    requestAnimationFrame(animate);
};
animate();

If it's for a specific CSS animation, you could maybe manage the requestAnimationFrame loop by listening for animationstart and animationend , or if those events don't have good enough browser support, you could kick it off when you know the animation will start (eg mouseenter for :hover ) and stop when an animated property's computed value stops changing (ie don't call requestAnimationFrame if it's equal to its previous value). 如果是针对特定CSS动画的,则可以通过侦听animationstartanimationend管理requestAnimationFrame循环,或者如果这些事件没有足够的浏览器支持,则可以在知道动画将要开始时将其启动(例如, mouseenter for :hover ),并在动画属性的计算值停止更改时停止(即,如果它等于其先前值,则不调用requestAnimationFrame )。

If you don't need to animate smoothly, you could use setInterval for possibly-better performance (checking if the document is hidden which requestAnimationFrame does implicitly): 如果您不需要平滑地设置动画效果,则可以使用setInterval以获得更好的性能(检查是否隐藏了requestAnimationFrame隐式requestAnimationFrame的文档):

var computedStyle = getComputedStyle(element);
setInterval(function () {
    if (!document.hidden) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = computedStyle.color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    }
}, 200);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM