-
Notifications
You must be signed in to change notification settings - Fork 1.6k
pattern canvas
The canvas.js module is a simple and robust JavaScript API for the HTML5 <canvas> element, which can be used to generate interactive 2D graphics in a web browser, using lines, shapes, paths, images and text.
The module is part of the pattern package: web | db | en | search | vector | graph.
*Download:* |
*Drawing* | *Data* | Helper functions
|
A canvas.js
animation is written in
JavaScript code as part of a HTML file. It will run in all modern web
browsers (Chrome, Firefox, IE7+, Safari, Opera). Performance may vary
from browser to browser. Animations on mobile devices are (currently)
quite slow.
Below is an example script. The HTML source imports the JavaScript canvas.js
module with the standard set of
drawing commands. Note the <script type="text/canvas">
that defines the animation. It has a setup()
function that will be executed once
when the animation starts, and a draw()
function that will be executed each animation frame.
<!doctype html>
<html>
<head>
<script type="text/javascript" src="canvas.js"></script>
</head>
<body>
<script type="text/canvas">
function setup(canvas) {
canvas.size(500, 500);
}
function draw(canvas) {
canvas.clear();
translate(250, 250);
rotate(canvas.frame);
rect(-150, -150, 300, 300, {fill: color(1,0,0,1)});
}
</script>
</body>
</html>
Functions can have parameters with default values. For example, the
star()
function takes two to five
parameters in the right order (x
, y
, points
,
outer
and inner
). If you supply four parameters, the
fifth parameter assumes a default value (inner=50
). If you need to define the fifth
parameter, you must define all parameters preceding it. Contrarily, some
functions have optional, named parameters. For example, the rect()
function takes four parameters and a
fifth, optional roundness
.
If you want to set roundness
, you must
supply it by name and enclosed in curly braces. If the documentation
mentions other optional parameters you can supply these as well inside
the curly braces, in any order. For example: rect(50,
50,
100,
100,
{roundness:
0.2,
fill:
color(1,0,0)});
You can use the online editor (with syntax coloring
and live editing) for sketching and testing. It runs in Chrome, FireFox
and Safari. You can import example scripts from pattern/examples/07-canvas/
or export new
scripts (remember to change the <script>
link to canvas.js
in the HTML source). The editor
will provide hintz when an error occurs, but the best way to track
errors is to use the browser's developer tools (e.g., FireBug).
pattern/examples/07-canvas/09-class.html
By, default, the canvas origin (0, 0) is located in the upper-left
corner. The origin can be moved (or translated) with the translate()
function, where positive numbers
define the amount of pixels to move right and down.
When the origin is translated to (100, 80), all subsequent shapes drawn at (0, 0) originate from this point. A shape is drawn, rotated and scaled from its top-left corner – except ellipses which are always drawn from their center. |
|
When the origin is translated to (100, 80) and a rectangle with a width of and height of 100 is then drawn at (-50, -50), it will have its center at the origin point, as illustrated in the figure on the left: translate(100, 80) |
The Color
object can be used to store a
color in terms of R,G,B,A channel values (red, green, blue and alpha).
It can be passed to background()
, fill()
and stroke()
to set the current drawing color for
primitives.
A color can be initialized with either four values (R,G,B,A), three
values (R,G,B), two values (grayscale + alpha) or one value (grayscale,
a Color
, or an \[R,G,B,A\]
array). An optional base
parameter defines the range of the given
values (e.g., 0-255 instead of 0.0-1.0). An optional colorspace
defines the color space of the
given parameters: HSB
expects hue,
saturation, brightness and alpha instead of red, green, blue and alpha.
var clr = new Color(r, g, b, a, {base: 1.0, colorspace: RGB});
var clr = new Color(r, g, b);
var clr = new Color(grayscale, a);
var clr = new Color(grayscale);
var clr = new Color(clr);
clr.r // Red value between 0.0-1.0.
clr.g // Green value between 0.0-1.0.
clr.b // Blue value between 0.0-1.0.
clr.a // Alpha value between 0.0-1.0.
clr.rgba() // Returns an array of [R,G,B,A]-values.
clr.map({base: 1.0, colorspace: RGB}) // Returns an array of [R,G,B,A]-values.
clr.rotate(angle) // Returns a new Color.
clr.adjust({hue: 0, saturation: 1, brightness: 1})
clr.copy()
-
Color.map()
returns an array of channel values mapped to the given base and colorspace.
For example:clr.map({base: 255, colorspace: HSB})
yields an\[H,S,B,A\]
array of values between 0-255. -
Color.rotate()
returns a color with hue rotated on the RYB color wheel by the given angle. -
Color.adjust()
returns a color with addedhue
and multipliedsaturation
andbrightness
(values between 0.0-1.0).
The color() function returns a new Color
. The background()
, fill()
and stroke()
functions set the current canvas
background, shape fill and shape outline color respectively. All
subsequently drawn primitives (e.g., lines, ellipses) will use the
current fill and outline color. Each function takes the same parameters
as a Color
object (R,G,B,A | R,G,B |
grayscale + alpha | Color
| \[R,G,B,A\]
). Each function returns its
current setting.
The strokewidth()
function sets the
width of the outline.
color(r, g, b, a, {base: 1.0, colorspace: RGB})
background(r, g, b, a)
fill(r, g, b, a)
stroke(r, g, b, a)
nofill()
nostroke()
strokewidth(width)
A color filter returns a new Color
that
is a variation of the given color, useful for constructing a set of
colors that look aesthetically pleasing together. The darker()
and lighter()
functions modify the color's
brightness in HSB, complement()
returns
the color that is opposite on the RYB color wheel, analog()
returns a random adjacent color on
the color wheel.
darker(clr, step=0.2) // Returns a new Color.
lighter(clr, step=0.2) // Returns a new Color.
complement(clr) // Returns a new Color.
analog(clr, angle=20, d=0.1) // d = random percentage saturation & brightness.
The Gradient
object can be used to
create a smooth LINEAR
or RADIAL
transition between two Color
objects. It can be passed to fill()
instead of a solid color.
var g = new Gradient(clr1, clr2, {type: LINEAR, x: 0, y: 0, spread: 100, angle: 0});
The shadow()
function enables drop
shadows for all subsequently drawn shapes:
shadow(dx=5, dy=5, blur=5, alpha=0.5)
noshadow()
The translate()
function sets the
current origin point for primitives, paths, images and text. By default
the origin is (0, 0), the upper left corner of the canvas. With
translate(100,100)
, the current origin
becomes (100, 100). If translate(-50,0)
is then called, the current origin becomes (50, 100). In the same way,
rotate(30)
followed by rotate(60)
sets the current rotation for all
subsequent shapes to 90°.
The push()
and pop()
functions create a nested branch in the
current transformation state. The effect of translate()
, rotate()
and scale()
after a push()
only lasts until pop()
is called. The reset()
function resets all transformations
(origin (0, 0), no rotation, scale 100%).
translate(x, y) // Push horizontal and vertical offset.
rotate(degrees) // Push angle in degrees.
scale(x, y=None) // Push relative scale: 1.0 = 100%
push()
pop()
reset()
Geometric primitives are the simplest shapes that can be drawn to the canvas: line, rectangle, triangle, ellipse, and two additional shapes, arrow and star.
*line* |
*rect* |
*triangle* |
*ellipse* |
*arrow* |
*star* |
line(x0, y0, x1, y1)
rect(x, y, width, height, {roundness: 0.0})
triangle(x1, y1, x2, y2, x3, y3)
ellipse(x, y, width, height)
arrow(x, y, width)
star(x, y, points=20, outer=100, inner=50)
Drawn primitives will adhere to the current color and transformation
state. The color state can be overridden by passing an optional fill
, stroke
, strokewidth
to the function, for example:
function draw(canvas) {
canvas.clear();
nofill();
stroke(0, 0.25);
strokewidth(1);
rect( 50, 50, 50, 50);
rect(110, 50, 50, 50, {stroke: color(0)});
rect(170, 50, 50, 50);
}
The PathElement
object defines a single
point in a Path
. Its cmd
property defines the kind of segment from
the previous point to this point: MOVETO
, LINETO
, CURVETO
or CLOSE
. For curve segments, the point has
ctrl1
and ctrl2
properties that define the control
handles of the curve:
-
ctrl1
describes the direction and magnitude of the curve starting from the previous point, -
ctrl2
describes the direction and magnitude of the curve ending in this point.
var pt = new PathElement(x, y, cmd);
pt.cmd // MOVETO, LINETO, CURVETO, CLOSE
pt.x // Horizontal offset.
pt.y // Vertical offset.
pt.ctrl1.x
pt.ctrl1.y
pt.ctrl2.x
pt.ctrl2.y
pt.copy() // Returns a copy of the point.
The Path
object contains an array of
PathElement
objects. The points in a
path can easily be traversed in a for
-loop. New points can be added to the path
with the moveto()
, lineto(
), curveto()
methods.
var path = new Path(path=null);
path.array
path.array.push(pathelement)
path.moveto(x, y)
path.lineto(x, y)
path.curveto(x1, y1, x2, y2, x3, y3)
path.closepath()
path.rect(x, y, width, height, {roundness: 0.0})
path.ellipse(x, y, width, height)
path.length() // Returns the length of the path.
path.contains(x, y) // Returns true if (x, y) in path.
path.angle(t) // Returns tangent angle at t.
path.point(t) // Returns PathElement at t.
path.points(amount, {start: 0.0, end: 1.0})
path.draw({fill: Color, stroke: Color, strokewidth: 1.0})
path.copy()
-
Path.points()
andPath.point(
) returnDynamicPathElement
objects.
These are dynamically calculated using linear interpolation based on a given timet
(wheret=0.0
is the start of the path andt=1.0
is the end of the path). -
Path.draw()
draws the path to the canvas.
Optional parameters includefill
,stroke
andstrokewidth
.
The beginpath(
) function starts a new
current path at (x, y). Points can be added to the current path with
moveto()
, lineto()
, curveto()
until endpath()
is called and the path is drawn (or
returned).
The drawpath()
function draws a Path
using the current color and
transformation state. The color state can be overridden by passing an
optional fill
, stroke
and/or strokewidth
to the function.
The findpath()
function takes an array
of \[x,y\]
coordinates (or PathElement
or Point
objects) and returns a smooth Path
.
autoclosepath(close=true)
beginpath(x, y)
moveto(x, y)
lineto(x, y)
curveto(x1, y1, x2, y2, x3, y3)
closepath()
endpath({draw: true}) // Returns a Path.
drawpath(path, {fill: Color, stroke: Color, strokewidth: 1.0})
findpath(points)
The derive()
function iterates over the
points in a path (Path
or array of
PathElement
objects) and passes each
tangent angle and point to a given callback function. The tangent angle
represents the direction of a point in the path. To get the normal (i.e.
perpendicular) of a point, rotate its angle by +90 or -90.
derive(points, callback)
This is useful if you want to have shapes following a path, for example, to fit text on a path:
function setup(canvas) {
path = new Path();
path.moveto(100, 50);
path.curveto(200, 100, 300, 0, 400, 50);
txt = 'pattern canvas.js'; // We'll draw each character separately.
}
function draw(canvas) {
canvas.clear();
fill(0);
fontsize(16);
var i = 0;
var points = path.points(txt.length, {start: 0.05, end: 0.95});
derive(points, function(angle, pt) {
push();
translate(pt.x, pt.y);
rotate(angle);
text(txt[i], -textwidth(txt[i])/2, 0);
pop();
i++;
});
drawpath(path, {fill: null, stroke: [0,0,0,0.5]});
}
Supershape
The supershape()
command can be used to
generate a range of natural-looking shapes (Gielis, 2003).
It returns a Path
that can be drawn
with drawpath()
.
m=3, n1=1.0, n2=1.0, n3=1.0 |
m=1, n1=0.65, n2=0.35, n3=0.35 |
m=16, n1=1.5, n2=0.5, n3=-0.75 |
supershape(x, y, width, height, m, n1, n2, n3, {points: 100, percentage: 1.0})
Drawing functions between beginclip()
and endclip()
are constrained to the
shape of the given path.
beginclip(path)
endclip()
The image()
function draws an image to
the canvas. It can load a PNG, JPEG or GIF from a given URL. However,
images are loaded asynchronously, i.e., the browser is idle while the
image downloads in the background. The safe way is to preload an
Image
object in setup()
. The main draw()
will not be called until all Image
objects in setup()
are ready.
function setup(canvas) {
images = [];
images.push(new Image('http://www.clips.ua.ac.bemedia/pattern_schema.gif'));
}
function draw(canvas) {
canvas.clear();
image(images[0], 0, 0);
}
The Image
object can be used to load an
image from a http://
location (file://
will not work), a data:
string, another Image
, Pixels
, an offscreen Buffer
or a Canvas
. Optionally, it will be rescaled to
the given width and height. Note that for security reasons you cannot
get Pixels
of remote images (i.e., from
a URL on another server).
var img = new Image(path, x=0, y=0, {width: null, height: null, alpha: 1.0});
img.x // Horizontal offset.
img.y // Vertical offset.
img.width // Image width in pixels.
img.height // Image height in pixels.
img.alpha // Image opacity (0.0-1.0).
img.busy() // Still preloading? (true|false)
img.copy()
img.draw(x=0, y=0, {width: null, height: null, alpha: 1.0})
The image()
function draws an image to
the screen. If optional parameters are given, they will take precedence
over any property set in the given Image
.
image(img, x, y, {width: null, height: null, alpha: 1.0})
imagesize(img) // Returns a [width, height]-array.
The Pixels
object can be used to
retrieve an array of R,G,B,A values (0-255) for each pixel in an image.
Values can be modified, after which Pixels.update()
must be called to reflect any
changes to Pixels.array
. The original
image is not modified. A Pixels
object
can be passed to the image()
function
to draw it to the canvas.
var pixels = new Pixels(img);
pixels.width // Image width in pixels.
pixels.height // Image height in pixels.
pixels.array // Array of width * height * 4 values (0-255).
pixels.get(i) // Returns an [R,G,B,A]-array.
pixels.set(i, rgba)
pixels.map(callback)
pixels.update()
pixels.image()
pixels.copy()
-
Pixels.map()
applies a function to each pixel. Function takes (and returns) an\[R,G,B,A\]
-array. -
Pixels.get()
returns pixeli
as an\[R,G,B,A\]
-array with values between 0-255. -
Pixels.set()
sets pixeli
from an\[R,G,B,A\]
-array.
To iterate the pixels row by row:
var p = new Pixels(img);
for (var i=0; i < p.height; i++) {
for (var j=0; j < p.width; j++) {
var rgba = p.get(i * p.width + j);
}
}
The render()
function returns an Image
from the drawing operations in the
given callback function, i.e., a procedural image. This is useful for
example to render a blur effect on a BezierPath
or text.
The filter()
function returns a new
Image
with the given callback function
applied to each pixel. This function takes an \[R,G,B,A\]
-array (base 255) and returns a
new array.
The polar()
function returns a new
Image
based on a polar coordinates
filter (i.e., radial). The given callback is a function(distance, angle)
that returns new
\[distance,
angle\]
-array.
render(callback, width, height)
filter(img, callback)
polar(img, x0, y0, callback)
A range of predefined filters is available, built on Pixels
, render()
, filter()
and polar()
. For example:
normal |
bloom |
blur |
twirl |
Generators
The solid()
function returns an Image
with a solid fill color.
solid(width, height, clr)
Coloring
Coloring filters return a new Image
with modified pixel values:
-
invert()
swaps all the color channels (e.g., black becomes white). -
colorize()
multiples the R,G,B,A channels with a color and adds bias. -
adjust()
modifies the image brightness, contrast, and/or hue. -
desaturate()
returns a grayscale image. -
brightpass()
makes pixels whose luminance falls below the threshold black. -
blur()
returns a blurred image, where radius defines the extent of the effect.
This uses the fast stack blur algorithm.
invert(img)
colorize(img, color=[1,1,1,1], bias=[0,0,0,0])
adjust(img, {hue: 0.0, saturation: 1.0, brightness: 1.0, contrast: 1.0})
desaturate(img)
brightpass(img, threshold=0.5)
blur(img, radius=10)
Alpha Compositing
Alpha compositing filters return a new Image that blend the pixels of
two images. The transparent()
function
applies a solid alpha channel to the image. The mask()
function applies img2
as alpha channel to img1
, where img2
is a grayscale image (black areas =
transparency).
transparent(img, alpha)
mask(img1, img2, dx=0, dy=0, alpha=1.0)
blend(mode, img1, img2, dx=0, dy=0, alpha=1.0)
The blend()
function mixes pixels using
a set of formulas comparable to blend modes in Photoshop:
Mode | Effect |
ADD | Pixels are added. |
SUBTRACT | Pixels are subtracted. |
LIGHTEN | Lightest value for each pixel. |
DARKEN | Darkest value for each pixel. |
MULTIPLY | Pixels are multiplied, resulting in a darker image. |
SCREEN | Pixels are inverted, multiplied, inverted, resulting in a brighter image. |
The dx
and dy
parameters define the offset in pixels of
img2
from the top-left of img1
. Each blend mode is also available as a
separate function: add()
, subtract()
etc., with the same parameters
except mode
.
Lighting
Lighting filters return a new Image
with fringes of light around bright areas ("magic glow"). The glow()
function uses a combination of blur()
and add()
. The bloom()
function uses a combination of brightpass()
, blur()
and glow()
. The radius
defines the extent of the blur. Pixels
whose luminance falls below the threshold
produce no glow.
glow(img, intensity=0.5, radius=10)
bloom(img, intensity=0.5, radius=10, threshold=0.3)
Distortion
Distortion filters return a new Image
based on a polar coordinates operation. The bump()
function bulges the image outward,
dent()
squeezes the image inward,
and pinch()
does both. The splash()
function produces a light-tunnel
effect, while twirl()
produces a
spinning effect. The radius
defines the
extent of the effect in pixels. The zoom
defines the depth of the effect (0.0
–1.0
for
bump and dent, and -1.0
–1.0
for pinch). The angle
is the amount of degrees to rotate.
bump(img, dx, dy, radius, zoom)
dent(img, dx, dy, radius, zoom)
pinch(img, dx, dy, zoom)
splash(img, dx, dy, radius)
twirl(img, dx, dy, radius, angle)
The dx
and dy
parameters define the offset of the effect
from the image center, in pixels.
The text()
function can be used to draw
a string of text to the canvas. The font()
, fontsize()
, fontweight()
and lineheight()
functions set the current text
state. Each function also returns its current setting. The default font
is 12px normal sans-serif with 1.2em line height.
font(fontname)
fontsize(fontsize)
fontweight(fontweight) // NORMAL, BOLD, ITALIC, BOLD+ITALIC
lineheight(lineheight)
The text()
function draws a string
using the current color, transformation and text state:
text(str, x, y)
textwidth(str)
textheight(str)
The state can be overridden by passing an optional font
, fontsize
, fontweight
, lineheight
and/or fill
to the functions:
text("Hello world", 0, 0, {
fill: new Color(1,0,0),
font: "Georgia",
fontweight: BOLD
});
The Mouse
object stores the current
state of the mouse input device (or touch event). It can be retrieved
with the canvas.mouse
property in the
main draw()
loop.
var mouse = canvas.mouse;
var mouse = new Mouse(element);
mouse.parent // Element to track.
mouse.x // Horizontal position.
mouse.y // Vertical position.
mouse.relative_x // Relative (0.0-1.0) to Canvas.width.
mouse.relative_y // Relative (0.0-1.0) to Canvas.height.
mouse.pressed // Mouse is pressed? (true|false)
mouse.dragged // Mouse is dragged? (true|false)
mouse.drag.x // Drag distance from previous x.
mouse.drag.y // Drag distance from previous y.
mouse.cursor(mode) // DEFAULT, CROSS, HAND, HIDDEN, TEXT, WAIT
mouse.onmove()
mouse.onpress()
mouse.onrelease()
mouse.ondrag()
Custom event handlers can be attached to Mouse
. The function takes a parameter mouse
, which is the Mouse
receiving the event. The canvas can be
accessed with mouse.parent.canvas
. To
draw to this canvas during the event, first call its focus()
method.
function setup(canvas) {
canvas.mouse.ondrag = function(mouse) {
mouse.parent.canvas.focus();
ellipse(mouse.x, mouse.y, 2, 2);
};
}
The Canvas
object manages the animation
container. With <script type="text/canvas">
, there is no explicit need to initialize a
new canvas in your script. It will be created for you and passed as
a parameter canvas
to the draw()
and setup()
functions in your script:
<!doctype html>
<html>
<head>
<script type="text/javascript" src="canvas.js"></script>
</head>
<body>
<script type="text/canvas" loop="true">
function setup(canvas) {
canvas.size(500, 500);
}
function draw(canvas) {
canvas.clear();
// Add drawing code here.
}
</script>
</body>
</html>
Custom animations require a HTML <canvas>
element and a window.onload()
that binds the element to a
Canvas
object and assigns a draw()
and a setup()
function to the canvas:
<!doctype html>
<html>
<head>
<script type="text/javascript" src="canvas.js"></script>
<script>
function setup(canvas) {
canvas.size(500, 500);
}
function draw(canvas) {
canvas.clear();
// Add drawing code here.
}
window.onload = function() {
canvas = new Canvas(document.getElementById("canvas1"));
canvas.setup = setup;
canvas.draw = draw;
canvas.run();
}
</script>
</head>
<body>
<canvas id="canvas1" width="500px" height="500px"></canvas>
</body>
</html>
The Canvas
object takes a <canvas>
element:
var canvas = new Canvas(element);
canvas.id
canvas.element // HTML <canvas> element.
canvas.width // Element width.
canvas.height // Element height.
canvas.frame // Current animation frame (start = 1).
canvas.fps // Frames per second (read-only).
canvas.dt // Time elapsed since last frame.
canvas.mouse // Mouse object.
canvas.variables // Widget variables.
canvas.size(width, height)
canvas.setup()
canvas.draw()
canvas.clear()
canvas.run()
canvas.pause()
canvas.stop()
canvas.active() // Returns true if the animation is running.
canvas.focus() // Sets the canvas as current drawing context.
canvas.image() // Returns the canvas as an Image.
canvas.save() // Returns the canvas as PNG data.
-
Canvas.setup()
is meant to be overridden. It runs once at the start of the animation. -
Canvas.draw()
is meant be overridden. It runs each frame. -
Canvas.save()
andCanvas.image()
will throw an error if the canvas contains remote images
(i.e., from a URL on a different server). This is for security reasons, see CORS.
Widgets (e.g., buttons, sliders) give you the possibility to create apps
that users can interact with without diving into the JavaScript
code. The widget()
function creates a
widget linked to the given Canvas
. The
value of the widget can be retrieved as Canvas.variables\[variable\]
. The type
can be STRING
or NUMBER
(a field), BOOLEAN
(a checkbox), RANGE
(a slider), LIST
(a dropdown list) or FUNCTION
(a button).
Optionally, a default value
can be
given. For lists, this is an Array
, the
index
of the selected value is 0 by
default. For sliders, you can also set min
, max
and
step
. For functions, a callback(event)
must be given. To get the
canvas in the callback function, use event.target.canvas
. If the function does
drawing, call event.target.canvas.focus()
first.
The widget()
function will generate a
<div id="\[canvas.id\]\_widgets" class="widgets">
, if it does not yet exist. The <div>
is added to the page below the
canvas. Optionally, a different parent
HTML element can be given. The parent contains all canvas widgets, each
wrapped in a <span class="widget">
.
widget(canvas, variable, type, {
parent: null,
value: null,
min: 0,
max: 1,
step: 0.01,
index: 0,
callback: function(event) { }
})
For example, the following script comes with buttons to start and pause the animation:
function setup(canvas) {
widget(canvas, "start", FUNCTION, {callback: function(e) {
e.target.canvas.run();
}});
widget(canvas, "pause", FUNCTION, {callback: function(e) {
e.target.canvas.pause();
}});
}
function draw(canvas) {
canvas.clear();
translate(200, 200);
rotate(canvas.frame);
rect(-75, -75, 150, 150);
}
The easiest way to incorporate data sets in an animation is by
using JSON, a lightweight data-interchange
format based on associative arrays (i.e., like a dict
in Python). For example, you can use the
Datasheet
object in
pattern.db to generate JSON from Python:
>>> from pattern.db import Datasheet, STRING, INTEGER
>>> ds = Datasheet(fields=[('name', STRING), ('count', INTEGER)])
>>> ds.append(( 'chickens', 12))
>>> ds.append(( 'penguins', 26))
>>> ds.append(('sombreros', 9))
>>> open('data.js', 'w').write('var data = ' + ds.json + ';')
This generates a data.js
file that
defines a data
variable:
var data = [
{'name': 'chickens', 'count': 12},
{'name': 'penguins', 'count': 26},
{'name': 'sombreros', 'count': 9}
];
We can load data.js
in the HTML <head>
section so data
becomes available in the animation:
<html>
<head>
<script type="text/javascript" src="canvas.js"></script>
<script type="text/javascript" src="data.js"></script>
</head>
<body>
<script type="text/canvas">
function draw(canvas) {
// Draw the data as a bar chart.
var dx = 10;
var dy = 10;
for (var i=0; i < data.length; i++) {
rect(dx, dy, data[i]['count'] * 10, 30);
text(data[i]['name'], dx+10, dy+20, {fill:1}); dy += 40;
}
}
</script>
</body>
</html>
The Point
object can be used to
represent (x, y) coordinates in 2D space:
var pt = new Point(x, y);
pt.x
pt.y
The module includes the following helper functions for 2D geometry:
geometry.angle(x0, y0, x1, y1) // Returns the angle between two points.
geometry.distance(x0, y0, x1, y1) // Returns the distance between two points.
geometry.coordinates(x0, y0, d, a) // Returns Point at distance d with angle a.
geometry.rotate(x, y, x0, y0, a) // Returns Point (x,y) rotated around (x0,y0).
geometry.lerp(a, b, t) // Linear interpolation: lerp(4, 8, 0.5) => 6
geometry.smoothstep(a, b, x) // Hermite interpolation (ease-in + ease-out).
geometry.lineIntesection(x0, y0, x1, y1, x2, y2, x3, y3, infinite=false)
geometry.pointInPolygon(points, x, y)
In addition to the standard math functions such as Math.sin()
, Math.cos()
and Math.sqrt()
, the module defines the following
math functions:
Math.sign(x) // Returns +1, -1 or 0 for a given number.
Math.degrees(radians) // Math.degrees(Math.PI) => 180
Math.radians(degrees) // Math.radians(180) => Math.PI
Math.clamp(value, min, max) // Math.clamp(1.5, 0.0, 1.0) => 1.0
Math.dot(array1, array2) // a1[0] * a2[0] + a1[1] * a2[1] + ...
An Array
can be used to store a list of
values (e.g., numbers and/or strings):
var a = [1, 2, 3];
a[index] // [1,2,3][0] => 1
a.indexOf(value) // [1,2,3].indexOf(1) => 0
a.push(value) // [1,2,3].push(4) => [1,2,3,4]
a.pop() // [1,2,3].pop() => [1,2] 3
a.shift() // [1,2,3].shift() => 1 [2,3]
a.concat(array) // [1,2,3].concact([4,5]) => [1,2,3,4,5] copy
a.slice(i, j=null) // [1,2,3].slice(1,3) => [2,3]
a.splice(i, n, v1, v2, ...) // [1,2,3].splice(1,0,11,12) => [1,11,12,2,3]
a.join(str) // [1,2,3].join(",") => "1,2,3"
The module defines the following helper functions for arrays:
Array.instanceof(array) // Returns true if object is an Array.
Array.min(array) // Returns the smallest value.
Array.max(array) // Returns the largest value.
Array.sum(array) // Returns the sum of all values.
Array.contains(array, value) // Returns true if array contains value.
Array.find(array, match) // Returns first value with match(value) == true.
Array.map(array, callback) // Returns new array of callback(value) values.
Array.filter(array, callback) // Returns new array for callback(value) == true.
Array.enumerate(array, callback) // Calls callback(index, value) for each value.
Array.eq(array1, array2) // Returns true if values array1 == array2.
Array.sorted(array, reverse=false) // Returns a new array with sorted values.
Array.reversed(array) // Returns a new array with reversed order.
Array.choice(array) // Returns a random value.
Array.shuffle(array) // Randomly shuffles the values in the array.
Array.range(i, j) // Returns an array with values i => j-1.
var a = [0, 1, 2, 3, 4, 5];
a = Array.map(a, function(v) { return v * 2; }); // {0, 2, 3, 6, 8, 10}
a = Array.filter(a, function(v) { return v < 5 }); // [0, 2, 4]