Загрязненный "OffscreenCanvas" не может быть экспортирован - PullRequest
2 голосов
/ 25 февраля 2020

Я передаю ImageBitmap в веб-рабочий, чтобы отобразить на холсте, а затем сгенерировать URL для загрузки в ТРИ. js в главном потоке.

в главном потоке

 this.canvas = this.canvasEl.transferControlToOffscreen() 
this.workerInstance.postMessage({canvas: this.canvas}, [this.canvas]);
...

createImageBitmap(this.img).then(imageData =>  {
        this.imageBitmap = imageData
        this.workerInstance.postMessage({image:imageData}, [imageData])

в рабочем

_ctx.drawImage(image, 0, 0)
    _canvas.convertToBlob({type: "image/png"}).then(blob => console.log(blob))

DOMException: Не удалось выполнить 'convertToBlob' для 'OffscreenCanvas': Tainted 'OffscreenCanvas "не может быть экспортировано.

Изображение в главном потоке имеет crossorigin="anonymous". На него также скопировано другое изображение, но это тот же домен.

Изображение создается динамически:

docString = '<svg width="' + this.width + '" height="' + this.height + '" xmlns="http://www.w3.org/2000/svg"><defs><style type="text/css"><![CDATA[a[href]{color:#0000EE;text-decoration:underline;}' + this.cssembed.join('') + ']]></style></defs><foreignObject x="0" y="0" width="' + this.width + '" height="' + this.height + '">' + parent[0] + docString + parent[1] + '</foreignObject></svg>';
this.img.src = "data:image/svg+xml;utf8," + encodeURIComponent(docString);

Код здесь https://github.com/supereggbert/aframe-htmlembed-component/blob/master/src/htmlcanvas.js

Я обновляю его для использования закадрового холста и веб-работники для быстрого рендеринга

1 Ответ

2 голосов
/ 25 февраля 2020

Это расширение этой известной ошибки , о которой я уже дал объяснение здесь .

Для вашего случая кажется, что даже используя "данные: URL hack-around"не будет работать, возможно, из-за некоторых других проверок, выполненных во внутренних шагах createImageBitmap.

Я добавлю комментарий об этом в отчете об ошибке, но на данный момент вы застряли с растеризацией этого svg изображения сначала на и используете это в качестве источника для ImageBitmap, который, я думаю, не совсем оптимален для вашего случая.

if( !window.OffscreenCanvasRenderingContext2D ) {
  console.warn("Your browser doesn't support the 2D context of the OffscreenCanvas API");
}

const worker = initWorker();

const data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
  '<foreignObject width="100%" height="100%">' +
  '<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
  '<em>I</em> like ' +
  '<span style="color:white; text-shadow:0 0 2px blue;">' +
  'beer</span>' +
  '</div>' +
  '</foreignObject>' +
'</svg>';
const img = new Image();
var url = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(data);

img.onload = function() {
  // create a new canvas just to rasterize that svg
  const canvas = document.createElement( 'canvas' );
  const ctx = canvas.getContext('2d');
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.drawImage(img, 0, 0);
  // use that canvas as the source for the ImageBitmap
  createImageBitmap(canvas).then(bmp => {
    worker.postMessage( bmp, [bmp] );
  });
};

img.src = url;

function initWorker() {
  const script = `
    let canvas, ctx;
    onmessage = e => {
      if(e.data instanceof ImageBitmap) {
        ctx.drawImage( e.data, 0, 0);
        canvas.convertToBlob().then( blob => {
          self.postMessage( blob );
        });
      }
      else {
        canvas = e.data;
        ctx = canvas.getContext('2d');
      }
    };
`
  const url = URL.createObjectURL(new Blob([script], { type: "application/javascript" }));
  const worker = new Worker(url);
  worker.onmessage = e => console.log('from worker', e.data);
  const offscreen = document.getElementById('canvas').transferControlToOffscreen();
  worker.postMessage(offscreen, [offscreen]);
  return worker;
}
<canvas id="canvas"></canvas>

Однако есть одна вещь, которая мне все еще совершенно не нравится в том, что вы должны получить ошибку еще до того, как она доберется до рабочий поток с указанием

Не удалось выполнить 'postMessage' для 'Worker': не может быть передано чистое ImageBitmap не из источника.

Я не знаю, как ваш Chrome обошел этот шаг ...

...