Mój kod działa bardzo dobrze na moim hoście lokalnym, ale nie działa w witrynie.
Otrzymałem ten błąd z konsoli, dla tej linii .getImageData(x,y,1,1).data
:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
część mojego kodu:
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;
}
Uwaga: adres URL mojego obrazu (src) pochodzi z adresu URL subdomeny
javascript
html
html5-canvas
Erfan Safarpoor
źródło
źródło
Odpowiedzi:
Jak powiedzieli inni, „plamiisz” płótno, ładując je z domeny o różnych źródłach.
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
Możesz jednak temu zapobiec, ustawiając po prostu:
img.crossOrigin = "Anonymous";
Działa to tylko wtedy, gdy serwer zdalny odpowiednio ustawi następujący nagłówek:
Access-Control-Allow-Origin "*"
Wyboru pliku Dropbox przy użyciu opcji „Direct Link” jest doskonałym tego przykładem. Używam go na oddprints.com, aby przenieść obrazy ze zdalnego adresu URL skrzynki domyślnej do mojego obszaru roboczego, a następnie przesłać dane obrazu z powrotem na mój serwer. Wszystko w javascript
źródło
Okazało się, że muszę użyć
.setAttribute('crossOrigin', '')
i muszę dołączyć sygnaturę czasową do ciągu zapytania adresu URL, aby uniknąć odpowiedzi 304 bezAccess-Control-Allow-Origin
nagłówka.To mi daje
var url = 'http://lorempixel.com/g/400/200/'; var imgObj = new Image(); imgObj.src = url + '?' + new Date().getTime(); imgObj.setAttribute('crossOrigin', '');
źródło
imgObj.setAttribute('crossOrigin', '')
rozwiązałem to dla mnie - dzięki!img.crossOrigin = "Anonymous"
działa również (jak wspomniano tutaj ). Przeglądarki @SanfordStaab traktują pliki lokalne jako znajdujące się w innej domenie, w przeciwnym razie właściciele witryn mogliby odczytać pliki lokalne. Musisz zażądać obrazów z tej samej domeny lub nagłówki w odpowiedzi na Twoje żądanie muszą informować przeglądarkę, że kod z innych domen może odczytać ten plik.Nie będzie można rysować obrazów bezpośrednio z innego serwera na kanwie, a następnie używać
getImageData
. Jest to kwestia bezpieczeństwa, a płótno zostanie uznane za „skażone”.Czy zadziałałoby, gdybyś zapisał kopię obrazu na serwerze za pomocą PHP, a następnie po prostu załadował nowy obraz? Na przykład możesz wysłać adres URL do skryptu PHP i zapisać go na swoim serwerze, a następnie zwrócić nową nazwę pliku do swojego javascript w następujący sposób:
<?php //The name of this file in this example is imgdata.php $url=$_GET['url']; // prevent hackers from uploading PHP scripts and pwning your system if(!@is_array(getimagesize($url))){ echo "path/to/placeholderImage.png"; exit("wrong file type."); } $img = file_get_contents($url); $fn = substr(strrchr($url, "/"), 1); file_put_contents($fn,$img); echo $fn; ?>
Używałbyś skryptu PHP z jakimś javascriptem Ajax w następujący sposób:
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; } }
Jeśli
getImageData
później użyjesz na płótnie, będzie działać dobrze.Alternatywnie, jeśli nie chcesz zapisywać całego obrazu, możesz przekazać współrzędne x & y do swojego skryptu PHP i obliczyć wartość rgba piksela po tej stronie. Myślę, że są dobre biblioteki do tego rodzaju przetwarzania obrazu w PHP.
Jeśli chcesz skorzystać z tego podejścia, daj mi znać, jeśli potrzebujesz pomocy w jego wdrożeniu.
edit-1: peeps wskazał, że skrypt php jest ujawniony i umożliwia internetowi potencjalnie złośliwe wykorzystanie go. istnieje milion sposobów, aby sobie z tym poradzić, jednym z najprostszych jest zaciemnianie adresów URL ... uważam, że bezpieczne praktyki php zasługują na osobne Google; P
edit-2: na popularne żądanie dodałem sprawdzenie, czy jest to obraz, a nie skrypt php (z: PHP sprawdź, czy plik jest obrazem ).
źródło
Widziałem ten błąd
Chrome
podczas lokalnego testowania kodu. Przerzuciłem się naFirefox
i już nie widzę błędu. Może przejście na inną przeglądarkę to szybkie rozwiązanie.Jeśli korzystasz z rozwiązania podanego w pierwszej odpowiedzi, to upewnij się, że dodajesz
img.crossOrigin = "Anonymous";
zaraz po zadeklarowaniuimg
zmiennej (np.var img = new Image();
).źródło
Twój problem polega na tym, że ładujesz obraz zewnętrzny, czyli z innej domeny. Powoduje to błąd zabezpieczeń podczas próby uzyskania dostępu do jakichkolwiek danych kontekstu kanwy.
źródło
„Plamiisz” płótno, ładując je z domeny o różnych źródłach. Przeczytaj ten artykuł w MDN:
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
źródło
Podczas pracy na lokalnym dodaj serwer
Miałem podobny problem podczas pracy na lokalnym. Twój adres URL będzie ścieżką do lokalnego pliku, np. File: ///Users/PeterP/Desktop/folder/index.html.
Pamiętaj, że korzystam z komputera MAC.
Poradziłem sobie z tym, instalując globalnie serwer http. https://www.npmjs.com/package/http-server
Kroki:
npm install http-server -g
http-server ~/Desktop/folder/
PS: Zakładam, że masz zainstalowany węzeł, w przeciwnym razie nie uzyskasz bardzo działających poleceń npm.
źródło
Jak Matt Burns mówi w swojej odpowiedzi , być może trzeba będzie włączyć CORS na serwerze, na którym są hostowane obrazy powodujące problemy.
Jeśli serwer to Apache, można to zrobić, dodając następujący fragment kodu ( stąd ) do konfiguracji VirtualHost lub do
.htaccess
pliku:<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>
... jeśli dodasz go do VirtualHost, prawdopodobnie będziesz musiał ponownie załadować konfigurację Apache (np.
sudo service apache2 reload
jeśli Apache działa na serwerze Linux)źródło
Mój problem był tak pomieszany, że po prostu zakodowałem obraz w base64, aby upewnić się, że nie ma żadnych problemów z CORS
źródło
Dziś napotykam ten sam problem i rozwiązuję go za pomocą poniższego kodu.
Kod 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>
kod js:
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) }
kod jak powyżej i nie ma problemu między domenami.
źródło
Miałem ten sam problem i dla mnie zadziałało to po prostu łącząc
https:${image.getAttribute('src')}
źródło