Испорченные холсты не могут быть экспортированы


Я хочу сохранить свой холст в img. У меня есть такая функция:

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

Это дает мне ошибку:

Uncaught SecurityError: не удалось выполнить 'toDataURL' на 'HTMLCanvasElement': испорченные полотна не могут быть экспортированы.

Что делать?

7 110

7 ответов:

по соображениям безопасности ваш локальный диск объявлен "другим доменом" и испортит холст.

(Это потому, что ваша самая конфиденциальная информация, скорее всего, на вашем локальном диске!).

во время тестирования попробуйте эти способы:

  • Поместите все связанные с страницей файлы (.формат HTML. ,формат JPG. ,js,.CSS и т. д.) На рабочем столе (не в подпапках).

  • разместите свои изображения на сайте, который поддерживает междоменный обмен (например dropbox.com). Убедитесь, что вы поместили свои изображения в общую папку dropbox, а также установили флаг cross origin при загрузке изображения (var img=new Image(); img.crossOrigin="аноним" ...)

  • установите веб-сервер на компьютере разработчика (веб-серверы IIS и PHP имеют бесплатные выпуски, которые хорошо работают на локальном компьютере).

в теге img установите cross origin в Anonymous

<img crossOrigin="Anonymous"></img>

в моем случае я рисовал на холст тег из видео. Чтобы устранить ошибку испорченного холста, мне пришлось сделать две вещи:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • убедитесь, что заголовок Access-Control-Allow-Origin установлен в ответе источника видео (Правильная настройка crossdomain.example.com)
  • установите видео тег, чтобы иметь crossorigin= "anonymous"

похоже, что вы используете изображение из URL-адреса, который не установил правильный заголовок Access-Control-Allow-Origin и, следовательно, проблему.. Вы можете получить это изображение с вашего сервера и получить его с вашего сервера, чтобы избежать проблем CORS..

Если кто-то смотрит на мой ответ, вы, возможно, в этом состоянии:

1. Попытка получить скриншот карты на холсте с помощью openlayers 3 или 4
2. И посмотрел пример экспорт карту
3. Используя ол.источник.XYZ для отображения слоя карты

Бинго!

С помощью ol.источник.XYZ.crossOrigin = 'Anonymous' чтобы решить вашу запутать. Или как следующий код:

     var baseLayer = new ol.layer.Tile({
         name: 'basic',
         source: new ol.source.XYZ({
             url: options.baseMap.basic,
             crossOrigin: "Anonymous"
         })
     });

проверить CORS включен image от MDN. В основном у вас должен быть сервер, на котором размещаются изображения с соответствующим заголовком Access-Control-Allow-Origin.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

вы сможете сохранить эти изображения в хранилище DOM, как если бы они обслуживались из вашего домена, иначе вы столкнетесь с проблемой безопасности.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "http://example.com/image"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}

если вы используете ctx.drawImage() функция, вы можете сделать следующее:

var img = loadImage('../yourimage.png', callback);

function loadImage(src, callback) {
    var img = new Image();

    img.onload = callback;
    img.setAttribute('crossOrigin', 'anonymous'); // works for me

    img.src = src;

    return img;
}

и в функции обратного вызова вы можете использовать ctx.drawImage и экспортировать его с помощью toDataURL