-
Notifications
You must be signed in to change notification settings - Fork 473
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
Change Path interpolation so that it can interpolate between paths of different sizes #990
Comments
Optimizing Flubber to work with the Skia API a bit deeper might be easier than expected. the interpolate function has a fun no? I'll keep this issue open for now as we might provide an example in the near future on how to achieve this. |
If you are interested of what flubber does behing the scene, this article is a create intro: https://css-tricks.com/rendering-svg-paths-in-webgl/ |
Did you try to generate the path at |
Yeah, I have something like (I think this is what you're referring to) const start = graphData[graphState.current.current].lineGraph;
const end = graphData[graphState.current.next].lineGraph;
return end.interpolate(start, graphTransition.current) ?? Skia.Path.Make(); and it's not working. I can also see when I check with This is probably because the two lineGraphs (both Thanks for the other suggestions as well. I'm not sure how I'll change my code from the |
That's quite interesting. This is because:
So
And
Which makes a lot of sense. At 0 and 1 you want to display the original path, not the triangulated one. |
this function seems to work like a charm: const Flubber2SkiaInterpolator = (interpolator: (t: number) => string) => {
const d = 1e-3;
const i0 = Skia.Path.MakeFromSVGString(interpolator(0))!;
const i01 = Skia.Path.MakeFromSVGString(interpolator(d))!;
const i1 = Skia.Path.MakeFromSVGString(interpolator(1))!;
const i11 = Skia.Path.MakeFromSVGString(interpolator(1 - d))!;
console.log(i01.isInterpolatable(i11));
return (t: number) => {
if (t < d) {
return i0;
}
if (1 - t < d) {
return i1;
}
return i11.interpolate(i01, t)!;
};
};
const leftInterpolator = Flubber2SkiaInterpolator(
interpolate(
"M 8 125 C 3.5 123 0.4 118.6 0 113.6 V 12.7 C 0.2 10.3 1 7.9 2.4 5.9 C 3.9 3.9 5.8 2.3 8 1.3 C 9.8 0.4 11.8 0 13.7 0 C 14.2 0 14.7 0 15.1 0.1 C 17.6 0.3 19.9 1.2 21.9 2.7 L 50 22 V 104.3 L 21.9 123.6 C 20.3 124.8 18.5 125.6 16.6 126 H 10.9 C 9.9 125.8 8.9 125.5 8 125 Z",
"M 16.7 0 C 12.2 0 8 1.8 4.9 4.9 C 1.8 8 0 12.2 0 16.7 V 105.6 C 0 110 1.8 114.2 4.9 117.3 C 8 120.5 12.2 122.2 16.7 122.2 C 21.1 122.2 25.3 120.5 28.5 117.3 C 31.6 114.2 33.3 110 33.3 105.6 V 16.7 C 33.3 12.2 31.6 8 28.5 4.9 C 25.3 1.8 21.1 0 16.7 0 Z"
)
);
const left = useComputedValue(() => {
const pathLeft = leftInterpolator(progress.current);
return pathLeft;
}, [progress]); This is like super fun no? I'm closing the issue for now but feel free to reopen if needed. |
This is very interesting and fun indeed! Thanks for taking the time to write this. So the way I understand this is that with Flubber, even though the start and end paths are of different sizes, all the intermediate paths (during the transition) are of the same size and that's the reason why we can use Skia to interpolate the intermediate paths. I did manage to run this in my project but unfortunately the Flubber algorithm doesn't work nicely with my use case (animating line graphs) - see veltman/flubber#99. In my case Flubber added a connection between the start and end point of the line graph, which looked odd during the transition. The algorithm provided by Polymorph looks a lot nicer - i.e. it handles polylines better. But I don't think I can use that library in a similar way as you described since it differs from Flubber in that the intermediate paths can also have different sizes. I.e. in the case of Polymorph, In any case, all I wanted was a nice animation when transitioning from one line graph to another and I ended up |
I feel like you're not trying to interpolate heterogeneous shapes but rather charts which have different number of data points. Maybe it would be easier to add the missing datapoints manually? I'm sure there must be some simple algorithm/lib that can help you to do it. |
Yeah, that's a good idea. So if line graph A has 10 points and line graph B has 100 points, I could "fake" A during the transition so that it now has 100 points but looks the same way as before and then use Skia to interpolate as normal. |
@Jorundur Have you end up doing some tests for adding data points before the interpolation? I'm planning to give it a try and solve the issue this way. |
@marcocaldera Unfortunately I haven't done that, I figured out a different way of animating the path change which I was happy with and which didn't require interpolation (by animating the But I'm curious to see your implementation if you were successful in trying this out! |
Hi @wcandillon , Thanks in advance. |
I've been trying to get this to work with the interpolating example in the repo and I'm not sure how to make it work with the recipe. @Jorundur You mentioned you were able to get @wcandillon You mentioned if (!path.isInterpolatable(currentPathRef.current)) {
const pointsToAdd = path.countPoints() - currentPathRef.current.countPoints()
console.warn('Paths must have the same length. Skipping interpolation.', pointsToAdd)
const path1 = new P.Path(animatedPath.current.toSVGString()) // polymorph-js
console.log('path1', path1)
const path2 = new P.Path(path.toSVGString())
console.log('path2', path2)
const newPath = P.interpolate([path1, path2], { // crashes
addPoints: pointsToAdd,
origin: { x: 0, y: 0 },
optimize: 'fill',
precision: 0,
})(0.5)
return
}
currentPathRef.current = animatedPath.current
nextPathRef.current = path
runSpring(
progress,
{ from: 0, to: 1 },
{
mass: 1,
stiffness: 500,
damping: 400,
velocity: 0,
},
) |
Description
Current functionality
endPath.interpolate(startPath, transition.current);
if the two paths have the same number of pointsisInterpolatable
to check whether or not we can interpolateDesired functionality
Current workaround
interpolate
function.Can the algorithm that is used in e.g.
Polymorph
or another similar path morphing library be added to the path interpolate function we have in Skia so as to do it natively?The text was updated successfully, but these errors were encountered: