var canvasPromise = html2canvas(document.body, {
allowTaint: true,
useCORS: true
});
canvasPromise.then(function(canvas) {
document.body.appendChild(canvas);
console.log(canvas);
canvas.toDataURL('image/png');
});
Uncaught(in promise)DOMException: 'HTMLCanvasElement'で 'toDataURL'を実行できませんでした:汚染されたキャンバスをエクスポートできない場合があります。
私も同じ問題を抱えています。
解決策または回避策を見つけましたか?
Firefox 61.0.2でも同じことをしていますが、allowTaintをtrueに設定しているにもかかわらず、SecurityErrorが発生します。
私の知る限り解決策はありませんが、回避策があります。すべての画像をbase64に変更します。 そうすれば、元々別のドメインからのものであっても、キャンバスでレンダリングできます。
これを見たことがありますか: CORS_enabled_image
外部コンテンツのソースがHTMLの場合要素、キャンバスのコンテンツを取得しようとすることは許可されていません。
CORSの承認なしに別のオリジンからロードされたデータをキャンバスに描画するとすぐに、キャンバスが汚染されます。
私は次のような構成オプションを使用します:
html2canvas(document.body, {
allowTaint: true,
foreignObjectRendering: true
});
こんにちは、私たちは同じ問題に直面しました。 変換を行うプロキシURLがすでにあるため、 @ dorklord23の提案に従いました。
誰かがそれが役に立ったと思った場合の解決策は次のとおりです。
html2canvas(document.body, {
proxy: this._proxyURL,
allowTaint: true,
onclone: (cloned) => convertAllImagesToBase64(this._proxyURL, cloned),
}).then((canvas) => {
this._postmessageChannel.send(`get.screenshot:${canvas.toDataURL('image/png')}`);
});
ヘルパー関数convertAllImagesToBase64は次のとおりです。
const convertAllImagesToBase64 = (proxyURL, cloned) => {
const pendingImagesPromises = [];
const pendingPromisesData = [];
const images = cloned.getElementsByTagName('img');
for (let i = 0; i < images.length; i += 1) {
// First we create an empty promise for each image
const promise = new Promise((resolve, reject) => {
pendingPromisesData.push({
index: i, resolve, reject,
});
});
// We save the promise for later resolve them
pendingImagesPromises.push(promise);
}
for (let i = 0; i < images.length; i += 1) {
// We fetch the current image
fetch(`${proxyURL}?url=${images[i].src}`)
.then((response) => response.json())
.then((data) => {
const pending = pendingPromisesData.find((p) => p.index === i);
images[i].src = data;
pending.resolve(data);
})
.catch((e) => {
const pending = pendingPromisesData.find((p) => p.index === i);
pending.reject(e);
});
}
// This will resolve only when all the promises resolve
return Promise.all(pendingImagesPromises);
};
export { convertAllImagesToBase64 };
ちなみに、これはそのヘルパー関数のテストです(テストとmockFetchパッケージの作成にjestを使用しています):
import { convertAllImagesToBase64 } from '../images';
fetch.resetMocks();
// Mock fetch to respond different for each image so we can assert that the image return the correct response
// Also make one of the response be delayed (2 seconds) to simulate the response is not in the same order we do the call (network latency, image size, etc)
fetch.mockImplementation((url) => {
if (url.includes('imagesrc1')) {
return Promise.resolve(new Response(JSON.stringify('data:image/png;base64,1')));
} else if (url.includes('imagesrc2')) {
return new Promise((resolve) => setTimeout(resolve(new Response(JSON.stringify('data:image/png;base64,2'))), 2000));
} else if (url.includes('imagesrc3')) {
return Promise.resolve(new Response(JSON.stringify('data:image/png;base64,3')));
}
return Promise.resolve(new Response(JSON.stringify('')));
});
const mocksImages = [
{ id: 1, src: 'imagesrc1' },
{ id: 2, src: 'imagesrc2' },
{ id: 3, src: 'imagesrc3' },
];
const mockClone = {
getElementsByTagName: jest.fn(() => mocksImages),
};
describe('utils/images', () => {
it('convertAllImagesToBase64. Expect to call 3 times to the correct enpoint using the image source', async () => {
const allPromises = convertAllImagesToBase64('http://localhost/fake_proxy', mockClone);
// Expect the clone elements gets all the image tags
expect(mockClone.getElementsByTagName).toBeCalledWith('img');
allPromises.then(() => {
// Expect to have done the 3 fetch calls and with the correct params
expect(fetch).toBeCalledTimes(3);
expect(fetch).toHaveBeenNthCalledWith(1, 'http://localhost/fake_proxy?url=imagesrc1');
expect(fetch).toHaveBeenNthCalledWith(2, 'http://localhost/fake_proxy?url=imagesrc2');
expect(fetch).toHaveBeenNthCalledWith(3, 'http://localhost/fake_proxy?url=imagesrc3');
// Expect that our images where updated properly
expect(mocksImages).toContainEqual({
id: 1, src: 'data:image/png;base64,1',
});
expect(mocksImages).toContainEqual({
id: 2, src: 'data:image/png;base64,2',
});
expect(mocksImages).toContainEqual({
id: 3, src: 'data:image/png;base64,3',
});
});
});
});
Rubyバックエンドenpdoint:
require 'base64'
require 'net/http'
module Api
module V1
class ImageProxyController < ApiController
def index
url = URI.parse(params[:url])
image = Net::HTTP.get_response(url)
render json: data_url(image).to_json, callback: params[:callback]
end
private
def data_url(image)
"data:#{image.content_type};base64,#{Base64.encode64(image.body)}"
end
end
end
end
誰かがこれがお役に立てば幸いです。 これを適切に修正するために私たちが行ったほど多くの時間を投資しないようにすることが誰かに役立つことを願っています。
改善が見られる場合は、提案してください。
よろしく。
あなたが以下が好きなら、何が起こりますか?
const TempImage = window.Image
const Image = function() {
const img = new TempImage()
img.crossOrigin = 'anonymous'
return img
}
解決策を見つけ、それは機能しています
html2canvasを呼び出している間、useCORStrueを渡します
html2canvas(selectorElement、 {useCORS:true} )。
//何かをする
});
html2canvas.jsファイルを修正してください。 タイプミスがあります
このifブロックで「anonymous」を「Anonymous」に変更します
if(isInlineBase64Image(src)|| useCORS){
img.crossOrigin = '匿名';
}
var canvasPromise = html2canvas(document.body, { allowTaint: true, useCORS: true }); canvasPromise.then(function(canvas) { document.body.appendChild(canvas); console.log(canvas); canvas.toDataURL('image/png'); });
バグレポート:
Uncaught(in promise)DOMException: 'HTMLCanvasElement'で 'toDataURL'を実行できませんでした:汚染されたキャンバスをエクスポートできない場合があります。
- テストされたhtml2canvasバージョン:
- Chrome 67.0.3396.99
- ウィンドウズ10
プロパティ 'useCORS:true'のみを使用する必要があります。プロパティ 'allowTaint:true'を使用する場合は、パーミッションを与えて、キャンバスを汚染されたキャンバスに変換します。
これを使って:
var canvasPromise = html2canvas(document.body, {
useCORS: true
});
canvasPromise.then(function(canvas) {
document.body.appendChild(canvas);
console.log(canvas);
canvas.toDataURL('image/png');
});
これの代わりに:
var canvasPromise = html2canvas(document.body, {
allowTaint: true,
useCORS: true
});
canvasPromise.then(function(canvas) {
document.body.appendChild(canvas);
console.log(canvas);
canvas.toDataURL('image/png');
});
こんにちは、html2canvasの素晴らしい仕事です。
悲しいことに、私は同じ問題に直面しています、誰かがこれを解決しましたか?
すでに@motarockとその前のすべてに加えて、組み合わせなどを試し
downloadQRCode = (fileName) => {
html2canvas(document.getElementById('generated-qr-code'), {
useCORS: true,
// allowTaint: false,
// logging: true,
}).then((canvas) => {
// document.body.appendChild(canvas); // checking
const data = canvas.toDataURL('image/jpeg');
const element = document.createElement('a');
element.setAttribute('href', data);
element.setAttribute('download', fileName + '.jpeg');
document.body.appendChild(element);
element.click();
// document.body.removeChild(element);
console.log("%c data", "font-size:2em;", data, fileName);
console.log("%c canvas", "font-size:2em;", canvas );
this.setState({
imageSrc: data // setting the src of a img tag to check the result. Nothing in it either..
})
});
前もって感謝します
私も同じ問題を抱えています。
誰でもこの問題を修正できますか?
:(同じ問題。ネストされたsvgを持つhtmlがあり、レンダリングされません
すでに@motarockとその前のすべてに加えて、組み合わせなどを試し
SSLを使用しない場合にこの問題が発生します。SSLを使用すると完全に機能します
最も参考になるコメント
私も同じ問題を抱えています。
解決策または回避策を見つけましたか?