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

129

Я хотел бы скопировать ВСЕ содержимое одного холста и перенести его на другой на стороне клиента. Я бы подумал, что использую метод canvas.toDataURL()and 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

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

Дж. Као
источник

Ответы:

273

На самом деле вам вообще не нужно создавать образ. 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 . Как упоминал Дейв в комментарии под этим ответом, вы не можете использовать контекст рисования холста в качестве источника . Если у вас есть контекст рисования холста, а не элемент холста, из которого он был создан, есть ссылка на исходный элемент холста в контексте ниже context.canvas.

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

Роберт Херст
источник
66
небольшой момент, который меня сбил с толку: хотя вы можете нарисовать холст ( HTMLCanvasElement), вы не можете нарисовать контекст ( CanvasRenderingContext2D). myContext.canvasВместо этого используйте .
Дэйв
3
Комментарий @Dave НЕОБХОДИМО ПРОЧИТАТЬ ... если возможно, поставьте +10;). @ Роберт-Херст должен дополнить свой ответ этим комментарием, поскольку он не уточняет, откуда он source canvas...
Пауло Буэно,
Не могли бы вы привести пример?
ShibinRagh 03
@RogerGajraj На самом деле холст не обязательно должен быть виден. Это продемонстрировано там => jsfiddle.net/d36wwtvj
Роберт Херст
2

@ robert-hurst предлагает более чистый подход.

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

    // select canvas elements
    var sourceCanvas = document.getElementById("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;
vishwarajanand
источник