Is it possible to scale a lottie file with call `d3.zoom()?
I tried it with these examples on codepen but wasn’t successful.
Thanks a lot for your help!
I don’t think that Lottie is a library that folks here are likely to have a lot of experience with. Also, your “examples on codepen” link points to a page on the D3 in Depth site.
It does appear, though, that there is a Hello lottie-web notebook here on Observable - one that’s been forked many times. Inspecting that notebook, it appears that Lottie produces SVG, which is easily manipulated by D3. In particular, we can create an SVG with a g
element, load a Lottie animation into that g
element, then call d3.zoom
on the containter SVG.
Here’s that strategy in action:
Thanks a lot for your help!
To me, D3 and Lottie seem to be a dream-team that combines the programming power of d3 and the design features of After Effects=>Lottie.
I did a proper Codepen with a linked Lottie file.
The only problem I have: I cannot figure out why the zoom center is not under the cursor when pinch zoomed…
In your definition of handleZoom
, you’ve got:
function handleZoom(e) {
d3.select('svg g')
.attr('transform', e.transform);
}
If you change that to
function handleZoom(e) {
d3.select('svg svg')
.attr('transform', e.transform);
}
I think it will work as you expect.
The setup seems a little awkward. You’ve got an
<svg class="lottie"></svg>
in your HTML. You then call lottie.loadAnimation
on that SVG, which produces another SVG nested inside your original. I guess that’s not how Lottie usually works but we’re essentially using it to our advantage here.
Great, thank you very much! The zoom problem is solved.
And I would like not to have the awkward SVG in the SVG issue, but I wasn’t able to get it right with putting the Lottie-SVG directly in a DIV. Every time I tried, the D3-zooming went crazy. But if someone sees a solution, I would very much appreciate.
I think that a better solution might be to set up your HTML structure as follows:
<div class="divclass">
<svg class="lottie">
<g id="zoom"></g>
</svg>
</div>
You can then load the animation into that g
element:
lottie.loadAnimation({
container: document.querySelector("#zoom"),
...
})
The handleZoom
function should then modify that g
element:
function handleZoom(e) {
d3.select('g#zoom')
.attr('transform', e.transform);
}
You still have nested SVGs but that’s no problem, as svg
is a legal SVG element.
I think this is preferable because you’re no longer modifying the SVG that was produced by Lottie. That SVG might, for example, have a transform
attribute that you don’t want to overwrite. That was the case in the original example I wrote, which is why I put the g
element in there then.
Super helpful again, thank you very much! It works perfectly.
I’m looking forward to making projects with D3 and Lottie.
Best regards from Switzerland