nonlogos
1/11/2017 - 5:02 PM

SVG animation with CSS and Greensock

SVG animation with CSS and Greensock

// some basic starter examples
// xmlns is good to keep in for backwards compatibility

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="450px" height="100px" viewBox="0 0 450 100"> // width can be pull out and define in css for responsive 
  <rect x="10" y="5" fill="white" stroke="black" width="90" height="90" />
  <circle fill="white" stroke="black" cx="170" cy="50" r="45" /> //cx: center point on the x axis, cy: center point on the y axis
  <polygon fill="white" stroke="black" points="279,5 294,35 328,40 303,62 309,94 279,79 248,94 254,62 230,39 263,35 " />
  <line fill="none" stroke="black" x1="410" y1="95" x2="440" y2="6" />
  <line fill="none" stroke="black" x1="360" y1="6" x2="360" y2="95" />
</svg>

// polyline: array of points for mapping coordinates or data viz
<polyline points="14,17 136,37 77,117 230,87 132,158 172,158" />
Default: preserveAspectRatio = "xMidYMid meet"
// uniformly scales, like background-size: cover in css
// align the ___ of the element's viewBox with the ___ value of the viewport

Takes two parameters: <align> <meetOrSlice>
x___  Y___  ______
min    min   meet
mid    mid   slice
max    max

Or None

Meet (default):
- Entire viewBox is visible within viewport
- the viewBox is scaled up as much as possible, meeting other criteria
- viewBox < viewport

Slice:
- entire viewport is covered by the viewBox
- the viewBox is scaled down as much as possible, meeting other criteria
- viewBox > viewport
// Resources

- jankfree.org
- advanced performance audits with devTools by Paul Irish
- CSS-Tricks Article: Weighing SVG Animation techniques with benchmarks
// paths and groups

<svg viewBox="0 0 218.8 87.1">
  <g>
    <path d="M7.3 75L25.9 6.8s58.4-6.4 3.5 13-41.1 32.8-11.2 30.8h15.9v5.5s42.6 18.8 0 20.6" /> //no z at the end so it's not closed
    <path d="M133.1 58.2s12.7-69.2 24.4-47.5c0 0 4.1 8.6 9.5.9 0 0 5-10 10.4.9 0 0  12.2 32.6 
    13.6 43 0 0 39.8 5.4 15.8 15.4-13.2 5.5-53.8 13.1-77.4 5.9.1 0-51.9-15.4 3.7-18.6z" />
  </g>
</svg>

// g will group together and can assign group class to a set of grouped elements and move multiple things at once
<g fill="none" stroke="black">
  ...
</g>


// explanation on the letters in path data
for Path letter: (cap: absolute, non cap: relative positioning)

Path letter     Path meaning            Note
M, m            moveTo                  start of the path, start of a new path

L, l            lineTo

H, h            horizontal line drawn
                from current position

V, v            vertical line drawn
                from current position

Ending Paths

Z, z            joins the end of a path  end of the path

// path example

// Curve commands

C, c            cubic-bezier

S, s            refecting cubic-bezier

Q, q            quadratic bezier- where both sides share the same control point

T, t            command control point that's been reflected

A, a            elliptical arc
// SVGs for animation support breakdown
// or how I learned to love the inline

For image src, object, embed, background url, and iframe, you can only designate animation if inside the SVG
But for inline, both SVG animation and interaction are supported
=> so if you are animating your svgs, put it inline in your code

// 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>
1. Platonic Shapes
2. ViewBox
3. PreserveAspectRatio
4. Grouping
5. Drawing Paths
6. SVG on Export
// Media queries for layout and fallback with Modernizr
// break page up to smaller components and resize/rearrange components with diff screen sizes

// media query example element, mobile first

@media (max-width: 825px) {
  .container {
    width: 100%;
  }
}

@media (min-width: 826px) {
  .container {
    width: 825px;
  }
}

// fallback
.inlinesvg .fallback {
  dislay: none;
}

.no-inlinesvg .fallback {
  width: 500px;
  height: 500px;
  display: block;
}
// After export from illustrator, before implementation
// OPTIMIZE!!!

- SVGOMG // preferred
  https://jakearchibald.github.io/svgomg/

- Peter Collingridge's SVG editor // can go in and edit some more
  https://petercollingridge.appspot.com/svg-editor
  
- SVGO / SVGO-GUI // terminal-based
[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; }
}

// No width and height for the SVG itself, instead define it in CSS
.initial {
  width: 50%;
  float: left;
  margin: 0 7% 0 0;
}
// we are using percentage here, but we could also use flexbox

viewBox="0 0 490 474" preserveAspectRatio="xMidYMid meet"
// Define smaller viewBox, put in preserveAspectRatio (tho this is also the default)

// Animation MEDIA Queries
(adjust initial object, affects animation)

[class^="mountain"], [class^="grass"] {
  transform: skew(2deg);
}

@media screen and ( max-width: 500px ) {
  [class^="mountain"], [class^="grass"] {
    transform: skew(1.5deg);
  }
}

// viewbox shift in sprite with javascript
// acts like a window to show and hide the requisite parts of the sprite

var shape = document.getelementById("svg");

//media query event handler
if (matchMedia) {
  var mg = window.matchMedia("(min-width: 500px)");
  mq.addListener(WidthChange);
  WidthChange(mq);
}

function widthChange(mq) {
  if (mq.matches) {
    shape.setAttribute("viewBox", "0 0 490 474");
  } else {
    shape.setAttribute("viewBox", "0 490 500 500");
  }
}
// Elemental Motion
- Further away is less contrast, blurry
- Does the air or environment affect movement
- Reducing precision allows for understanding
- Combine techniques
// Animating with CSS, refresher

// Keyframes

@keyframes animation-name-you-pick {
  0% {
    background: blue;
    transform: translateX(0);
  }
  50% {
    background: purple;
    transform: translateX(50px);
  }
  100% {
    background: red;
    transform: translateX(100px);
  }
}

// Animation properties -shorthand
.ball {
  animation: animation-name-you-pick 2s 2s 3 alternate ease-in-out forwards;
}

// animating SVG with CSS has the following gotchas
- moving the whole SVG instead of the circle
- background doesn't work for SVG, we use fill
- Apply the fill to the circle, not whole SVG

// instead of apply animation to the whole div, we will apply to the circle instead and instead of animating background color, we will use fill. Also make viewBox wider so the circle does not animate out of it

<svg width="200px" height="70px" vewBox="0 0 200 70">
  <circle class="ball2" cx="45" cy="45" r=25" />
</svg>

@keyframes second-animation {
  0% {
    fill: blue;
    transform: translateX(0);
  }
  50% {
    fill: purple;
    transform: translateX(50px);
  }
  100% {
    fill: red;
    transform: translateX(100px);
  }
}  
// Key takeaways

- Target the circle, expend the viewBox, use fill, and remove the fill from the markup