汚染されたキャンバスはエクスポートできません


187

キャンバスを画像に保存したい。私はこの機能を持っています:

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: 'HTMLCanvasElement'で 'toDataURL'を実行できませんでした:汚染されたキャンバスはエクスポートされない可能性があります。

私は何をすべきか?


どのブラウザで?stackoverflow.com/a/21362569/476716は、これがバグであると主張しています。
OrangeDog 2014年

1
クロム上とFirefoxの
user3465096

回答:


180

セキュリティ上の理由から、ローカルドライブは「その他のドメイン」であると宣言され、キャンバスを汚染します。

(これは、最も機密性の高い情報がローカルドライブにある可能性が高いためです。)

テスト中に次の回避策を試してください。

  • ページに関連するすべてのファイル(.html、.jpg、.js、.cssなど)をデスクトップ(サブフォルダーではなく)に置きます。

  • クロスドメイン共有をサポートするサイト(dropbox.comなど)に画像を投稿します。ドロップボックスのパブリックフォルダーに画像を配置し、画像をダウンロードするときにクロスオリジンフラグも設定してください(var img = new Image(); img.crossOrigin = "anonymous" ...)

  • 開発用コンピューターにWebサーバーをインストールします(IISサーバーとPHP Webサーバーには、ローカルコンピューターで問題なく動作する無料版があります)。


16
おかげで、img.crossOriginプロパティを設定すると役に立ちました。
zumek 2014

5
@markE-ファイルやURLからではなく、localStorageから画像データを読み込んだ後、テキストを追加するなどの操作を行いました。次に、toDataURL()を使用してそれをlocalStorageにソートしようとしました。しかし、「 'HTMLCanvasElement'で 'toDataURL'を実行できませんでした:汚染されたキャンバスはエクスポートされない可能性があります」と表示されます。この場合、クロスドメインの問題を取得するためにexteranlファイルまたはURLを使用していません。では、なぜこのエラーが発生するのでしょうか。
Sajith、2015

2
@Saijth-画像に使用されているパスを確認することができます。ローカル仮想サーバーのIP(127.0.xx /)を介して直接アクセスをテストしていたが、一部のイメージがドメイン(localhost /)を介してリンクされていたため、この問題も発生しました。代わりにlocalhostを使用すると、うまくいきました。ですから、そのようなことに遭遇しないようにしてください。
ビクターD.

1
(1)c:/ localdisk / fileではなく、xampp webserver、localhost / fileから表示します。そうすれば、Chromeはセキュリティエラーについて文句を言いません。(2)やChromeを起動するときに、このフラグを使用:--allow-ファイル・アクセスから、ファイル
モッシュ

1
もう1つの考えられる問題を追加します。ForeignObjectを含むsvgを含むキャンバスをエクスポートしようとすると、一部のブラウザーはそれを汚染されているとマークします。
HairyFotr 2018年

128

imgタグで、crossoriginをAnonymousに設定します。

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

61
しかし、img要素ではなくhtml5 canvasの場合に何をすべきか
graphics123

11
canvas要素の場合、問題の原因は常に、その上に描画しているいくつかの画像にあります。したがって、ロードする前に、画像を追跡し、示されているとおりにcrossOrigin属性を設定するだけです。
Fernando Echeverria 2017

3
これは私の日を救った!
チャン


9
その午前12時のオフィスで、私はこの単純な答えを見つけます、これは純粋な幸せです
Dheeraj

26

誰かが私の答えを見た場合、あなたはおそらくこの状態にあります:

1. openlayers(バージョン> = 3)を使用してキャンバスでマップスクリーンショットを取得しようとします
2. マップエクスポートする例を表示しました
3. ol.source.XYZを使用してマップレイヤーをレンダリングします

ビンゴ!

ol.source.XYZ.crossOrigin = 'Anonymous'を使用して混乱を解決します。または次のコードのように:

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

1
素晴らしい。TileImageなどのすべてのソースに役立ちます。
Phil

素晴らしい!まさに私が自分で探していたもの、OpenLayersのデモの簡単な修正です。
Marc、

私はベクタータイルレイヤーを使用していますが、このプロパティをソースに追加した後も機能しません。
mahdi n75

まさに私が必要としたもの:)
レイ

17

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


6
これは私にはうまくいきませんでした。まだTainted canvases may not be exported.エラーメッセージが表示される。
Sam Sverko

1
わたしにはできる。ありがとう。@SamSverkoは、必ずimg.srcの前に属性を設定してください。
aijogja

14

私の場合、ビデオからキャンバスタグに描画していました。汚染されたキャンバスエラーに対処するには、2つのことを行う必要がありました。

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Access-Control-Allow-Originヘッダーがビデオソースレスポンスに設定されていることを確認します(crossdomain.example.comの適切な設定)
  • 動画タグにcrossorigin = "anonymous"を設定します

5

正しいAccess-Control-Allow-Originヘッダーが設定されていないURLの画像を使用しているため、問題が発生しているようです。サーバーからその画像をフェッチし、サーバーから取得して、CORSの問題を回避できます。


私は本当にそのすべての概念を知らないので、あなたはあなたの答えについてより正確にできますか サーバーからその画像を取得するにはどうすればよいですか?
user3465096 14年

あなたはその画像をどこからフェッチしていますか?それはあなたのサーバーからですか、それとも他の画像ですか?
Prasanna Aarthi 2014年

次のようになります。loadImage( "example.jpg"、0、0、500、300); ランダムな画像のURLまたは画像を自分のコンピューターの同じフォルダーに配置できますが、同じです
user3465096

はい、でもペイントでイメージを作成しましたが、同じです
user3465096

1
ファイルにAccess-Control-Allow-Origin:*を指定しましたが、それでもエラーが表示されます
Harikrishnan

5

useCORS: trueオプションを使用して問題を解決しました

 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の[CORS enabled image] [1]をご覧ください。基本的には、適切な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 = "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;
}


このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。- レビューから
Gowtham Shiva 2017

お知らせありがとうございます。MDNリンクからコンテンツを追加するだけです:)
BerlinaLi 2017年

1

ローカルサーバーを作成する場合は、@ markEの答えに基づいて構築します。ローカルサーバーではこのエラーは発生しません。

コンピュータにPHPがインストールされている場合:

  1. ターミナル/ cmdを開きます
  2. ウェブサイトのファイルがあるフォルダーに移動します
  3. このフォルダ内でコマンドを実行しますphp -S localhost:3000←大文字の 'S'に注意してください
  4. ブラウザを開き、URLバーでlocalhost:3000に移動します。あなたのウェブサイトはそこで実行されているはずです。

または

コンピュータにNode.jsがインストールされている場合:

  1. ターミナル/ cmdを開きます
  2. ウェブサイトのファイルがあるフォルダーに移動します
  3. このフォルダ内で、次のコマンドを実行します npm init -y
  4. ファイル名を指定して実行npm install live-server -gまたはsudo npm install live-server -gMac上
  5. 実行するlive-serverと、ウェブサイトが開いた状態でブラウザに新しいタブが自動的に開きます。

注:フォルダーのルートにindex.htmlファイルがあることを忘れないでください。そうしないと、問題が発生する可能性があります。


0

私もこのuseCORS : true,ようなコードを追加してこのエラーを解決しました-

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.