For general information about using <canvas> see the canvas topic page.
Code usable from Web content
Getting the number of pixels of a certain color in a canvas
The following function will return the number of pixels in a canvas that have the RGB color of r, g and b. This can be very useful to compare for example if a user has painted over another area as explained in this blog post.
function getpixelamount(canvas, r, g, b) {
var cx = canvas.getContext('2d');
var pixels = cx.getImageData(0, 0, canvas.width, canvas.height);
var all = pixels.data.length;
var amount = 0;
for (i = 0; i < all; i += 4) {
if (pixels.data[i] === r &&
pixels.data[i + 1] === g &&
pixels.data[i + 2] === b) {
amount++;
}
}
return amount;
};
Getting the color of a pixel in a canvas
This following snippet returns an object with the RGBA values of the pixel at position x and y of the canvas. This can be used to determine if the mouse cursor is inside a certain shape or not.
function getpixelcolour(canvas, x, y) {
var cx = canvas.getContext('2d');
var pixel = cx.getImageData(x, y, 1, 1);
return {
r: pixel.data[0],
g: pixel.data[1],
b: pixel.data[2],
a: pixel.data[3]
};
}
Chaining methods
This class provides jQuery-style chained access to 2D context methods and properties.
function Canvas2DContext(canvas) {
if (typeof canvas === 'string') {
canvas = document.getElementById(canvas);
}
if (!(this instanceof Canvas2DContext)) {
return new Canvas2DContext(canvas);
}
this.context = this.ctx = canvas.getContext('2d');
if (!Canvas2DContext.prototype.arc) {
Canvas2DContext.setup.call(this, this.ctx);
}
}
Canvas2DContext.setup = function() {
var methods = ['arc', 'arcTo', 'beginPath', 'bezierCurveTo', 'clearRect', 'clip',
'closePath', 'drawImage', 'fill', 'fillRect', 'fillText', 'lineTo', 'moveTo',
'quadraticCurveTo', 'rect', 'restore', 'rotate', 'save', 'scale', 'setTransform',
'stroke', 'strokeRect', 'strokeText', 'transform', 'translate'];
var getterMethods = ['createPattern', 'drawFocusRing', 'isPointInPath', 'measureText', // drawFocusRing not currently supported
// The following might instead be wrapped to be able to chain their child objects
'createImageData', 'createLinearGradient',
'createRadialGradient', 'getImageData', 'putImageData'
];
var props = ['canvas', 'fillStyle', 'font', 'globalAlpha', 'globalCompositeOperation',
'lineCap', 'lineJoin', 'lineWidth', 'miterLimit', 'shadowOffsetX', 'shadowOffsetY',
'shadowBlur', 'shadowColor', 'strokeStyle', 'textAlign', 'textBaseline'];
for (let m of methods) {
let method = m;
Canvas2DContext.prototype[method] = function() {
this.ctx[method].apply(this.ctx, arguments);
return this;
};
}
for (let m of getterMethods) {
let method = m;
Canvas2DContext.prototype[method] = function() {
return this.ctx[method].apply(this.ctx, arguments);
};
}
for (let p of props) {
let prop = p;
Canvas2DContext.prototype[prop] = function(value) {
if (value === undefined)
return this.ctx[prop];
this.ctx[prop] = value;
return this;
};
}
};
var canvas = document.getElementById('canvas');
// Use context to get access to underlying context
var ctx = Canvas2DContext(canvas)
.strokeStyle('rgb(30, 110, 210)')
.transform(10, 3, 4, 5, 1, 0)
.strokeRect(2, 10, 15, 20)
.context;
// Use property name as a function (but without arguments) to get the value
var strokeStyle = Canvas2DContext(canvas)
.strokeStyle('rgb(50, 110, 210)')
.strokeStyle();
Code usable only from privileged code
These snippets are only useful from privileged code, such as extensions or privileged apps.
Saving a canvas image to a file
The following function accepts a canvas object and a destination file path string. The canvas is converted to a PNG file and saved to the specified location. The function returns a promise which resolves when the file has been completely saved.
function saveCanvas(canvas, path, type, options) {
return Task.spawn(function *() {
var reader = new FileReader;
var blob = yield new Promise(accept => canvas.toBlob(accept, type, options));
reader.readAsArrayBuffer(blob);
yield new Promise(accept => { reader.onloadend = accept });
return yield OS.File.writeAtomic(path, new Uint8Array(reader.result),
{ tmpPath: path + '.tmp' });
});
}
Loading a remote page onto a canvas element
The following class first creates a hidden iframe element and attaches a listener to the frame's load event. Once the remote page has loaded, the remotePageLoaded method fires. This method gets a reference to the iframe's window and draws this window to a canvas object.
Note that this only works if you are running the page from chrome. If you try running the code as a plain webpage, you will get a 'Security error" code: "1000' error.
RemoteCanvas = function() {
this.url = 'http://developer.mozilla.org';
};
RemoteCanvas.CANVAS_WIDTH = 300;
RemoteCanvas.CANVAS_HEIGHT = 300;
RemoteCanvas.prototype.load = function() {
var windowWidth = window.innerWidth - 25;
var iframe;
iframe = document.createElement('iframe');
iframe.id = 'test-iframe';
iframe.height = '10px';
iframe.width = windowWidth + 'px';
iframe.style.visibility = 'hidden';
iframe.src = this.url;
// Here is where the magic happens... add a listener to the
// frame's onload event
iframe.addEventListener('load', this.remotePageLoaded, true);
//append to the end of the page
window.document.body.appendChild(iframe);
return;
};
RemoteCanvas.prototype.remotePageLoaded = function() {
// Look back up the iframe by id
var ldrFrame = document.getElementById('test-iframe');
// Get a reference to the window object you need for the canvas
// drawWindow method
var remoteWindow = ldrFrame.contentWindow;
//Draw canvas
var canvas = document.createElement('canvas');
canvas.style.width = RemoteCanvas.CANVAS_WIDTH + 'px';
canvas.style.height = RemoteCanvas.CANVAS_HEIGHT + 'px';
canvas.width = RemoteCanvas.CANVAS_WIDTH;
canvas.height = RemoteCanvas.CANVAS_HEIGHT;
var windowWidth = window.innerWidth - 25;
var windowHeight = window.innerHeight;
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0,
RemoteCanvas.CANVAS_WIDTH,
RemoteCanvas.CANVAS_HEIGHT);
ctx.save();
ctx.scale(RemoteCanvas.CANVAS_WIDTH / windowWidth,
RemoteCanvas.CANVAS_HEIGHT / windowHeight);
ctx.drawWindow(remoteWindow,
0, 0,
windowWidth, windowHeight,
'rgb(255, 255, 255)');
ctx.restore();
};
Usage:
var remoteCanvas = new RemoteCanvas(); remoteCanvas.load();
Convert image files to base64 strings
The following code gets a remote image and converts its content to Data URI scheme.
var canvas = document.createElement('canvas');
var ctxt = canvas.getContext('2d');
function loadImageFile(url, callback) {
var image = new Image();
image.src = url;
return new Promise((accept, reject) => {
image.onload = accept;
image.onerror = reject;
}).then(accept => {
canvas.width = this.width;
canvas.height = this.height;
ctxt.clearRect(0, 0, this.width, this.height);
ctxt.drawImage(this, 0, 0);
accept(canvas.toDataURL());
});
}
Usage:
loadImageFile('myimage.jpg').then(string64 => { alert(string64); });
If you want to get instead the base64 content of a local file using the file <input> element, you must use the FileReader object.
