"Rendering Tale:

 Comparing SVG, Canvas, WebGL (and CSS)

@vincentntang  : twitter

About Me

About Me

Some clients

Work

<disclaimer>

Fundamentals

Showcase Examples

Why?

Web makes communication standards easier

The ones that do it best have

 great UX design and Animations

mastery requires knowledge in:

SVG, Canvas, WebGL (and CSS)

Software solves problems

...opens oppurtunities for bigger, meaningful projects (dev/agency). 

Goal of Talk

  • SVG, Canvas, WebGL
  • Low Level
  • High Level
  • Examples (Business, Practical)
  • Tooling
  • Performance
  • <disclaimer>
  • Creative Agency
  • Tooling Visualization

Images Vs Vectors

Canvas

  • One DOM Element
  • Requires Javascript
  • Raster Based
  • Animate by calling a function
  • Not portable

SVG

  • Multiple DOM Elements
  • Does not require javascript
  • Vector Based
  • Animate by modifying it's DOM attribute
  • Very portable, copy paste HTML

When to use SVG?

  • Copypaste SVG assets from https://www.flaticon.com/ instead of fontawesome
  • Don't want to use CSS sprites on a page
  • Don't want to use images
  • Need to make a simple CRUD app
  • Using something like d3.js for data viz
  • Don't mind using the extra HTML markup

Canvas+SVG

  • Open maps
  • https://tympanus.net/codrops/2015/12/16/animated-map-path-for-interactive-storytelling/

SVG

SVG is an XML based vector image format for 2-dimension graphics with support for interactivity and animation. SVG specification was developed by W3C in 1999

 

- Wikipedia

Scalable Vector Graphics

Can be rendered in any size and resolution

Comprised of vectors drawn with strokes and fill

graphics

Bitmap vs SVG

SVG are native markup documents written in native webcode

SVGs are styled with CSS and controlled by Javascript

SVG is standard graphics format

  • Create and edit SVG in sketch, adobe illustrator, etc
  • Display SVG in image viewers and web browsers
  • SVG is an open format you can use as any vector based graphic - not limited to just web graphics

Pros

Pros:

  • Scales on any display
  • Less HTTP requests to handle
  • Small file size
  • Many ways to animate
  • Its just HTML markup
  • Portable
  • Data Visualization
<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">
 <rect x="10" y="5" fill="white" stroke="black" width="90" height="90"/>
 <circle fill="white" stroke="black" cx="170" cy="50" r="45"/>
 <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>

3 Ways to use SVG

  • Inline
  • Embedded with CSS background
  • Image `src`

Animating in VanillaJS


    //  Returns the bezier points for a smile. Scale is 0-1.
      function smilePoints(scale) {
        const factor = scale * 2 - 1; // i.e sad = -1, happy = +1
        const p1 = { x: -20, y: -10 * factor };
        const c1 = { x: -20, y: 10 * factor };
        const p2 = { x: 20, y: -10 * factor };
        const c2 = { x: 20, y: 10 * factor };
        return [p1, c1, c2, p2];
      }

      function writeSmilePoints(points) {
        console.log(points);
        const p = p => `${p.x},${p.y}`; // write a point as a coord
        return `M${p(points[0])} C${p(points[1])} ${p(points[2])} ${p(
          points[3]
        )}`;
      }

      function scaleSmile(scale) {
        //  Get the geometry of the new smile.
        const points = writeSmilePoints(smilePoints(scale));
        const svg = document.getElementById("svg");

        //  Create the geometry animation, which will look summat like this:
        //  <animate attributeName="d" attributeType="XML"
        //    to="M-20,10 C-20,-10 20,-10 20,10" dur="3s" repeatCount="indefinite"
        //    fill="freeze" />
        const smilePath = document.getElementById("smilepath");
        const animate = document.createElementNS(svg.namespaceURI, "animate");
        animate.setAttribute("attributeName", "d");
        animate.setAttribute("attributeType", "XML");
        animate.setAttribute("to", points);
        animate.setAttribute("dur", "0.3s");
        animate.setAttribute("repeatCount", "1");
        animate.setAttribute("fill", "freeze");
        smilePath.appendChild(animate);
        animate.beginElement();
      }

      function onChange() {
        //  Get the slider value, scale it from percentage to 0-1.
        const val = this.value;
        const scale = parseInt(val, 10) / 100;
        scaleSmile(scale);
      }
      <svg id="svg" viewbox="0 0 120 120">
        <g id="face" transform="translate(60 60)">
          <!-- Yellow Background-->
          <circle
            id="facecircle"
            cx="0"
            cy="0"
            r="50"
            stroke="#000000"
            stroke-width="2"
            fill="#FAD257"
          />
          <!-- Left Eye, Right Eye-->
          <circle cx="-20" cy="-10" r="5" fill="#000000" />
          <circle cx="20" cy="-10" r="5" fill="#000000" />
          <!-- Smile -->
          <g id="smile" transform="translate(0, 25)">
            <path
              id="smilepath"
              fill="none"
              stroke="#000000"
              stroke-width="3"
              stroke-linecap="round"
              d="M-20,-10 C-20,10 20,10 20,-10"
            />
          </g>
        </g>
      </svg>

Hand Code

From Adobe Illustrator, Sketch, etc

JS Library - e.g. Anime.js

3 ways to animate SVGs

  1. Transition / states
  2. CSS Keyframes / Animation
  3. JS to manipulate `attr` data

SMIL

tanuki-nose {
  fill: #e24329;
  transition: all 0.8s;
}
.tanuki-nose:hover {
  fill: #f1a699;
  transition: all 0.1s;
}
svg {
  animation: grow 5s infinite;
}
@keyframes grow {
  50% {
    transform: scale(1.5);
  }
}

1. Starting State

2. Ending State

3. Use a library

SVG Animating Tools

- Adobe AfterEffects + Plugin (Lottie, BodyMoving)

AfterEffects + Lottie

AfterEffects + Lottie

SVGator

SVG tool for one-time CSS Animations

AE / Lottie

6 kB

 

Native SVG

~200 kB minified per graphic

SVGator

~32 kB minified

One-time CSS Keyframe

Gifs

 

300kB to 10mb

Can set loop amount

pen by sarah drasner

Examples
d3.js

MIT Scratch

SVG Assets to download

https://www.flaticon.com/

HTML Canvas

HTML Canvas

What is it?

 

- 2011 HTML5 spec, for drawing graphics on a screen

Can I Use?

WebGL

WebGL

Javascript API that enables creation and display of 3D content inside browser using GPU (Graphical processing unit)

 

  • Works in all modern browsers
  • Low level API

CanIuse?

WebGL

A javascript API that enables creation and display of 3D content inside browser using the graphical processing unit (GPU)

 

  • Low Level API
var gl = canvas.getContext("webgl2");

HTML, CSS, Javascript

ThreeJS

Opensource Javascript library that abstracts complexity of webGL for 3D content, making things easier to manage

 

  • Handles linear algebra / matrix-math behind scenes

Hello world WebGL

How it works

Hello World WebGL

How it works

ThreeJS

Examples

1. Scene

2. Camera

3. Renderer

4. Mesh

6. Material

5. Geometry

7. Lights

<Example Code>

Scene Graph

Introduction to Three.js

Breakdown

//FoV, aspect, near, far
var camera = new THREE.PerspectiveCamera(
  75, 
  window.innerWidth/window.innerHeight, 
  0.1, 
  1000
);

camera.position.z = 100;

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
var geometry = new THREE.BoxGeometry(20, 20, 20);
var material = new THREE.MeshLambertMaterial({color: 0xfd59d7});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

var light = new THREE.PointLight(0xFFFF00);
light.position.set(10, 0, 25);
scene.add(light);
var scene = new THREE.Scene();

By Dennis Gaebel.

Loading the data

  // Sets up the scene.
  function init() {

    // Code from previous steps goes here...

    // Load in the mesh and add it to the scene.
    var loader = new THREE.JSONLoader();
    loader.load( "models/treehouse_logo.js", function(geometry){
      var material = new THREE.MeshLambertMaterial({color: 0x55B663});
      mesh = new THREE.Mesh(geometry, material);
      scene.add(mesh);
    });

    // More code goes here next...

  }

three.js examples

  • thingiverse

  • matterport

  • Figma
  • Lucidchart
  • Arcentry - Three.js + vue
  • Google Earth
  • Mapbox
  • Panic Transmit
  • A-Frame (VR Mozilla)
  • Pottermore Hogwarts

ThreeJs ExampleFusion360

Pixi.js

http://ellcreative.com/

OTHER

Simple UX and animation effects

CSS, simple JS, and images, etc

CSS Sprites

  • 10 kb
  • More performant to group many icons over many small SVGs
  • Spritecow.com
  • Ecommerce

Drag and Drop

Parallax

CSS Positioning and Javascript

Fonts and Emojis ⚡

52 kB

Summary

Which tech to use?

WebGL

  • Shader + lighting support

  • 3D + camera

  • Three.js

  • Pixi.js

Canvas

  • Physics Demo
  • A lot of items on screen
  • WebGL fallback

OTHER

  • CSS Sprites
  • Drag and Drop
  • Parallax
  • FontAwesome
  • CSS Positioning
  • CSS Transforms
  • Reveal.JS
  • Animate.css

SVG

  • Compact
  • Portable
  • Flexible
  • Animatable
  • Just HTML / XML
  • Can do pretty much anything
  • Works with canvas/other

It depends.

check for edge cases first.

Cons of each

SVGs

  • Generally requires tooling
  • Performance issues with too many objects

Native WebGL2

  • A lot of boilerplate
  • Complex (GLSL code)
  • Requires GPU
  • Generally requires tooling

Canvas

  • Not portable
  • Most limited of 3 options (cannot use CSS on it, no shaders)

👋 Questions?

Combination Patterns

  • Canvas on top of Canvas - Earthcc
  • Canvas on top of WebGL (mapbox) - hoodmaps
  • SVG + Canvas for Maps
  • SVG with blurring / color effects on top of image
  • React/Vue/Angular as side menus / event listeners, canvas/webgl in center
  • HTML Canvas as fallback to webGL (e.g. pixi.js)

 

CSS

  • Position: absolute
  • Z-index

SVG Resources

 

Some Common Libraries

  • SVG.js
  • Snap.svg
  • D3.js
  • Mo.js
  • Anime.js
  • Morph SVG, DrawSVG, TweenMax (GSAP)
  • Embedded SVG using SCSS (sass-svg)

 

Tooling

  • Adobe Illustrator / Figma / etc
  • Flaticon
  • Drawing by hand
  • AfterEffects / Lottie
  • http://www.heropatterns.com/

Real World SVG Examples

  • Gitlab's Logo
  • Nuclino - AST mapping for notes
  • 16 personalities - Static Logos
  • Curse.com - Animated logos
  • React Redux chrome extension tools
  • Graphviz / mermaidJS
  • Musicnotes.com
  • MIT Scratch / educational K-12 content
  • SVGator
  • 2dimensions.com
  • https://d3js.org/
  • https://gannon.tv/work
  • https://css-tricks.com/what-is-svg-good-for/
  • https://codepen.io/collection/svfAa/10/
  • https://codepen.io/chriscoyier/pen/WRwxYO/
  • https://www.youtube.com/watch?v=z8EppLDkgtw

More Real World SVG

WebGL Resources

 

Libraries / Tooling

  • Three.JS (3D)
  • Pixi.JS (2D)
  • Phaser (2D games)
  • Blender / Maya / Etc
  • Unity /Unreal plugins

 

Deeper Dive in 3D without libraries

Real World WebGL Examples

  • AutoCAD Fusion360 - Three.js
  • Thingiverse - Three.js
  • Figma
  • Lucidchart
  • Arcentry - Three.js + vue
  • Google Earth
  • Mapbox
  • Panic Transmit
  • A-Frame (VR Mozilla)
  • Pottermore Hogwarts
  • WebGL Water test
  • Matterport
  • https://2050.earth/
  • Oil Map
  • https://www.clicktorelease.com/code/cruciform/
  • https://renaultespace.littleworkshop.fr/

 

Anything found from these agencies

  • https://www.littleworkshop.fr/
  • https://www.epic.net/en
  • https://activetheory.net/work
  • https://threejs.org/docs/

Canvas Resources

 

Libraries

  • P5.js
  • Vanilla JS

 

Inspiration

Real World Canvas Examples

 

(real world examples are hard to find)

Addional Resources Comparing Technologies

Examples that don't need webGL, SVG, or Canvas

  • Reveal.js / Slides.com
  • Drag and drop
  • Parallax
  • realthread.com (image overlay on T-shirts)

Animation Resources

Splitting.js

Anime.js 3.0 (really nice docs)

 

Made with Slides.com