mala
v2.0.0
Published
Lightweight <canvas> drawing library
Downloads
4
Readme
Måla
Måla is swedish for painting. This is a lightweight (less than 7kB) library to paint on the HTML5 <canvas>
element.
Setup
Use with browserify
$ npm install mala
And
var Mala = require('mala')
Use directly in an HTML page
Download mala.min.js
here
And add it to the page
<script src="mala.min.js"></script>
Usage
Initialise
Add a <div>
to your HTML with a unique id.
<div id="myPainting"></div>
Add a canvas within the div by creating a new instance of Måla that takes two arguments:
- The id of the div
- The desired size of the canvas
var paint = new Mala('myPainting', { width: 1000, height: 500 })
Now you can add rectangles, circles, lines, polygons, text and images (see below). When you are done, draw the canvas with
paint.draw()
Add a rectangle
var firstRectangle = paint.rect(10, 10, 100, 50)
.rect(x,y,width,height)
takes four arguments:
- x: The number of pixels to the right of the top-left corner
- y: The number of pixels down from the top-left corner
- width (in pixels)
- height (in pixels)
Style options
fill
: Any HTML color (defaults to'black'
)stroke
: Any HTML color (defaults toundefined
)opacity
: A number between 0 and 1 (defaults to1
)lineWidth
: The width in pixels of thestroke
(defaults to1
)lineJoin
: The shape of the corners of thestroke
(defaults tomiter
, other possibilities areround
andbevel
)
Set the styles like this:
firstRectangle.fill = 'blue'
firstRectangle.stroke = 'red'
Example:
var paint = new Mala('c', {width: 200, height: 100})
// Create the rectangle
var firstRectangle = paint.rect(10, 10, 100, 50)
// Set the style
firstRectangle.fill = 'blue'
firstRectangle.stroke = 'red'
firstRectangle.lineWidth = 5
// Render
paint.draw()
Looks like this:
Add a circle
var firstCircle = paint.circle(50, 30, 20)
.circle(x,y,r)
takes four arguments:
- x: The number of pixels to the right of the top-left corner
- y: The number of pixels down from the top-left corner
- r: The radius in pixels
Style options
fill
: Any HTML color (defaults to'black'
)stroke
: Any HTML color (defaults toundefined
)opacity
: A number between 0 and 1 (defaults to1
)
Set the styles like this:
firstCircle.fill = 'green'
Add a line
var firstLine = paint.line([[10,10],[20,20],[20,30]])
.line([[x1,y1],[x2,y2],[x3,y3]])
takes one argument: an array of x and y coordinates
To draw curves add one or two control points like this:
.line([[x1,y1],[ctrlPoint1-x,ctrlPoint1-y,x2,y2],[x3,y3]])
(with one control point)
or
.line([[x1,y1],[ctrlPoint1-x,ctrlPoint1-y,ctrlPoint2-x,ctrlPoint2-y,x2,y2],[x3,y3]])
(with two control points)
Example with a simple line:
paint.line([[20,50],[180,50])
With one control point at [100,20]
paint.line([[20,50],[100,20,180,50])
With two control points at [40,20] and [160,20]
paint.line([[20,50],[40,20,160,20,180,50])
Style options
stroke
: Any HTML color (defaults to'black'
)opacity
: A number between 0 and 1 (defaults to1
)lineWidth
: The width in pixels of thestroke
(defaults to1
)lineJoin
: The shape of the corners of thestroke
(defaults tomiter
, other possibilities areround
andbevel
)lineCap
: The shape of the ends of the line (defaults tobutt
, other possibilities areround
andsquare
)
Set the styles like this:
firstLine.lineWidth = 5
firstLine.lineCap = 'round'
Add a polygon
var firstPolygon = paint.polygon([[[10,10],[20,20],[20,30]]])
.polygon([[[x1,y1],[x2,y2],[x3,y3]]])
, takes one argument: an array of arrays of x and y coordinates. For curved sides of the polygon, add control points as with .line()
Style options
fill
: Any HTML color (defaults to'black'
)stroke
: Any HTML color (defaults toundefined
)opacity
: A number between 0 and 1 (defaults to1
)lineWidth
: The width in pixels of thestroke
(defaults to1
)lineJoin
: The shape of the corners of thestroke
(defaults tomiter
, other possibilities areround
andbevel
)
Set styles like this:
firstPolygon.fill = 'yellow'
To make a hole in a polygon, add an array of coordinates in counter clockwise order.
var paint = new Mala('c', {width: 200, height: 100})
var outlineArray = [[0,0],[0,100],[200,100]]
var holeArray = [[10,60],[10,80],[30,80]]
var polygonWithHole = paint.polygon([outlineArray, holeArray])
paint.draw()
Add text
var firstText = paint.text('Hello world', 20, 30)
.text(txt,x,y)
takes three arguments:
- txt: The text string
- x: The number of pixels to the right of the top-left corner
- y: The number of pixels down from the top-left corner
Style options
fill
: Any HTML color (defaults to'black'
)font
: A string with the font-size (followed bypx
) and the font-family (defaults to'12px sans-serif'
)stroke
: Any HTML color (defaults toundefined
)opacity
: A number between 0 and 1 (defaults to1
)lineWidth
: The width in pixels of thestroke
(defaults to1
)
Set styles like this:
firstText.font = '20px Helvetica'
Example:
var paint = new Mala('c', {width: 200, height: 100})
// Add text
var firstText = paint.text('Hello world', 20, 30)
// Set style
firstText.font = '30px Helvetica'
firstText.fill = undefined
firstText.stroke = 'red'
// Render
paint.draw()
Add an image
In order to add an image to the canvas, you first need to add the image file
var myImage = paint.addImageFile('theImage.png')
.addImageFile(pathToImage)
takes one argument, the path to the file.
..............................................................................
WARNING
paint.draw()
waits until all images are loaded to draw on canvas. If the path does not lead to a file, the canvas will not be drawn.
If you are doing an animation, use .addImageFile()
before starting the animation. Even if you are not going to use it in the first frames.
..............................................................................
Once you have added a file with .addImageFile()
, you can add the image to the canvas like this:
var firstImage = paint.image(myImage, 10, 10)
.image(img, x, y)
takes three arguments:
- img: the image loaded with
.addImageFile()
- x: The number of pixels to the right of the top-left corner
- y: The number of pixels down from the top-left corner
You can add an image several times using .addImageFile()
once:
var myImage = paint.addImageFile('theImage.png')
var firstImage = paint.image(myImage, 10, 10)
var secondImage = paint.image(myImage, 100, 100)
Style options
opacity
: A number between 0 and 1 (defaults to1
)width
: the width in pixels (defaults to the image files naturalWidth)height
: the height in pixels (defaults to the image files naturalHeight)
If only width
, or only height
, is defined the aspect ratio will be preserved. If both are used, the image will have the defined width
and height
.
Examples with this image (100px wide and 80px high)
Add it to canvas
var paint = new Mala('c', {width: 200, height: 100})
// Setting a gray background to better see the image on the canvas
var r = paint.rect(0,0,200,100)
r.fill = 'lightgray'
// Add the file
var img = paint.addImageFile('troll.png')
// Add the image
var img1 = paint.image(img, 0, 0)
// Render
paint.draw()
It looks like this:
If we set only the width:
var img1 = paint.image(img, 0, 0)
img1.width = 50
If we set only the height:
var img1 = paint.image(img, 0, 0)
img1.height = 100
If we set both width and height:
var img1 = paint.image(img, 0, 0)
img1.width = 50
img1.height = 100
Layers
When paint.draw()
is triggered, all objects will be drawn in the order they have been added. The last above the ones before.
If we draw a rectangle, then a circle. The circle will be on top of the rectangle.
var paint = new Mala('c', {width: 200, height: 100})
var rect = paint.rect(0,0,100,50)
rect.fill = 'blue'
rect.layer = 1
var circle = paint.circle(70,60,40)
circle.fill = 'red'
paint.draw()
Looks like this:
By default all added objects are on layer 0 (the bottom layer). If we want the rectangle in the example above to be on top although it is created before:
var paint = new Mala('c', {width: 200, height: 100})
var rect = paint.rect(0,0,100,50)
rect.fill = 'blue'
rect.layer = 1 // <-- new line setting "rect" on layer 1
var circle = paint.circle(70,60,40)
circle.fill = 'red'
paint.draw()
Looks like:
Animation
Måla does not provide any animation method, you will have to use your own. It does have two features that will help you animating:
- the
.move()
method - the
.show
property
.move()
Every object (rectangle, circle, line, polygon, text or image) can be "moved" with the method .move()
.
.move(x,y)
takes two arguments:
- x: the number of pixels by which we want to move the object horizontally
- y: the number of pixels by which we want to move the object vertically
If we want to have a square moving across the canvas from left to right:
var paint = new Mala('c', {width: 200, height: 100})
var movingSquare = paint.rect(0,45,10,10) // <-- create the square
setInterval(function() {
movingSquare.move(1,0) // <-- move it
paint.draw() // <-- redraw the canvas to see the move
},100)
This will move the square one pixel to the right at every interval. Here the interval is set to 100, a tenth of a second.
Another way of animating is to move not at a certain interval in milliseconds but every time the screen is refreshed on your device by using requestAnimationFrame()
instead of setInterval()
This does the same using requestAnimationFrame()
. It is a bit faster because the screen is usually refreshed more often than every tenth of a second.
var paint = new Mala('c', {width: 200, height: 100})
var movingSquare = paint.rect(0,45,10,10) // <-- create the square
requestAnimationFrame(animate)
function animate() {
movingSquare.move(1,0) // <-- move it
paint.draw() // <-- redraw the canvas to see the move
requestAnimationFrame(animate)
}
.show
Every object has a show
attribute. By default it is set to true
, you can set it to false
when you want the object not to be shown on the next frame but do not want to remove it permanently.
If we want to have a blinking circle:
var paint = new Mala('c', {width: 200, height: 100})
var blinkingCircle = paint.circle(100,50, 20)
setInterval(function() {
// set "show" to "false" if it is "true". If is "false", set it to "true"
if(blinkingCircle.show === true) {
blinkingCircle.show = false
} else {
blinkingCircle.show = true
}
paint.draw() // <-- redraw
},500)
paint.remove()
If you want to permanently remove an object from the canvas:
paint.remove(blinkingCircle)
Updates
2.0.0
Modified .polygon()
API. It now takes an array of arrays of coordinates so that polygons can have holes.