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

stable clip paths #1624

Merged
merged 5 commits into from
Aug 5, 2024
Merged

stable clip paths #1624

merged 5 commits into from
Aug 5, 2024

Conversation

Fil
Copy link
Contributor

@Fil Fil commented May 24, 2023

new description!

By using (and reusing) the same clip-path when two renders are clipped with the same shape, we get:

  • smaller files
  • better performance during pointer interactions

Tested manually against #1623. The only reason why I based this PR on #1623 originally is that this forms a good test case: demo); for the same reason, merging this will change the snapshots for the new tests added in #1623, but they are independent concerns.

@Fil Fil requested a review from mbostock May 24, 2023 06:00
@Fil Fil changed the title unique clip paths stable clip paths May 24, 2023
@Fil Fil force-pushed the fil/voronoi-initializer branch 3 times, most recently from d4192ad to 4a6ef93 Compare August 21, 2023 08:20
@Fil Fil changed the base branch from fil/voronoi-initializer to main August 22, 2023 16:33
@Fil Fil force-pushed the fil/clip-path-perf branch 2 times, most recently from d99190a to 6f95488 Compare September 13, 2023 14:56
@Fil Fil marked this pull request as draft September 13, 2023 22:41
@Fil

This comment was marked as outdated.

@Fil Fil marked this pull request as ready for review September 14, 2023 09:29
@Fil
Copy link
Contributor Author

Fil commented Sep 14, 2023

This seems ready now.

@Fil
Copy link
Contributor Author

Fil commented Aug 1, 2024

rebased

src/style.js Outdated
break;
}
case "sphere": {
const clips = context.clips ?? (context.clips = new Map());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These probably shouldn’t be exposed publicly on the context. Maybe use a WeakMap keyed by the context instead of assigning to a new property on the context? (Also note that the Context interface is publicly documented in context.d.ts.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there only at most two keys in the clip cache (frame and projection)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently yes, these are the only keys; related: #1109

src/style.js Outdated Show resolved Hide resolved
@Fil
Copy link
Contributor Author

Fil commented Aug 5, 2024

This was clearly over engineered. I don't think we even need a WeakMap, as we could just do a quick check through the DOM with querySelector; we just need to pass the type of clip (frame, sphere) in a class or in the id, then select against it e.g. with [id^=plot-clip-sphere-].

@mbostock
Copy link
Member

mbostock commented Aug 5, 2024

I don't think we even need a WeakMap, as we could just do a quick check through the DOM with querySelector

Why do you think that (going through the DOM) is simpler or faster than a WeakMap?

@Fil
Copy link
Contributor Author

Fil commented Aug 5, 2024

Using the DOM feels simpler [information-wise], in the sense that we wouldn't need to track the association of type of clip and clipPath in parallel, as we could just look it up. (It's hard to remember what I had in mind a year ago, though — I think I was probably trying to change the output as little as possible.) But I'm happy with this version too.

@mbostock
Copy link
Member

mbostock commented Aug 5, 2024

Using the DOM feels simpler [information-wise], in the sense that we wouldn't need to track the association of type of clip and clipPath in parallel, as we could just look it up.

I don’t follow that the DOM is simpler. In the DOM approach, you have to use some (serializable) identifier in the DOM such as an id prefix ([id^=plot-clip-sphere-]), and then use querySelector to find it. In the WeakMap approach, you use a symbolic identifier (the reference to the WeakMap) and you use map.get to find it. The main difference I see is that the WeakMap approach is completely symbolic and hidden, whereas the DOM approach exposes its implementation, and requires pattern matching or other messiness via querySelector since it’s not a symbolic reference.

@mbostock
Copy link
Member

mbostock commented Aug 5, 2024

The way I think about the WeakMap is that there’s a context.frameClip and context.projectionClip property that are lazily set in getFrameClip and getProjectionClip. The only thing the WeakMap provides is that these properties aren’t publicly exposed.

@Fil
Copy link
Contributor Author

Fil commented Aug 5, 2024

Makes sense; you're right that there is as much tracking in both cases, just differently. To be clear my comment about over engineering was about the original introduction of the parallel tracking with Map; I could have used a className instead, but indeed it would have been visible in the output.

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

Successfully merging this pull request may close these issues.

2 participants