Reputation: 55
I have an SVG file with multiple, sequential animations (1. an arrow appears from left to right; 2. a tirangle grows while changing color; 3. the triangle now shrinks). I want to include the animated SVG file in my quarto presentation (in a single slide), but I do not know how to control the sequence of the animations.
I tried several things, but I can't figure it out. In my previous iterations, when I reached the slide that contains the animated SVG, I got one of these situations: A) all the animation is already finished, or B) I have to manually go to my touchpad and click into the SVG image to get the animation started (which is not what I want: I need to advance the presentation using only the usual spacebar/arrow keys).
I found many examples of how to show animated SVGs in quarto but for some reason, they all include a single animation, not a sequence of events controlled by the presentation workflow.
I need more of a ppt-like slide if you will, where different objects can be animated one by one, triggered by the same default keys in all cases.
Below you can see in the SVG code that the trigger event is 'click' (which makes sense for a website, etc.) but I would like to avoid that and advance each animation using the default key for presentations, which is usually right arrow or spacebar.
<?xml version="1.0" encoding="utf-8" ?>
<svg width="80%" height="80%" viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink"><defs />
<rect x="0" y="0" width="200" height="100" fill="none" stroke="blue" stroke-width="2" />
<text id="text1" x="10" y="40" style="display: none;">Animation</text>
<text id="text2" x="110" y="40" style="display: none;">↔Render</text>
<path id="arrow" d="M 0 0 L 0 50" stroke="red" stroke-width="5" fill="none" style="display: none;">
<animate attributeName="d" from="M 0 0 L 0 50" to="M 0 50 L 200 50" dur="1s" fill="freeze" />
</path>
<path id="triangle" d="M 120 50 L 75 75 L 125 75 Z" fill="red" style="display: none;">
<animateTransform attributeName="transform" type="scale" from="1" to="1.5" dur="1s" fill="freeze" />
<animate attributeName="fill" from="red" to="green" dur="1s" fill="freeze" />
<animateTransform attributeName="transform" type="scale" from="1.5" to="0.5" dur="1s" fill="freeze" />
</path>
<text id="text3" x="10" y="40" style="display: none;">Animation</text>
<script>
const svg = document.querySelector('svg');
const text1 = document.getElementById('text1');
const text2 = document.getElementById('text2');
const text3 = document.getElementById('text3');
const arrow = document.getElementById('arrow');
const triangle = document.getElementById('triangle');
let step = 0;
svg.addEventListener('click', () => {
switch (step) {
case 0:
text1.style.display = 'block';
text2.style.display = 'block';
step++;
break;
case 1:
arrow.style.display = 'block';
arrow.querySelector('animate').beginElement();
step++;
break;
case 2:
triangle.style.display = 'block';
triangle.querySelector('animate').beginElement();
triangle.querySelectorAll('animateTransform')[0].beginElement();
step++;
break;
case 3:
triangle.querySelectorAll('animateTransform')[1].beginElement();
text3.style.display = 'block';
step++;
break;
}
});
</script>
</svg>
Upvotes: 0
Views: 78