Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 429145 of Canvas code snippets

  • Revision slug: Code_snippets/Canvas
  • Revision title: Canvas
  • Revision id: 429145
  • Created:
  • Creator: codepo8
  • Is current revision? No
  • Comment

Revision Content

For general information about using <canvas> see the canvas topic page.

Getting the amount of pixels of a certain colour in a Canvas

The following function will return the amount of pixels in canvas that have the RGB colour 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, c.width, c.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 colour 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

Class to give jQuery-style chained access to 2D context methods and properties.

<html xmlns="https://www.w3.org/1999/xhtml">
<head><title></title></head>
<body>
<canvas id="canvas" width="1800" height="1800"></canvas>

<script type="text/javascript">

function Canvas2DContext(c) {
  if (typeof c === 'string') {
    c = document.getElementById(c);
  }
  if (!(this instanceof Canvas2DContext)) {
    return new Canvas2DContext(c);
  }
  this.context = this.ctx = c.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'];

  var gmethl, propl;
  for (var i = 0, methl = methods.length; i < methl; i++) {
    var m = methods[i];
    Canvas2DContext.prototype[m] = (function (m) {return function () {
      this.ctx[m].apply(this.ctx, arguments);
      return this;
    };}(m));
  }

  for (i = 0, gmethl = getterMethods.length; i < gmethl; i++) {
    var gm = getterMethods[i];
    Canvas2DContext.prototype[gm] = (function (gm) {return function () {
      return this.ctx[gm].apply(this.ctx, arguments);
    };}(gm));
  }

  for (i = 0, propl = props.length; i < propl; i++) {
    var p = props[i];
    Canvas2DContext.prototype[p] = (function (p) {return function (value) {
      if (typeof value === 'undefined') {
        return this.ctx[p];
      }
      this.ctx[p] = value;
      return this;
    };}(p));
  }
};

var c = document.getElementById('canvas');

var ctx = Canvas2DContext(c).strokeStyle("rgb(30,110,210)").
             transform(10, 3, 4, 5, 1, 0).strokeRect(2, 10, 15, 20).context; // Use context to get access to underlying context
//alert(ctx);

var strokeStyle = Canvas2DContext(c).strokeStyle("rgb(50,110,210)").strokeStyle(); // Use property name as a function (but without arguments) to get the value
// alert(strokeStyle);

</script>
</body>
</html>

The following snippets can only be used from privileged code (extensions, in particular).

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 displays a download progress dialog, but the dialog can be removed.

function saveCanvas(canvas, destFile) {
  // convert string filepath to an nsIFile
  var file = Components.classes["@mozilla.org/file/local;1"]
                       .createInstance(Components.interfaces.nsILocalFile);
  file.initWithPath(destFile);

  // create a data url from the canvas and then create URIs of the source and targets  
  var io = Components.classes["@mozilla.org/network/io-service;1"]
                     .getService(Components.interfaces.nsIIOService);
  var source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
  var target = io.newFileURI(file)
    
  // prepare to save the canvas data
  var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                          .createInstance(Components.interfaces.nsIWebBrowserPersist);
  
  persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
  persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
  
  // displays a download dialog (remove these 3 lines for silent download)
  var xfer = Components.classes["@mozilla.org/transfer;1"]
                       .createInstance(Components.interfaces.nsITransfer);
  xfer.init(source, target, "", null, null, null, persist);
  persist.progressListener = xfer;
  
  // save the canvas data to the file
  persist.saveURI(source, null, null, null, null, file);
}

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 = "https://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 oCanvas = document.createElement("canvas"), oCtx = oCanvas.getContext("2d");
function loadImageFile (sURL, fCallback) {
  var oImage = new Image();
  oImage.src = sURL;
  oImage.onload = function () {
    oCanvas.width = this.width;
    oCanvas.height = this.height;
    oCtx.clearRect(0, 0, this.width, this.height);
    oCtx.drawImage(this, 0, 0);
    fCallback.call(this, oCanvas.toDataURL());
  };
}

Usage:

loadImageFile("myimage.jpg", function(string64) { alert(string64); });

If you want to get instead the base64 content of a local file using the file {{ HTMLElement("input") }} element, you must use the FileReader object.

{{ languages( { "fr": "fr/Extraits_de_code/Canvas", "ja": "ja/Code_snippets/Canvas", "pl": "pl/Fragmenty_kodu/Canvas" } ) }}

Revision Source

<p>For general information about using <code>&lt;canvas&gt;</code> see the <a class="internal" href="/en/HTML/Canvas" title="En/HTML/Canvas">canvas topic page</a>.</p>
<h3 id="Getting_the_amount_of_pixels_of_a_certain_colour_in_a_Canvas">Getting the amount of pixels of a certain colour in a Canvas</h3>
<p>The following function will return the amount of pixels in canvas that have the RGB colour of r, g and b. This can be very useful to compare for example if a user has painted over another area as explained <a href="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/" title="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/">in this blog post</a>.</p>
<pre class="brush: js">
function getpixelamount(canvas, r, g, b) {
  var cx = canvas.getContext('2d');
  var pixels = cx.getImageData(0, 0, c.width, c.height);
  var all = pixels.data.length;
  var amount = 0;
  for (i = 0; i &lt; all; i += 4) {
    if (pixels.data[i] === r &amp;&amp;
        pixels.data[i + 1] === g &amp;&amp;
        pixels.data[i + 2] === b) {
      amount++;
    }
  }
  return amount;
};
</pre>
<h3 id="Getting_the_colour_of_a_pixel_in_a_canvas">Getting the colour of a pixel in a canvas</h3>
<p>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.</p>
<pre class="brush: js">
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]
  };
}
</pre>
<h3 id="Chaining_methods">Chaining methods</h3>
<p>Class to give jQuery-style chained access to 2D context methods and properties.</p>
<pre class="brush: js">
&lt;html xmlns="https://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;&lt;title&gt;&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;
&lt;canvas id="canvas" width="1800" height="1800"&gt;&lt;/canvas&gt;

&lt;script type="text/javascript"&gt;

function Canvas2DContext(c) {
  if (typeof c === 'string') {
    c = document.getElementById(c);
  }
  if (!(this instanceof Canvas2DContext)) {
    return new Canvas2DContext(c);
  }
  this.context = this.ctx = c.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'];

  var gmethl, propl;
  for (var i = 0, methl = methods.length; i &lt; methl; i++) {
    var m = methods[i];
    Canvas2DContext.prototype[m] = (function (m) {return function () {
      this.ctx[m].apply(this.ctx, arguments);
      return this;
    };}(m));
  }

  for (i = 0, gmethl = getterMethods.length; i &lt; gmethl; i++) {
    var gm = getterMethods[i];
    Canvas2DContext.prototype[gm] = (function (gm) {return function () {
      return this.ctx[gm].apply(this.ctx, arguments);
    };}(gm));
  }

  for (i = 0, propl = props.length; i &lt; propl; i++) {
    var p = props[i];
    Canvas2DContext.prototype[p] = (function (p) {return function (value) {
      if (typeof value === 'undefined') {
        return this.ctx[p];
      }
      this.ctx[p] = value;
      return this;
    };}(p));
  }
};

var c = document.getElementById('canvas');

var ctx = Canvas2DContext(c).strokeStyle("rgb(30,110,210)").
             transform(10, 3, 4, 5, 1, 0).strokeRect(2, 10, 15, 20).context; // Use context to get access to underlying context
//alert(ctx);

var strokeStyle = Canvas2DContext(c).strokeStyle("rgb(50,110,210)").strokeStyle(); // Use property name as a function (but without arguments) to get the value
// alert(strokeStyle);

&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<div class="note">
  <p>The following snippets can only be used from privileged code (extensions, in particular).</p>
</div>
<h3 id="Saving_a_canvas_image_to_a_file" name="Saving_a_canvas_image_to_a_file">Saving a canvas image to a file</h3>
<p>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 displays a download progress dialog, but the dialog can be removed.</p>
<pre class="brush: js">
function saveCanvas(canvas, destFile) {
  // convert string filepath to an nsIFile
  var file = Components.classes["@mozilla.org/file/local;1"]
                       .createInstance(Components.interfaces.nsILocalFile);
  file.initWithPath(destFile);

  // create a data url from the canvas and then create URIs of the source and targets  
  var io = Components.classes["@mozilla.org/network/io-service;1"]
                     .getService(Components.interfaces.nsIIOService);
  var source = io.newURI(canvas.toDataURL("image/png", ""), "UTF8", null);
  var target = io.newFileURI(file)
    
  // prepare to save the canvas data
  var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
                          .createInstance(Components.interfaces.nsIWebBrowserPersist);
  
  persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
  persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
  
  // displays a download dialog (remove these 3 lines for silent download)
  var xfer = Components.classes["@mozilla.org/transfer;1"]
                       .createInstance(Components.interfaces.nsITransfer);
  xfer.init(source, target, "", null, null, null, persist);
  persist.progressListener = xfer;
  
  // save the canvas data to the file
  persist.saveURI(source, null, null, null, null, file);
}
</pre>
<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">Loading a remote page onto a canvas element</h3>
<p>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.</p>
<p>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.</p>
<pre class="brush: js">
RemoteCanvas = function() {
    this.url = "https://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();
};
</pre>
<p>Usage:</p>
<pre class="brush: js">
var remoteCanvas = new RemoteCanvas();
remoteCanvas.load();
</pre>
<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">Convert image files to base64 strings</h3>
<p>The following code gets a remote image and converts its content to <code><a href="/en/data_URIs" title="en/data_URIs">Data URI scheme</a></code>.</p>
<pre class="brush: js">
var oCanvas = document.createElement("canvas"), oCtx = oCanvas.getContext("2d");
function loadImageFile (sURL, fCallback) {
  var oImage = new Image();
  oImage.src = sURL;
  oImage.onload = function () {
    oCanvas.width = this.width;
    oCanvas.height = this.height;
    oCtx.clearRect(0, 0, this.width, this.height);
    oCtx.drawImage(this, 0, 0);
    fCallback.call(this, oCanvas.toDataURL());
  };
}
</pre>
<p>Usage:</p>
<pre class="brush: js">
loadImageFile("myimage.jpg", function(string64) { alert(string64); });
</pre>
<p>If you want to get instead the base64 content of a local file using the file {{ HTMLElement("input") }} element, you must use the <code><a href="/en/DOM/FileReader#readAsDataURL%28%29" title="en/DOM/FileReader#readAsDataURL%28%29">FileReader</a></code> object.</p>
<p>{{ languages( { "fr": "fr/Extraits_de_code/Canvas", "ja": "ja/Code_snippets/Canvas", "pl": "pl/Fragmenty_kodu/Canvas" } ) }}</p>
Revert to this revision