Canvas

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

Chaining methods

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

<html xmlns="http://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 = "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 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 <input> element, you must use the FileReader object.

Tags (3)

Edit tags

Attachments (0)

 

Attach file