You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We want to observe computed property values (custom or not). For example:
When an element's computed left style changes (for any reason, including CSS transitions, or stylesheet addition/removal, etc), we want a WebGL scene to be updated based on the observed value.
We want to polyfill new CSS rendering features, and we may need to have a separate <canvas> for rendering the graphics, so we'll want to update the canvas any time the computed (possibly --custom) CSS properties of an element change for any reason.
We want to implement new custom rendering libraries (and similarly to the previous point, we will render to a canvas). For example imagine libraries like a-frame, CSSVR, or (disclaimer, my own library) Lume having rendering features defined by --custom CSS properties defined with CSS.registerProperty)
All of the above use cases are possible today, but not as easy as it would be with an official observation API. Current techniques involve polling with requestAnimationFrame.
Problem
Given a reference to an element, I'd like to be able to observe property changes on that element in a non-polling fashion.
I could currently make a loop with requestAnimationFrame and use getComputedValue inside of it, like this:
constel=document.querySelector('div')constelStyle=getComputedStyle(el)// Starts animation of the element with a CSS transitionsetTimeout(()=>el.classList.add('move'),1000)functionloop(){// Logs the current `left` value every frame.console.log(elStyle.getPropertyValue('left'))requestAnimationFrame(loop)}loop()
But this is not a good approach, because it does not know when the values have actually changed, and so continuously polling in a loop will use CPU over time.
Solution
It would be better to have a push-based approach, so that computed style observers can execute only when style changes actually happen.
Maybe we can add this to MutationObserver; it seems like the best place, currently, where such a feature could live.
Maybe it would look something like this:
// Create an observer that will watch for computed style changes.constobserver=newMutationObserver(mutations=>{for(constmutationofmutations){conststyle=mutation.styleMap// live StylePropertyMapReadOnly?console.log(style);}});// Start observing the target node for computed style changes.observer.observe(targetNode,{computeStyle: true,stylePropertyFilter: ['left']// observe only the "left" style property});// ...Later, we can stop observing.observer.disconnect();
where perhaps mutation.styleMap is a "live" StylePropertyMapReadOnly instance, so that under the hood the engine can be more efficient by always returning that same instance, or something.
If we used MutationObserver, I think there would only ever be a single item inside the mutations list, unlike with other types of changes. I think we can encourage people to rely only on the last known value of a style property (inside the styleMap) in order to do something for next paint.
Or maybe, like other observer classes similar to ResizeObserver, there could be a separate ComputedStyleObserver class instead of adding this feature onto MutationObserver.
Other way to achieve it?
Can we use a worklet, which will update on property changes, and somehow allow that worklet to communicate back to the main thread (or other worker thread) the changes that happened, so that we can avoid polling with rAF? Are worklets able to communicate with the main thread or any other thread?
The text was updated successfully, but these errors were encountered:
What
We want to observe computed property values (custom or not). For example:
left
style changes (for any reason, including CSS transitions, or stylesheet addition/removal, etc), we want a WebGL scene to be updated based on the observed value.<canvas>
for rendering the graphics, so we'll want to update the canvas any time the computed (possibly--custom
) CSS properties of an element change for any reason.--custom
CSS properties defined withCSS.registerProperty
)All of the above use cases are possible today, but not as easy as it would be with an official observation API. Current techniques involve polling with
requestAnimationFrame
.Problem
Given a reference to an element, I'd like to be able to observe property changes on that element in a non-polling fashion.
I could currently make a loop with
requestAnimationFrame
and usegetComputedValue
inside of it, like this:JSFiddle demo
But this is not a good approach, because it does not know when the values have actually changed, and so continuously polling in a loop will use CPU over time.
Solution
It would be better to have a push-based approach, so that computed style observers can execute only when style changes actually happen.
Maybe we can add this to
MutationObserver
; it seems like the best place, currently, where such a feature could live.Maybe it would look something like this:
where perhaps
mutation.styleMap
is a "live"StylePropertyMapReadOnly
instance, so that under the hood the engine can be more efficient by always returning that same instance, or something.If we used
MutationObserver
, I think there would only ever be a single item inside themutations
list, unlike with other types of changes. I think we can encourage people to rely only on the last known value of a style property (inside thestyleMap
) in order to do something for next paint.Or maybe, like other observer classes similar to
ResizeObserver
, there could be a separateComputedStyleObserver
class instead of adding this feature ontoMutationObserver
.Other way to achieve it?
Can we use a worklet, which will update on property changes, and somehow allow that worklet to communicate back to the main thread (or other worker thread) the changes that happened, so that we can avoid polling with rAF? Are worklets able to communicate with the main thread or any other thread?
The text was updated successfully, but these errors were encountered: