SVG Summit, January 2016
Senior UX Engineer at Trulia
Pieces of the UI move to aid in an informative UX choreography. This can typically be done with well placed CSS, some JS to trigger interactions. Responsive can be achieved with good CSS media queries.
From this CSS-Tricks Article
Another good navigation example at Concrete Matter
This pen.
Used to illustrate concepts in the body of the page, either alongside or on it's own. Most of the basis of this talk is complex standalone animation. JavaScript is recommended for much longer implementations (explained later).
This pen.
Adhering to your branding means motion solves the problem for your users.
This pen.
Ugly storyboards save you time!
This pen.
Start with this technique from Joe Harrison
This pen.
Compare to using text with photos to illustrate an article.
[class^="star"] {
animation: blink 2s ease-in-out infinite both;
}
[class^="dot"] {
animation: blink 5s -3s ease-in-out infinite both;
}
@keyframes blink {
50% { opacity: 0; }
}
.initial {
width: 50%;
float: left;
margin: 0 7% 0 0;
}
We're using percentage here, but we could also use flexbox.
viewBox="0 0 490 474" preserveAspectRatio="xMidYMid meet"
Define smaller viewbox, put in preserveAspectRatio (though this is also the default)
[class^="mountain"], [class^="grass"] {
...
transform: skew(1.5deg);
}
@media screen and ( min-width: 500px ) {
[class^="mountain"], [class^="grass"] {
transform: skew(2deg);
}
}
var shape = document.getElementById("svg");
// media query event handler
if (matchMedia) {
var mq = window.matchMedia("(min-width: 500px)");
mq.addListener(WidthChange);
WidthChange(mq);
}
// media query change
function WidthChange(mq) {
if (mq.matches) {
shape.setAttribute("viewBox", "0 0 490 474");
}
else {
shape.setAttribute("viewBox", "0 490 500 500");
}
};
Acts like a window to show and hide the requisite parts of the sprite
3 of 21 frames.
Shooting on twos.
This pen.
Large Sprite and animate the background position.
Keep it simple.
@keyframes splashit {
100% { background-position: 0 -3046px; }
}
.splash {
background: url(‘splash-sprite2.svg’);
animation: splashit 1.8s steps(21) infinite;
}
/* fallback */
.no-svg .splash {
background: url(‘splash-sprite2.png’);
}
Illustrator, with a template:
Works with Sketch, too.
In an SVG editor with Grunticon
The background rolls through...
Let's use this to our advantage.
/*--extend--*/
.area {
width: 600px;
height: 348px;
}
.fore, .mid, .bk, .container { @extend .area; }
Extend to keep it DRY
.fore {
background: url(‘fore.svg’);
animation: bk 7s -5s linear infinite;
}
.mid {
background: url(‘mid.svg’);
animation: bk 15s -5s linear infinite;
}
.bk {
background: url(‘bkwalk2.svg’);
animation: bk 20s -5s linear infinite;
}
@keyframes bk {
100% { background-position: 200% 0; }
}
Z-index for parallax, consistent bk position,
different length of animation in seconds.
Very easy to implement. SVG stays a consistent size.
here's why...
(I don't work for them and they don't pay me.)
Bad transform origin bug on rotation, soon to be solved in Firefox.
More in this CSS-Tricks article.
Chrome
IE
Firefox
Safari (zoomed)
The issue with longer CSS animations:
This pen.
This pen courtesy of GreenSock.
This pen.
//variable declaration for the global repeated animations
var gear = $("#gear1, #gear2, #gear3");
...
//animation that's repeated for all of the sections
function revolve() {
var tl = new TimelineMax();
tl.add("begin");
tl.to(gear, 4, {
transformOrigin: "50% 50%",
rotation: 360,
ease: Linear.easeNone
}, "begin");
...
return tl;
}
var repeat = new TimelineMax({repeat:-1});
repeat.add(revolve());
function paintPanda() {
var tl = new TimelineMax();
tl.to(lh, 1, {
scaleY: 1.2,
rotation: -5,
transformOrigin: "50% 0",
ease: Circ.easeOut
}, "paintIt+=1");
...
return tl;
}
//create a timeline but initially pause it so that we can control it via click
var triggerPaint = new TimelineMax({
paused: true
});
triggerPaint.add(paintPanda());
//this button kicks off the panda painting timeline
$("#button").on("click", function(e) {
e.preventDefault();
triggerPaint.restart();
});
...
TweenMax.to("#start", 1, {morphSVG:{shape:"#end"},
ease:Linear.easeNone});
TweenMax.to("#start", 1, {morphSVG:{shape:"#end",
shapeIndex:"1"}});
MorphSVGPlugin.convertToPath("ellipse");
function flame() {
var tl = new TimelineMax();
tl.add("begin");
tl.fromTo(blurNode, 2.5, {
attr: {
stdDeviation: 9
}
}, {
attr: {
stdDeviation: 3
}
}, "begin");
var num = 9;
for (var i = 1; i <= num; i++) {
tl.to(fStable, 1, {
morphSVG: {
shape: "#f" + i
},
opacity: ((Math.random() * 0.7) + 0.7),
ease: Linear.easeNone
}, "begin+=" + i);
}
By Blake Bowen
function solve(data) {
var size = data.length;
var last = size - 4;
var path = "M" + [data[0], data[1]];
for (var i = 0; i < size - 2; i +=2) {
var x0 = i ? data[i - 2] : data[0];
var y0 = i ? data[i - 1] : data[1];
var x1 = data[i + 0];
var y1 = data[i + 1];
var x2 = data[i + 2];
var y2 = data[i + 3];
var x3 = i !== last ? data[i + 4] : x2;
var y3 = i !== last ? data[i + 5] : y2;
var cp1x = (-x0 + 6 * x1 + x2) / 6;
var cp1y = (-y0 + 6 * y1 + y2) / 6;
var cp2x = (x1 + 6 * x2 - x3) / 6;
var cp2y = (y1 + 6 * y2 - y3) / 6;
path += "C" + [cp1x, cp1y, cp2x, cp2y, x2, y2];
}
return path;
}
Article about history in computer science.
var poly = document.querySelector("polyline");
var path = document.querySelector("path");
var points = [
100,350,
200,100,
300,350,
400,150,
500,350,
600,200,
700,350
];
poly.setAttribute("points", points);
path.setAttribute("d", solve(points));
var points = [
100,350,
200,150,
300,350,
400,120,
500,350,
600,180,
700,350
];
var points = [
100,350,
200,100,
300,350,
400,150,
500,350,
600,200,
700,350
];
(one source example, The Whole Brain Group)
This pen.
Change the viewbox in JavaScript like we did before:
Media queries for layout, and fallback with Modernizr:
/* media query example element, mobile first */
@media (max-width: 825px) {
container {
width: 100%;
}
}
@media (min-width: 826px) {
.container {
width: 825px;
}
}
/* fallback */
.inlinesvg .fallback {
display: none;
}
.no-inlinesvg .fallback {
width: 500px;
height: 500px;
display: block;
}
Title and associative aria tags: (WIP)
<svg aria-labelledby="title" id="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 765 587">
<title id="title" lang="en">Circle of icons that illustrate Global Warming Solutions</title>
You can also add a title for elements in the SVG DOM
This resource, with support charts.
Also, this article by Dudley Storey.
This pen.
//balloon
function balloonGrow(){
var balloon = $("#balloon");
var radius = balloon.getAttribute("r");
var cySet = balloon.getAttribute("cy");
balloon.setAttribute('r', parseInt(radius) + 10);
balloon.setAttribute('cy', parseInt(cySet) - 10);
//all of the poppingness
if (parseInt(radius) > 125) {
//play the sound for the popping
ion.sound.play("balloon-pop3");
var balloonTl = new TimelineMax();
balloonTl.add("pop");
balloonTl.to("#balloon", 0.05, {
scale: 5,
opacity: 0,
transformOrigin: "50% 50%",
ease: Circ.easeOut
}, "pop");
... //wait and then put it back
setTimeout(function(){
balloon.setAttribute("r", "45");
balloon.setAttribute("cy", "233.5");
}, 200);
}
}
Fun. Remember fun?
(I don't work for them and they don't pay me)
SVG Immersion Podcast and Web Animation Weekly
These Slides:
slides.com/sdrasner/svg-summit