12

是否有非轮询方法来监听元素计算样式的更改?

这个幻想代码片段应该简洁地解释我的意思:

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

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

我知道DOMAttrModified突变事件和即将到来的MutationObserver,但两者都不够——它们只能用于观察style元素的 DOM 属性,这并不能完全确定元素的计算样式。


这个用例最初是这个问题的一部分,这真的只是让我好奇。

4

2 回答 2

3

没有这样的方法。CSS OM还没有。

目前尚不清楚“计算样式更改”是什么意思。

原则上,您可以检测使用(例如渲染)样式的变化。但这需要像“绘画”或“布局”这样的事件才能发生。

于 2012-11-02T02:45:54.867 回答
-1

目前你能做的最好的就是请求动画帧。

getComputedStyle显然返回计算属性的实时更新对象。

你可以像这样做一个基本的动画循环:

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();

如果任何使用的属性发生更改,您可以通过仅更新来进行优化:

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();

如果是针对特定的 CSS 动画,您可以通过侦听和来管理requestAnimationFrame循环,或者如果这些事件没有足够好的浏览器支持,您可以在知道动画将开始(例如for )和停止时将其启动当动画属性的计算值停止变化时(即,如果它等于其先前的值,则不调用)。animationstartanimationendmouseenter:hoverrequestAnimationFrame

如果您不需要平滑地制作动画,则可以使用setInterval可能更好的性能(检查文档是否隐藏,这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);
于 2015-09-03T03:01:25.033 回答