Как скопировать содержимое одного холста на другой холст на локальном уровне

Я бы хотел скопировать ВСЕ содержимое одного холста и перенести их на другое на клиентской стороне. Я бы подумал, что я бы использовал методы canvas.toDataURL() и context.drawImage() для реализации этого, но я столкнулся с несколькими проблемами.

Моим решением было бы получить canvas.toDataURL() и сохранить его в объекте Image в Javascript, а затем использовать метод context.drawImage(), чтобы поместить его обратно.

Однако, я считаю, что метод toDataURL возвращает 64-битный кодированный тег с "data:image/png;base64,", добавленным к нему. Это, похоже, не является допустимым тегом (я всегда мог бы использовать некоторый RegEx для его удаления), но является ли эта 64-битная кодированная строка ПОСЛЕ подстроки "data:image/png;base64," действительным изображением? Могу ли я сказать image.src=iVBORw...ASASDAS и нарисовать это на холсте?

Я рассмотрел некоторые связанные проблемы: Показать изображение холста с одного холста на другой холст с использованием base64

Но решения не кажутся правильными.

Ответ 1

На самом деле вам не нужно создавать изображение вообще. drawImage() будет принимать Canvas, а также объект Image.

//grab the context from your destination canvas
var destCtx = destinationCanvas.getContext('2d');

//call its drawImage() function passing it the source canvas directly
destCtx.drawImage(sourceCanvas, 0, 0);

Способ быстрее, чем использование объекта ImageData или Image.

Обратите внимание, что sourceCanvas может быть HTMLImageElement, HTMLVideoElement или HTMLCanvasElement. Как указано в Dave в комментарии ниже этого ответа, вы не можете использовать контекст рисования в качестве источника. Если у вас есть контекст рисования холста, а не элемент холста, из которого он был создан, есть ссылка на исходный элемент холста в контексте под context.canvas.

Вот jsPerf, чтобы показать, почему это единственный правильный способ клонирования холста: http://jsperf.com/copying-a-canvas-element

Ответ 2

@robert-hurst имеет более чистый подход, но это решение может использоваться в тех местах, где вы действительно хотите иметь копию URL-адреса данных после копирования. Примеры: когда вы создаете веб-сайт, на котором много операций с изображением/холстом.

    // select canvas elements
    var sourceCanvas = document.getElementsById("some-unique-id");
    var destCanvas = document.getElementsByClassName("some-class-selector")[0];

    //copy canvas by DataUrl
    var sourceImageData = sourceCanvas.toDataURL("image/png");
    var destCanvasContext = destCanvas.getContext('2d');

    var destinationImage = new Image;
    destinationImage.onload = function(){
      destCanvasContext.drawImage(destinationImage,0,0);
    };
    destinationImage.src = sourceImageData;

Ответ 3

Мне удалось заставить его работать, что я сделал правильно:

testImage = new testImage();
testImage.src = data:image/png;base64,iVBORw0KG......kSZIkSZIkSZI0u/1/diDteJCiN80AAAAASUVORK5CYII=

(Пример выше URL-адреса)

context.drawImage(testImg,0,0);

Это работает, когда я запускаю его на консоли в Chrome и FireBug