Duplicating a canvas multiple times: cloning a canvas or copying image data?

One of my interface elements is rendered using an HTML5 element <canvas>and the corresponding JavaScript API. This item is used in several places on the same screen and on multiple screens in the application. What is the most efficient way to display this wherever it is needed?

My first idea is to draw a master on canvas, which I then clone and paste where necessary on the page. A master canvas might look something like this:

var master = $('<canvas>').attr({
      width: 100,
      height: 100
    }),
    c = master[0],
    ctx = c.getContext("2d");

    ctx.fillStyle = "#FF0000";
    ctx.fillRect(0, 0, 150, 75);

Let's say I want to duplicate the canvas in these containers div:

<div class="square-container" id="square_header"></div>
...
<div class="square-container" id="square_dataTable"></div>
...
<div class="square-container" id="square_gallery"></div>
....

When the page loads, I will do this to insert a duplicate canvas element into each container:

$(document).ready(function() {
    $('.square-container').each(function() {
        master.clone().appendTo($(this));
    });
}); 

, , , , , . , , , .

, , toDataURL() :

var master = $('<canvas>').attr({
    width: 100,
    height: 100
}),
    c = master[0],
    ctx = c.getContext("2d");

    ctx.fillStyle = "#FF0000";
    ctx.fillRect(0,0,150,75);

var square = c.toDataURL('image/png'); 

, :

<img src="" id="square_header" class="square" alt="" />
...
<img src="" id="square_dataTable1" class="square" alt="" />
...
<img src="" id="square_gallery" class="square" alt="" />
....

SRC :

$(document).ready(function() {
    $('img.square').attr('src', square);
});

, . , , ? , <canvas>, , , ?

, , javascript ( , ) CANVAS_ELEMENT.toDataURL() cookie, ?

+4
1

, . , drawImage . originalCanvas duplicateCanvas, :

duplicateCanvas.getContext('2d').drawImage(originalCanvas, 0, 0);

:

  • ,

  • , cloneNode

  • , cloneNode drawImage

  • , URI

function message(s) {
  document.getElementById('message').innerHTML += s + '<br />';
}

function timeIt(action, description, initializer) {
  var totalTime = 0,
      initializer = initializer || function () {};
  initializer();
  var startTime = performance.now();
  action();
  var elapsed = performance.now() - startTime;
  message('<span class="time"><span class="number">' +
      Math.round(elapsed * 1000) + ' &mu;s</span></span> ' + description);
}

function makeCanvas() {
  var canvas = document.createElement('canvas'),
      context = canvas.getContext('2d');
  canvas.width = 100;
  canvas.height = 100;
  timeIt(function () {
    context.fillStyle = '#a63d3d';
    context.fillRect(10, 10, 80, 40);   // Paint a small scene.
    context.fillStyle = '#3b618c';
    context.beginPath();
    context.arc(60, 60, 25, 0, 2*Math.PI);
    context.closePath();
    context.fill();
  }, '(millionths of a second) to draw original scene', function () {
    context.clearRect(0, 0, canvas.width, canvas.height);
  });
  return canvas;
}

// copyCanvas returns a canvas containing the same image as the given canvas.
function copyCanvas(original) {
  var copy;
  timeIt(function () {
    copy = original.cloneNode();  // Copy the canvas dimensions.
    copy.getContext('2d').drawImage(original, 0, 0);  // Copy the image.
  }, 'to copy canvas with cloneNode and drawImage');
  return copy;
}

// imageFromStorage extracts the image data from a canvas, stores the image data
// in a browser session, then retrieves the image data from the session and
// makes a new image element out of it. We measure the total time to retrieve
// the data and make the image.
function imageFromStorage(original) {
  var image,
      dataURI = original.toDataURL();
  timeIt(function () {
    image = document.createElement('img');
    image.src = dataURI;
  }, 'to make image from a dataURI');
  return image;
}

function pageLoad() {
  var target = document.getElementById('canvases'),
      containers = {},  // We'll put the canvases inside divs.
      names = ['original', 'cloneNode', 'drawImage', 'dataURI'];
  for (var i = 0; i < names.length; ++i) {
    var name = names[i],  // Use the name as an ID and a visible header.
        container = document.createElement('div'),
        header = document.createElement('div');
    container.className = 'container';
    header.className = 'header';
    header.innerHTML = container.id = name;
    container.appendChild(header);
    target.appendChild(container);
    containers[name] = container;  // The canvas container is ready.
  }
  var canvas = makeCanvas();
  containers.original.appendChild(canvas);  // Original canvas.
  containers.cloneNode.appendChild(canvas.cloneNode());  // cloneNode
  containers.drawImage.appendChild(copyCanvas(canvas));  // cloneNode + drawImage
  containers.dataURI.appendChild(imageFromStorage(canvas));  // localStorage
}

pageLoad();
body {
  font-family: sans-serif;
}
.header {
  font-size: 18px;
}
.container {
  margin: 10px;
  display: inline-block;
}
canvas, img {
  border: 1px solid #eee;
}
#message {
  color: #666;
  font-size: 16px;
  line-height: 28px;
}
#message .time {
  display: inline-block;
  text-align: right;
  width: 100px;
}
#message .number {
  font-weight: bold;
  padding: 1px 3px;
  color: #222;
  background: #efedd4;
}
<div id="canvases"></div>

<div id="message"></div>

toDataURL , cookie. cookie . HTML5 API - . , , PNG- Cache-Control, .

, , . - . , , performance.now, .

+6

All Articles