10

以下のコードを使用して、2 つのキャンバス要素を比較しています

function createImage(html, can) {
     var canvas = $( "#" + can );
     var ctx = canvas[0].getContext("2d");
     var data = "<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='1000'>" +
                    "<foreignObject width='100%' height='100%'>" +
                        "<div xmlns='http://www.w3.org/1999/xhtml'>" +
                            html +
                        "</div>" +
                    "</foreignObject>" +
                "</svg>";
    var DOMURL = self.URL || self.webkitURL || self;
    var img = new Image();
    img.crossOrigin = '';
    var svg = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
    var url = DOMURL.createObjectURL(svg);
    img.onload = function () {
        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);
    };
    img.src = url;
    //return img.src;
    return canvas[0];
}
var a1 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>","can1");
var a2 = createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>", "can2");
setTimeout(function() {
    var ctx1 = a1.getContext('2d');
    var imageData = ctx1.getImageData(0, 0, a1.width, a1.height);
    var pixels = imageData.data;
    var ctx2 = a2.getContext('2d');
    var imageData2 = ctx2.getImageData(0, 0, a2.width, a2.height);
    var pixels2 = imageData2.data, count;
    for(var i = 0, il = pixels.length; i < il; i++) {
        if(pixels[i] == pixels2[i]){
            count++;
        }
    }
    if(count === pixels.length && count === pixels2.length){
        alert("Match");
    }
},5000);

しかし、以下のようなエラーが返されます

クロスオリジン データによってキャンバスが汚染されているため、キャンバスから画像データを取得できません。

このエラーを取り除くにはどうすればよいですか?

4

2 に答える 2

5

クロスオリジン エラーが発生する理由は、異なるオリジンの に<svg>ある with 名前空間宣言を使用しているためです。http://www.w3.org/

var data = "<svg xmlns='http://www.w3.org/2000/svg' width='1000' height='1000'>" +
             "<foreignObject width='100%' height='100%'>" +
               "<div xmlns='http://www.w3.org/1999/xhtml'>" +
                    html +
               "</div>" +
             "</foreignObject>" +
           "</svg>";

このメソッドは、Drawing DOM objects into a canvas on MDN のものであることがわかります。

この方法でデータに再アクセスすると、

var ctx1 = a1.getContext('2d');
var imageData = ctx1.getImageData(0, 0, a1.width, a1.height);

エラーが発生します:

クロスオリジン データによってキャンバスが汚染されているため、キャンバスから画像データを取得できません。

これを Chrome でテストできます。

このエラーを回避するには、関数からのみデータを返すことができます。しかし、 の非同期性のためにimg.onload

img.onload = function () {
    ctx.drawImage(img, 0, 0);
    DOMURL.revokeObjectURL(url);
};

データの取得を延期する必要があり、関数からデータに再アクセスする必要があり、エラーが発生します。

したがって、 html2canvas<svg>など、 に依存しない DOM オブジェクトを使用してキャンバスを構築する別の方法を使用する必要があります。

function createImage(html) {
    var dfd = new $.Deferred();
    var el = document.createElement("div");
        el.innerHTML = html;
        el.style.display = 'inline-block';
        document.body.appendChild(el);
    html2canvas(el, {
      onrendered: function(canvas) {
          document.body.appendChild(canvas);
          document.body.removeChild(el);
          dfd.resolve(canvas.toDataURL());
      }
    });
    return dfd;
}
$.when(
    createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>"), 
    createImage("<span style='font-size:34px'><i><b>Hello</b></i></span>")
).done(function(a1, a2){
   if (a1 === a2) {
      alert("Match"); 
   }
});

デモを参照してください。

于 2013-05-10T18:38:20.037 に答える
1

「クロスオリジンポリシー」の問題について

クロスオリジン データによってキャンバスが汚染されているため、キャンバスから画像データを取得できません。SECURITY_ERR: DOM 例外 18

これは、ナビゲーターの「クロス オリジン ポリシー」によって引き起こされるセキュリティ上の問題です。


このエラーは、キャンバスが「汚れている」場合に表示されます。これは、異なるオリジンからのイメージをキャンバスに描画することによって行われます。たとえば、キャンバスが www.example.com でホストされていて、www.wikipedia.org の画像を使用している場合、キャンバスorigin-cleanフラグはfalse内部的に設定されます。

origin-clean フラグが に設定されるとfalse、電話をかけtoDataURLたり、getImageData


技術的には、ドメイン、プロトコル、およびポートが一致する場合、イメージは同じオリジンです。


ローカルで作業している場合 (file://)、描画された画像はフラグをオフに設定します。これはデバッグを面倒にしますが、Chrome ではこれ--allow-file-access-from-filesを許可するフラグで開始できます。


詳細については、次の記事を参照してください:「HTML5 Canvas のイメージ セキュリティ ルールについて」。

サイモン・サリスの功績

私のファイルは同じドメインにあるか、chrome フラグが有効になっていますが、まだこのエラーが発生します。何が起こっていますか?

問題は、SVG ドキュメントがキャンバスに描画されると、Chrome (現在) が常にキャンバスを汚染することです。

より詳細な説明については、以下の質問を参照してください。

ドキュメント内の SVG を Canvas にラスタライズする

わかりました、svg の使用が問題のようですが、どうすれば修正できますか?

私が執筆している時点で、アントニーはそれに答えました!

彼の答えを見てください

于 2013-05-05T17:57:00.337 に答える