Как исправить ошибку getImageData() Холст был испорчен данными перекрестного происхождения?
Мой код работает очень хорошо на моем localhost, но он не работает на сайте.
Я получил эту ошибку с консоли, для этой строки .getImageData(x,y,1,1).data
:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
часть моего кода:
jQuery.Event.prototype.rgb=function(){
var x = this.offsetX || (this.pageX - $(this.target).offset().left),y = this.offsetY || (this.pageY - $(this.target).offset().top);
if (this.target.nodeName!=="CANVAS")return null;
return this.target.getContext('2d').getImageData(x,y,1,1).data;
}
Примечание: мой url изображения (src) - из URL поддомена
Ответы
Ответ 1
Как уже говорили другие, вы "портите" холст, загружая его из домена перекрестного происхождения.
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
Однако вы можете предотвратить это, просто установив:
img.crossOrigin = "Anonymous";
Это работает, только если удаленный сервер устанавливает следующий заголовок соответствующим образом:
Access-Control-Allow-Origin "*"
Отличным примером этого является средство выбора файлов Dropbox при использовании опции "прямая ссылка". Я использую его на oddprints.com для перемещения изображений из URL- адреса удаленного изображения в Dropbox на свой холст, а затем отправляю данные изображений обратно на мой сервер. Все в JavaScript
Ответ 2
Я обнаружил, что мне пришлось использовать .setAttribute('crossOrigin', '')
и мне пришлось добавить временную метку в строку запроса URL-адреса, чтобы избежать ответа 304 без заголовка Access-Control-Allow-Origin
.
Это дает мне
var url = 'http://lorempixel.com/g/400/200/';
var imgObj = new Image();
imgObj.src = url + '?' + new Date().getTime();
imgObj.setAttribute('crossOrigin', '');
Ответ 3
Вы не сможете рисовать изображения с другого сервера на холст, а затем использовать getImageData
. Это проблема безопасности, и полотно будет считаться "испорченным".
Будет ли работать для вас, чтобы сохранить копию изображения на ваш сервер с помощью PHP, а затем просто загрузить новое изображение? Например, вы можете отправить URL-адрес на PHP script и сохранить его на свой сервер, а затем вернуть новое имя файла в свой javascript следующим образом:
<?php //The name of this file in this example is imgdata.php
$url=$_GET['url'];
$img = file_get_contents($url);
$fn = substr(strrchr($url, "/"), 1);
file_put_contents($fn,$img);
echo $fn;
?>
Вы используете PHP script с некоторым javascript ajax следующим образом:
xi=new XMLHttpRequest();
xi.open("GET","imgdata.php?url="+yourImageURL,true);
xi.send();
xi.onreadystatechange=function() {
if(xi.readyState==4 && xi.status==200) {
img=new Image;
img.onload=function(){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.src=xi.responseText;
}
}
Если после этого вы используете getImageData
на холсте, он будет работать нормально.
В качестве альтернативы, если вы не хотите сохранять изображение целиком, вы можете передать координаты x и y на ваш PHP script и вычислить значение пикселя rgba на этой стороне. Я думаю, что есть хорошие библиотеки для выполнения такой обработки изображений в PHP.
Если вы хотите использовать этот подход, дайте мне знать, если вам нужна помощь в его реализации.
Ответ 4
Ваша проблема заключается в том, что вы загружаете внешнее изображение, то есть из другого домена. Это приводит к ошибке безопасности при попытке доступа к любым данным вашего контекста canvas.
Ответ 5
Вы "испортили" холст, загрузив его из перекрестного источника. Ознакомьтесь с этой статьей MDN:
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
Ответ 6
Я видел эту ошибку в Chrome
когда тестировал свой код локально. Я перешел на Firefox
и больше не вижу ошибки. Возможно, переключение на другой браузер - это быстрое решение.
Если вы используете решение, указанное в первом ответе, обязательно добавьте img.crossOrigin = "Anonymous";
сразу после объявления переменной img
(например, var img = new Image();
).
Ответ 7
Как матовый ожог говорит в его ответ, вам может потребоваться включить CORS на сервере, где размещены изображения проблем.
Если сервер Apache, это можно сделать, добавив следующий фрагмент (из здесь) либо в конфигурацию VirtualHost, либо в .htaccess
файл:
<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>
... если добавить его в VirtualHost, вам, вероятно, потребуется перезагрузить конфигурацию Apache (например. sudo service apache2 reload
, если Apache работает на сервере Linux)
Ответ 8
При работе на локальном сервере добавь сервер
У меня была похожая проблема при работе на местном. Ваш URL будет путь к локальному файлу, например file:///Users/PeterP/Desktop/folder/index.html.
Обратите внимание, что я нахожусь на MAC.
Я обошел это, установив http-сервер по всему миру. https://www.npmjs.com/package/http-server
шаги:
- Глобальная установка:
npm install http-server -g
- Запустить сервер:
http-server ~/Desktop/folder/
PS: я предполагаю, что у вас установлен узел, в противном случае вы не будете слишком далеко запускать команды npm.
Ответ 9
Сегодня я сталкиваюсь с той же проблемой и решаю ее с помощью кода.
html-код:
<div style='display: none'>
<img id='img' src='img/iak.png' width='600' height='400' />
</div>
<canvas id='iak'>broswer don't support canvas</canvas>
js code:
var canvas = document.getElementById('iak')
var iakImg = document.getElementById('img')
var ctx = canvas.getContext('2d')
var image = new Image()
image.src=iakImg.src
image.onload = function () {
ctx.drawImage(image,0,0)
var data = ctx.getImageData(0,0,600,400)
}
как указано выше, и нет проблемы между доменами.
Ответ 10
У меня https:${image.getAttribute('src')}
та же проблема, и для меня это сработало простым объединением https:${image.getAttribute('src')}