I recently posted a pen to celebrate the new year and I got a lot of positive feedback on how I used the viewBox as a camera in my scene.
I decided to write a post to explain how I managed to create such animation :)
Happy New Year !
See the Pen Happy New Year ! by Louis Hoebregts (@Mamboleoo) on CodePen.
After opening your gift, click on the little scenes to zoom
What is the viewBox ?
I won't go into details, there are a lot of really good articles about the viewBox on the Internet.
Basically, the viewBox is a portion of your SVG that will ALWAYS be visible.
Everything outside the viewBox may or may not be visible, depending on the size and the ratio of your SVG.
You define the viewBox in the <svg> tag with 4 values :
<svg viewBox="min-x min-y width height">
For more information, check Understanding SVG Coordinate Systems from Sara Soueidan.
Let's get started !
First I will create a simple HTML document with an SVG.
See the Pen Animating the viewBox | Part.1 by Louis Hoebregts (@Mamboleoo) on CodePen.
The viewBox defined on this svg is the exact size of our scene. That means every element of our SVG is inside the viewBox.
Try to resize the window (or the editor panel) and you will see how the SVG scales when you are trying to crop it :)
Updating the viewBox
In this new pen, I drew a red rectangle to show you the new values of the viewBox we are going to apply. Move your mouse over that rectangle to update the viewBox and see how the sVG is repainted.
Magic right ?
Our svg has not changed and all the elements outside the viewBox are still in our page but you can't see all of them anymore.
Because of the size and the ratio of the SVG, you probably can still see some part of the scene on the horizontal axis. (At least with the embedded pen)
See the Pen Animating the viewBox | Part.2 by Louis Hoebregts (@Mamboleoo) on CodePen.
Animating the viewBox
Ok now we know how to update the viewBox but it's not animated at all.
Sadly we cannot animate the viewBox with CSS yet probably in the future, we will need some javascript.
I usually use GreenSockreenSock to create my animations since it's (for me) the best javascript plugin for it.
Here is a simple animation where the viewBox switches from the original values to the rectangle ones.
See the Pen Animating the viewBox | Part.3 by Louis Hoebregts (@Mamboleoo) on CodePen.
Let's see how the animation is set with TweenMax:
gsap.to('svg', {
attr: { // This is the AttrPlugin which updates any attribute on every new frame
viewBox: '220 110 370 350' // We specify the end values of the animation
},
duration: 2,
repeat: -1, // To repeat our animation endlessly
yoyo: true // The animation will go forwards then backwards
});
As you can see, it's really simple to tween the viewBox from one frame to another one. With only just those few lines you can create endless possibilities in you website !
Using the viewBox as a camera
Let's take a look at my Happy New Year pen and how I used the viewBox as a camera to zoom in the little scenes.
I created areas on my SVG which are clickable but visible only on hover. We will use them to trigger events on click on our little scenes.
// Select all my areas
const overlays = svg.querySelectorAll('#overlays > g');
// Add an event Listener on every area
for (let i = 0; i < overlays.length; i++) {
overlays[i].addEventListener('click', zoomViewBox);
}
// This variable will be useful later to check if the viewBox is already zoomed in
let zoom = false;
// I create an object with the values of every area.
// Each key is equal to the ID of one area.
const viewBoxes = {
'overHouses': {
x: 43,
y: 290,
width: 130,
height: 67
},
'overSnowmen': {
x: 250,
[...]
};
When the user click on any area, we call the zoomViewBox() function :
function zoomViewBox(e) {
// If the user clicked on the area when the viewBox is already zoomed
// or if the initial animation is not over yet, we leave our function
if (zoom || !animationOn) {
return;
}
// To prevent other unwanted events
e.stopPropagation();
// Each area has a unique ID which
const id = this.getAttribute('id');
// It's the same code as the previous example,but now the values are not static.
// I am getting them from our 'viewBoxes' object with the ID of the clicked area.
gsap.to(svg, {
attr:{
viewBox: viewBoxes[id].x + " " + viewBoxes[id].y + " " + viewBoxes[id].width + " " + viewBoxes[id].height
},
duration: 2,
ease: 'power3.out'
});
// The SVG is now zoomed in
zoom = true;
}
To allow the user to zoom out, I simply check every click on the SVG, and if the SVG is zoomed in, we call the unZoom() function.
// Listen to every click on our SVG
svg.addEventListener('click', unZoom);
function unZoom() {
// Set the value to false
zoom = false;
//It's again the same animation, but now with the initial values
gsap.to(svg, {
attr: {
viewBox:'0 0 1600 900'
},
duration: 2,
ease: 'power3.out'
});
}
This is of course a summary of the whole Javascript. I encourage you to read the entire code if you are interested !
Examples
Here is an example where three scenes are hidden by the default viewBox and can be visible after the user made a choice.
(Click on RERUN to reset the pen)
See the Pen Animating the viewBox | Part.4 by Louis Hoebregts (@Mamboleoo) on CodePen.
Another example from David Bachmann Johannesson you may have already seen on CodePen
Animating the viewbox - David Bachmann Johannesson
See the Pen Animating the viewbox by David Bachmann Johannesson (@dbj) on CodePen.