library(minisvg)
library(svganim)

Introduction

There are at least 5 methods of animating SVG. These methods are detailed on the w3.org pages).

The 5 methods are as follows:

  1. SMIL - Synchronized Multimedia Integration Language. MDN doc
  2. CSS Animations w3 css animation reference
  3. CSS Transitions w3 css transitions reference
  4. SVG DOM manipulation via scripting w3 reference
  5. Web Animation w3 web animation reference

This package (and this vignette) uses SMIL to animate the SVG by including animation specific tags witin objects.

This vignette assumes you are familiar with SVG tags and document structures.

SMIL animation

SMIL stands for Synchronized Multimedia Integration Language.

The way it works is to add an animate, animateTransform or animateMotion tag as a child of the element to be animated.

  • <animate /> - specifies an attribute on the parent object and how it should change. e.g. change the radius of a <circle /> element.
  • <animateTransform /> - specifies how the transformation of the parent object should change e.g. change the rotation of the object from 0 to 90 degrees.
  • <animationMotion /> - species how the object moves along a given path.

This package includes a number of pre-baked animation types, and this vignette shows examples of how these animations can be applied to elements.

Create a pattern animation

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a simple pattern using the `svgpatternsimple` package
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
stripes <- svgpatternsimple::create_pattern_stripe(id = 'stripe')

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a pattern rotation animation and add it to the pattern
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
anim1 <- create_anim_pattern_rotation()
stripes$append(anim1)

stripes$save_full_svg("svg/README-stripe-rotation.svg", height = 100)
Show/hide SVG text <pattern id="stripe" width="20" height="20" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse"> <rect width="100%" height="100%" style="fill:#ffffff; fill-opacity:1; stroke:none;" /> <line x1="0" y1="0" x2="0" y2="20" style="stroke:#000000; stroke-width:8; stroke-opacity:1;" /> <animateTransform attributeName="patternTransform" attributeType="xml" from="0 0 0" to="360 0 0" type="rotate" dur="16s" repeatCount="indefinite" /> </pattern>

Animate the pulsing of an object’s outline

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a document in `minisvg`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library(minisvg)
doc   <- minisvg::svg_doc(width = 400, height = 200)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the pulse animation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pulse <- create_anim_pulse_line(size2 = 20)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a rectangle which includes the animation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rect  <- stag$rect(
  x = "10%", y = "10%", width = "80%", height = "80%",
  fill = "blue", stroke = 'black',
  pulse
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add the animated rectangle to the svg document and save
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc$append(rect)
# doc$show()
doc$save("svg/README-example-pulse.svg")
Show/hide SVG text <?xml version="1.0" encoding="UTF-8"?> <svg width="400" height="200" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <rect x="10%" y="10%" width="80%" height="80%" fill="blue" stroke="black"> <animate attributeName="stroke-width" attributeType="XML" dur="4s" repeatCount="indefinite" values="0;20;0" keyTimes="0;0.5;1" /> </rect> </svg>

Animate the rotation of an object

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a document in `minisvg`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library(minisvg)
doc   <- minisvg::svg_doc(width = 400, height = 200)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the rotation animation around a particular point
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rotation <- create_anim_rotation(cx = 200, cy = 100)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a rectangle which includes the animation
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rect  <- stag$rect(
  x = "10%", y = "10%", width = "80%", height = "80%",
  fill = "blue", stroke = 'black',
  rotation
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add the animated rectangle to the svg document and save
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc$append(rect)
# doc$show()
doc$save("svg/README-example-rotation.svg")
Show/hide SVG text <?xml version="1.0" encoding="UTF-8"?> <svg width="400" height="200" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <rect x="10%" y="10%" width="80%" height="80%" fill="blue" stroke="black"> <animateTransform attributeName="transform" attributeType="xml" from="0 200 100" to="360 200 100" type="rotate" dur="16s" repeatCount="indefinite" /> </rect> </svg>

Anply multiple animations to an object

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a document in `minisvg`
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library(minisvg)
doc   <- minisvg::svg_doc(width = 400, height = 200)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create the motion animated along the path given by xs, ys
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
path_motion <- create_anim_motion(xs = c(20, 180, 180, 20), ys = c(20, 20, 80, 80))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create a rectangle which includes multiple animations
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rect  <- stag$rect(
  x = "10%", y = "10%", width = "20%", height = "20%",
  fill = "blue", stroke = 'black',
  path_motion, 
  pulse
)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Add the animated rectangle to the svg document and save
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
doc$append(rect)
# doc$show()
doc$save("svg/README-example-pathmotion.svg")
Show/hide SVG text <?xml version="1.0" encoding="UTF-8"?> <svg width="400" height="200" viewBox="0 0 400 200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <rect x="10%" y="10%" width="20%" height="20%" fill="blue" stroke="black"> <animateMotion path="M 20 20 L 180 20 L 180 80 L 20 80 Z" dur="4s" repeatCount="indefinite" /> <animate attributeName="stroke-width" attributeType="XML" dur="4s" repeatCount="indefinite" values="0;20;0" keyTimes="0;0.5;1" /> </rect> </svg>