Boyalı tuvaller dışa aktarılamaz


187

Tuvalimi bir img'e kaydetmek istiyorum. Bu işlevi var:

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

Bana hata veriyor:

Yakalanmamış SecurityError: 'HTMLCanvasElement' öğesinde 'toDataURL' yürütülemedi: Boyalı tuvaller dışa aktarılamayabilir.

Ne yapmalıyım?


Hangi tarayıcıda? stackoverflow.com/a/21362569/476716 , bunun bir hata olduğunu iddia ediyor.
OrangeDog

1
krom ve firefox'ta
user3465096

Yanıtlar:


180

Güvenlik nedeniyle, yerel sürücünüz "diğer etki alanı" olarak ilan edilir ve tuvali kirletir.

(Bunun nedeni, en hassas bilgilerinizin yerel sürücünüzde bulunmasıdır!).

Test sırasında şu geçici çözümleri deneyin:

  • Sayfa ile ilgili tüm dosyaları (.html, .jpg, .js, .css vb.) Masaüstünüze (alt klasörlere değil) koyun.

  • Resimlerinizi web alanları arası paylaşımı destekleyen bir siteye gönderin (dropbox.com gibi). Resmi indirirken resimlerinizi dropbox'ın ortak klasörüne koyduğunuzdan ve ayrıca çapraz kökenli bayrağı ayarladığınızdan emin olun (var img = new Image (); img.crossOrigin = "anonim" ...)

  • Geliştirme bilgisayarınıza bir web sunucusu yükleyin (IIS ve PHP web sunucularının her ikisinin de yerel bilgisayarda güzel çalışan ücretsiz sürümleri vardır).


16
Teşekkürler, img.crossOrigin özelliğini ayarlamak bana yardımcı oldu!
zumek

5
@markE - Dosyadan veya herhangi bir url'den yüklemek yerine localStorage'dan görüntü verileri yükledim, sonra metin eklemek gibi bazı değişiklikler yaptım. Sonra toDataURL () kullanarak localStorage geri sotre çalıştı. Ancak "HTMLCanvasElement" üzerinde "toDataURL" çalıştırılamadı: Boyalı tuvaller dışa aktarılamayabilir "gösterir. Bu durumda, etki alanları arası bir sorun elde etmek için herhangi bir exteranl dosyası veya url kullanmıyorum. O zaman neden bu hatayla sonuçlanıyor?
Sajith

2
@Saijth - Görüntüler için kullanılan yolu doğrulamak isteyebilirsiniz. Ben de IP (127.0.xx /) üzerinden yerel sanal sunucuma doğrudan erişim test ediyordum ama bazı görüntüleri etki alanı (localhost /) ile bağlı olduğu için de bu sorunu vardı. Bir kez bunun yerine localhost kullandım. Bu yüzden böyle bir şeyle karşılaşmadığınızdan emin olun.
Victor D.

1
(1) c: / localdisk / file yerine xampp webserver, localhost / dosyasından görüntüleyin; chrome Güvenlik Hatası'ndan şikayet etmez. (2) Veya kromu başlatırken bu bayrağı kullanın:
mosh

1
Başka bir olası sorun daha eklemek gerekirse: ForeignObject ile bir svg içeren bir tuvali dışa aktarmaya çalışıyorsanız, bazı tarayıcılar bunu renkli olarak işaretler.
HairyFotr

128

İmg etiketinde crossorigin'i Anonim olarak ayarlayın.

<img crossorigin="anonymous"></img>

61
Ama html5 tuval durumunda ne yapmalı, img elemanları değil
graphics123

11
Bir tuval öğesi söz konusu olduğunda, sorunun kaynağı her zaman üzerine çizdiğiniz bazı görüntü (veya görüntüler) ile olur. Bu yüzden yüklemeden önce görüntüyü izlemeniz ve crossOrigin niteliğini belirtildiği gibi ayarlamanız yeterlidir.
Fernando Echeverria

3
Bu benim günümü kurtardı!
Chang

1
Mutlu yardım :)
Annia Martinez

9
ofiste 12 am im ve bu basit cevap bulmak, bu saf mutluluk
Dheeraj

26

Birisi cevabımı görüntülerse, belki bu durumda:

1. Openlayers kullanarak tuvalde bir harita ekran görüntüsü almaya çalışmak (sürüm> = 3)
2. Ve haritayı dışa aktarma örneğini inceledi
3. Harita katmanını oluşturmak için ol.source.XYZ kullanma

Bingo!

Kullanılması ol.source.XYZ.crossOrigin = 'Anonim' senin karıştırmayın çözmek için. Veya aşağıdaki kod gibi:

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

1
fantastik. TileImage gibi tüm kaynaklar için kullanışlıdır.
Phil

Fatastic! Tam olarak kendimi aradığım şey, yaptığım bir OpenLayers demosu için kolay düzeltme.
Marc

Vektör kiremit katmanları kullanıyorum ve sonra kaynak için bu özelliği eklemek ama çok da çalışmıyor!
Mehdi n75

Tam ihtiyacım olan şey :)
Ray

17

ctx.drawImage()İşlev kullanıyorsanız , aşağıdakileri yapabilirsiniz:

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;
}

Ve geri aramanızda artık ctx.drawImagekullanaraktoDataURL


6
Bu benim için işe yaramadı. Hala Tainted canvases may not be exported.hata mesajı alıyorum .
Sam Sverko

1
benim için çalışıyor. Teşekkürler. @SamSverko, özniteliği img.src'den önce ayarladığınızdan emin olun.
aijogja

14

Benim durumumda bir videodan bir tuval etiketine çizim yapıyordum. Kirli tuval hatasını gidermek için iki şey yapmak zorunda kaldım:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Video kaynağı yanıtında Access-Control-Allow-Origin başlığının ayarlandığından emin olun (crossdomain.example.com'un doğru kurulumu)
  • Video etiketini crossorigin = "anonim" olarak ayarlayın

5

Görünüşe göre, doğru Erişim-Kontrol-İzin Ver-Kökeni üstbilgisi ayarlamayan bir URL'den bir resim kullanıyorsunuz ve dolayısıyla sorun .. CORS sorunlarından kaçınmak için bu resmi sunucunuzdan alabilir ve sunucunuzdan alabilirsiniz ..


Cevabınız hakkında daha kesin olabilir misiniz, çünkü tüm bu kavramı gerçekten bilmiyorum. Bu görüntüyü sunucumdan nasıl alırım?
user3465096

bu görüntüyü nereden alıyorsunuz, sunucunuzdan mı yoksa başka bir görüntüden mi?
Prasanna Aarthi

Şöyle gider: loadImage ("example.jpg", 0, 0, 500, 300); Bilgisayarımdaki aynı klasöre rastgele resim url'si veya resim koyabilirim, hala aynı
user3465096

evet, ama ben sadece boya üzerinde görüntü oluşturdu ve hala aynı
user3465096

1
Dosya için Access-Control-Allow-Origin: * verdim, ancak yine de hatayı gösteriyor
Harikrishnan

5

useCORS: trueSeçeneğini kullanarak sorunu çözdüm

 html2canvas(document.getElementsByClassName("droppable-area")[0], { useCORS:true}).then(function (canvas){
        var imgBase64 = canvas.toDataURL();
        // console.log("imgBase64:", imgBase64);
        var imgURL = "data:image/" + imgBase64;
        var triggerDownload = $("<a>").attr("href", imgURL).attr("download", "layout_"+new Date().getTime()+".jpeg").appendTo("body");
        triggerDownload[0].click();
        triggerDownload.remove();
    });

3

MDN'den [CORS etkin resim] [1] 'e göz atın. Temel olarak uygun Access-Control-Allow-Origin üstbilgisine sahip görüntüleri barındıran bir sunucunuz olmalıdır.

<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>

Bu görüntüleri alan adınızdan sunulmuş gibi DOM Storage'a kaydedebilirsiniz; aksi takdirde güvenlik sorunu yaşarsınız.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; // 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;
}


Bu bağlantı soruyu cevaplayabilse de, cevabın temel kısımlarını buraya eklemek ve bağlantıyı referans olarak sağlamak daha iyidir. Bağlantı verilen sayfa değişirse, yalnızca bağlantı yanıtları geçersiz olabilir. - Yorumdan
Gowtham Shiva

Uyarı için teşekkürler. Ben sadece MDN link içeriği ekleyin :)
BerlinaLi

1

Yerel bir sunucu oluşturmak istiyorsanız, @ markE'nin cevabı üzerine bir derleme gibi. Yerel bir sunucuda bu hatayı almayacaksınız.

Bilgisayarınızda PHP yüklüyse:

  1. Terminalinizi / cmd'nizi açın
  2. Web sitesi dosyalarınızın bulunduğu klasöre gidin
  3. Bu klasördeyken, php -S localhost:3000`` S '' harfine dikkat edin
  4. Tarayıcınızı açın ve URL çubuğunda localhost: 3000'e gidin . Web siteniz orada çalışıyor olmalıdır.

veya

Bilgisayarınızda Node.js yüklüyse:

  1. Terminalinizi / cmd'nizi açın
  2. Web sitesi dosyalarınızın bulunduğu klasöre gidin
  3. Bu klasördeyken, komutu çalıştırın npm init -y
  4. Mac'te npm install live-server -gveya sudo npm install live-server -gMac'te çalıştırın
  5. Çalıştırın live-serverve web siteniz açıkken tarayıcıda otomatik olarak yeni bir sekme açmalıdır.

Not: klasörünüzün kök dizininde bir index.html dosyası bulunduğunu unutmayın, aksi takdirde bazı sorunlarınız olabilir.


0

Ben de useCORS : true,benim gibi kod ekleyerek bu hatayı çözdü -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.