Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

shape.getClientRect() is not updated after layer.cache() #1759

Open
VanquishedWombat opened this issue May 9, 2024 · 2 comments
Open

shape.getClientRect() is not updated after layer.cache() #1759

VanquishedWombat opened this issue May 9, 2024 · 2 comments

Comments

@VanquishedWombat
Copy link
Contributor

The shape.getClientRect() function should return the rect relative to the canvas element.

In cases of large number of shapes we suggest for performance reasons to cache the layer.

If we apply scale to the stage after caching the layer we expect shape.getClientRect() to return a different value than the initial one.

The issue is that after layer.cache() the shape.getClientRect() is unchanged. This is unexpected behaviour and not consistent.

Under the covers Konva uses caching of absolute transforms. When a container such as layer is cached, for performance reasons the descendant nodes do NOT have their absolute transform cache value reset.

Proposed solution: Could it be possible to mark the cached absolute transform values of the descendent nodes as dirty - there is already code for this. The idea would be that when we next call for a shape.getClientRect() it's abs transform would be recalculated because it was flagged as dirty. This would cause the same process up the ascendent chain, and so we would get a correct client rect. This would add some overhead but as it is solely resetting the dirty flag or clearing the cached values, it is data-only rather than any redrawing or processor heavy work.

Version: Konva 8 & 9.

Demo: https://codepen.io/JEE42/pen/RwmwpMx?

@VanquishedWombat
Copy link
Contributor Author

I wrote a small test demo for my proposed solution and it appears to work.

function clearCachedTransform(node){
  node._clearCache('absoluteTransform')   // <<<< this is an existing Konva method
  
  if (['Layer','Group'].includes(node.getClassName())){
    for (const child of node.getChildren()){
      doClearCachedTransform(child)
    }
  }  
}

What we need to do is call this when a container (stage / layer / group) is cached It clears the cached version of the absolute transform for the container and all descendants. Next time we ask for a getClientRect() the absolute transform is re-assembled and re-cached for the entire parent chain up to the node initially passed in to the function.

I have a hunch that this is only needed when the caching us after a new transform is applied. I came across the issue in a case where I cached a layer then scaled it and I was looking at a child shapes client rect, noticing it should have but did not change after the layer was scaled. I therefore expect than any transformation of the layer which would have the effect of moving the child shapes from the perspective of the canvas element would require this cached absolute transform reset approach.

Just for interest, in my codepen demo with 19952 shapes the caches are cleared in less than 5ms - this is with all the codepen bloat loaded so should be faster in leaner cases.

@VanquishedWombat
Copy link
Contributor Author

Update - as proposed in my last comment, the issue of caching the absolute transform appears to also be present when I drag the stage. Remember it is the layer that is cached and the layer is translated (in the perspective of the canvas) with the stage drag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant