4

2 つの HTML キャンバスを 1 つのキャンバスにマージしてから、それを画像としてダウンロードしようとしています。私のコードは以下の通りです:

function downloadCanvas() {
    var bottleCanvas = document.getElementById('bottleCanvas');
    var designCanvas = document.getElementById('editorCanvas');

    var bottleContext = bottleCanvas.getContext('2d');
    bottleContext.drawImage(designCanvas, 69, 50);

    var dataURL = bottleCanvas.toDataURL("image/png");
    var link = document.createElement('a');
    link.download = "bottle-design.png";
    link.href = bottleCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
    link.click();
}

ここでの私の問題は、次の行のようです。

bottleContext.drawImage(designCanvas, 69, 50);

これは、一方のキャンバスのコンテンツを他方のキャンバスに描画することを想定していますが、実際にはそうしていますが、コードの後半部分が実行されて画像がダウンロードされるのを防ぎます。この特定の行を削除すると、ダウンロード機能は正常に機能しますが、残念ながらキャンバスの 1 つしかダウンロードされません。

したがって、私の質問は次のいずれかです。ここで何が間違っているのですか? または 2 つの HTML キャンバスをマージして、画像としてダウンロードするにはどうすればよいですか。

(別の注意として、ダウンロード用の上記のコードは Chrome でのみ正常に機能します。他のブラウザーでは、ファイルの名前を設定してファイル拡張子を設定することはできません。)

4

1 に答える 1

6

ソースがクロスドメインの画像をキャンバスに描画すると、セキュリティ エラーが発生する可能性があります。任意のキャンバスにクロスドメイン イメージを描画すると、そのキャンバスが「汚染」さcontext.toDataURLれ、実行しようとすると許可されなくなり、セキュリティ エラーが発生しますtoDataURL。汚染されたキャンバスを汚染されていないキャンバスに drawImage すると、これと同じ「汚染」が発生します。

修正は、キャンバスに描画するすべての画像が Web ページと同じドメインで作成されていることを確認することです。

以下は、クロスドメイン セキュリティ エラーを発生させない画像を使用している場合に正しく動作するコードの例です。

var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/fish.jpg";
function start(){

  var bottleCanvas = document.getElementById('bottleCanvas');
  var designCanvas = document.getElementById('editorCanvas');
  var ctxb=bottleCanvas.getContext('2d');
  var ctxd=editorCanvas.getContext('2d');

  ctxb.drawImage(img,0,0);
  ctxd.fillRect(50,50,50,50);

  downloadCanvas();
}

function downloadCanvas() {
  var bottleCanvas = document.getElementById('bottleCanvas');
  var designCanvas = document.getElementById('editorCanvas');

  var bottleContext = bottleCanvas.getContext('2d');
  bottleContext.drawImage(designCanvas, 69, 50);

  var dataURL = bottleCanvas.toDataURL("image/png");
  var link = document.createElement('a');
  link.download = "bottle-design.png";
  link.href = bottleCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
  link.click();
}
body{ background-color: ivory; }
canvas{border:1px solid red;}
<canvas id="bottleCanvas" width=300 height=300></canvas>
<canvas id="editorCanvas" width=300 height=300></canvas>

クロスオリジンのセキュリティ制限を満たす

イメージへのクロスオリジン アクセスを既に許可しているサーバーでイメージをホストできます。それが、上記の例で行っていることです。Dropbox.com では、キャンバスを「汚す」ことなく、ホストしている画像をキャンバスに描画できるように指定できます。

イメージへのクロスオリジン アクセスを許可するように S3 バケットを設定することもできます。このリンクでは、応答ヘッダーをサーバーのクロスオリジン イメージに設定する方法について説明しています: http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

私の例のように、クロスオリジンの画像を使用している場合はimage.crossOrigin='anonymous'、JavaScript で最初に画像オブジェクトを作成するときにもフラグを設定する必要があることに注意してください。

于 2015-04-10T01:45:19.033 に答える