+ - 0:00:00
Notes for current slide
Notes for next slide

canvas

 

an intro to web graphics with html5

 

Kai Chang
bl.ocks.org/syntagmatic

1 / 33

Julia Set

2 / 33

3 / 33

Exoplanets

Extrasolar planets, their discovery method and characteristics in parallel coordinates.

Data from the NASA Exoplanet Archive.

4 / 33
5 / 33
6 / 33
The electric light is pure information.
It is a medium without a message, as it were, unless it is used to spell out some verbal ad or name.
Marshall McLuhan
7 / 33
8 / 33
The canvas is the door to another dimension.
The paintbrush is the key.
Luhraw
10 / 33
The HTML5 canvas is the door to another dimension.
The paintbrush Javascript is the key.
Kai
11 / 33

Canvas

  • Used for drawing graphics in the browser
  • Pixel-based (bitmap of rgba image data)
  • Procedural, immediate Mode
  • This talk is about the 2D Context
  • There is also a 3D WebGL Context

JavaScript

  • Call methods on the Canvas context
  • Load, parse, draw data
  • Data structures: Arrays, Objects, Strings, Numbers
  • Functions for data transformation, drawing subroutines

Applications

  • Generative art
  • Data visualization
  • Web-based games
  • Drawing and image editing apps
12 / 33

Can I use?

13 / 33

A Blank Canvas

We need a canvas element to draw on:

<canvas id='painting' width=960 height=500></canvas>

And a canvas context to render to:

<script type='text/javascript'>
var canvas = document.getElementById('painting')
var context = canvas.getContext('2d')
// draw on pixels here
</script>
14 / 33

Rectangles

Rect arguments:

  • x
  • y
  • width
  • height
<script type='text/javascript'>
var canvas = document.getElementById('painting')
var context = canvas.getContext('2d')
context.fillStyle = "mediumseagreen"
context.fillRect(500,20,200,600)
context.fillStyle = "darkorchid"
context.fillRect(200,200,600,60)
context.fillStyle = "deepskyblue"
context.fillRect(400,180,60,300)
</script>
15 / 33

Lines

Move a cursor around with moveTo and lineTo

context.strokeStyle = "#f5b"
context.lineWidth = 3
context.beginPath()
context.moveTo(150,250)
context.lineTo(200,100)
context.lineTo(250,175)
context.lineTo(300,100)
context.lineTo(350,250)
context.stroke()

 

16 / 33

Lines

Close shapes with closePath()

context.strokeStyle = "#5738FF"
context.lineWidth = 3
context.beginPath()
context.moveTo(150,250)
context.lineTo(200,100)
context.lineTo(250,175)
context.lineTo(300,100)
context.lineTo(350,250)
context.closePath()
context.stroke()

 

17 / 33

Shapes

The same as lines, just using fill instead of stroke

context.fillStyle = "#15673D"
context.beginPath()
context.moveTo(150,250)
context.lineTo(200,100)
context.lineTo(250,175)
context.lineTo(300,100)
context.lineTo(350,250)
context.closePath()
context.fill()

 

18 / 33

Circles

Arc arguments:

  • x
  • y
  • r
  • start angle
  • end angle
context.fillStyle = "crimson"
context.beginPath()
context.arc(800,250,450,0,2*Math.PI)
context.fill()
context.fillStyle = "steelblue"
context.beginPath()
context.arc(50,250,50,0,2*Math.PI)
context.fill()
19 / 33

Creating words

function circle(x,y,radius,color) {
context.fillStyle = color
context.beginPath()
context.arc(x,y,radius,0,2*Math.PI)
context.fill()
}
20 / 33

Creating words

Filling circles (again)

circle(800,250,450,"crimson")
circle(800,250,450,"steelblue")
function circle(x,y,radius,color) {
context.fillStyle = color
context.beginPath()
context.arc(x,y,radius,0,2*Math.PI)
context.fill()
}
21 / 33

Animation

 

<script src="https://d3js.org/d3.v4.js"></script>
<script>
d3.timer(function() {
// redraw all the things!
})
</script>
22 / 33

Animation

 

var canvas = document.getElementById('painting')
var context = canvas.getContext('2d')
// center the animation
context.translate(canvas.width/2, canvas.height/2)
d3.timer(function(t) {
var x = Math.cos(t/2000*Math.PI) * 120
var y = Math.sin(t/2000*Math.PI) * 120
var color = "hsl(" + (Math.floor(t/30)%360) + ",80%,60%)"
circle(x,y,40,color)
})
function circle(x,y,radius,color) {
context.fillStyle = color
context.beginPath()
context.arc(x,y,radius,0,2*Math.PI)
context.fill()
}
23 / 33

Animation

 

 

Use clearRect to erase previously drawn areas of the canvas

 

var canvas = document.getElementById('painting')
var context = canvas.getContext('2d')
// center the animation
context.translate(canvas.width/2, canvas.height/2)
d3.timer(function(t) {
context.clearRect(-canvas.width/2,
-canvas.height/2,
canvas.width,
canvas.height)
var x = Math.cos(t/2000*Math.PI) * 120
var y = Math.sin(t/2000*Math.PI) * 120
var color = "hsl(" + (Math.floor(t/30)%360) + ",80%,60%)"
circle(x,y,40,color)
})
function circle(x,y,radius,color) {
context.fillStyle = color
context.beginPath()
context.arc(x,y,radius,0,2*Math.PI)
context.fill()
}
24 / 33

Particle Trails

Clearing the canvas by filling a transparent rect can be used to create a whimsical trail effect

d3.timer(function() {
context.fillStyle = 'rgba(255,255,255,0.3)'
context.fillRect(0, 0, canvas.width, canvas.height)
// redraw all the things!
})
25 / 33

That's right, Particle Trails!

And torus wrapping!

26 / 33

Bar Chart

 
Set up the canvas
 
Make some data
 
Color pink
 
Draw the bars
 
These "magic numbers" shape and scale the chart

 

<canvas id='painting' width=100 height=500></canvas>
<script>
var canvas = document.getElementById('painting')
var context = canvas.getContext('2d')
var data = [1, 1, 2, 3, 5, 8, 13, 21, 34]
context.fillStyle = "#f5b"
data.forEach(drawBar)
function drawBar(d,i) {
var x = 10*i
var y = 190
var width = 8
var height = -5*d
context.fillRect(x,y,width,height)
}
</script>
27 / 33

Compositing

Changes the way colors combine when overlapping shapes are rendered.

context.globalCompositeOperation = "source-over" // default

context.globalCompositeOperation = "multiply"

context.globalCompositeOperation = "screen"
28 / 33

Mapmaking

var projection = d3.geoAlbersUsa()
var path = d3.geoPath()
.projection(projection)
.context(context)
var color = d3.scaleThreshold()
.range(["#fde0dd", "#fcc5c0",
"#fa9fb5", "#f768a1",
"#dd3497", "#ae017e",
"#7a0177","#49006a"])
.domain([250, 500, 750, 1000, 1250, 1500, 1750, 2000])
context.strokeStyle = "#fff"
context.lineWidth = 0.3
countGeojson.forEach(function(d) {
context.fillStyle = color(d["Crude Rate"])
context.beginPath()
path(d)
context.fill()
context.stroke()
})
30 / 33

Science Satellites

d3.timer(function(elapsed) {
// run time at 151x speed
var time = new Date(now.getTime() + 150*elapsed)
data.forEach(function(d) {
plotSatellite(d, time)
})
})
function plotSatellite(d, time) {
var position = satellite.propagate(sat, time).position
var groundPosition = satellite.geodetic(position, time)
drawSat(sat, groundPosition)
}

Note: this bit is pseudo-code.

Click here for a live version.

31 / 33

Thank you Øredev

Now go draw some rects!

33 / 33

Julia Set

2 / 33
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow