努力将 SVG 绘制到网络工作者的屏幕外画布上

问题描述 投票:0回答:1

我从零经验的网络工作者到现在工作的时间比我愿意承认的要长,这让我失败了。

我想将一个长任务

canvas.toBlob(/* jpeg stuff */)
移至工作人员,但向工作人员发送 SVG,将其绘制到屏幕外画布上,然后转换为 JPEG 并将其发送回主线程。

这是我的代码:

self.onmessage = async event => {
    const { imageSVG, width, height } = event.data;

    try {
        // Set up the offscreen canvas
        const offscreen = new OffscreenCanvas(width, height);
        const ctx = offscreen.getContext('2d');
        
        // Create the image and draw to canvas
        const imageSrc = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(imageSVG)))}`;

        const imgBlob = await fetch(imageSrc)
            .then(response => response.blob());

        const img = await createImageBitmap(imgBlob);

        ctx.drawImage(img, 0, 0, width, height);

        offscreen.convertToBlob({
            type: 'image/jpeg',
            quality: 1.0
        }).then(blob => {
            postMessage({ blob: blob });
        });
    }
    catch(error) {
        postMessage(`Error: ${error}`);
    }
};

我无法克服的错误是

InvalidStateError: The source image could not be decoded.
,我在网上找不到太多关于它的含义的信息。

我确实遇到过一条 github 评论,现在丢失了一百万个关闭的选项卡,建议将数据 URI 包装在 SVGImageElement 中,但我不知道这意味着什么,而且他们没有详细说明。

javascript svg canvas web-worker
1个回答
0
投票

虽然规范目前表示应该支持这一点,但没有浏览器实现从

Blob
以及在
Worker
中对 SVG 进行解码,而且他们也不打算这样做。我什至写了一个 PR,以便将其从规范中删除。 他们不想这样做的原因是他们需要将所有 DOM 路径公开给工作人员,而目前工作人员不需要它。 至于解决方法,您必须通过

<img>

:

 从 UI 上下文中解码图像
if (blob.type === "image/svg+xml") { const img = new Image(); img.src = URL.createObjectURL(blob); await img.decode(); URL.revokeObjectURL(img.src); bmp = await createImageBitmap(img); worker.postMessage(bmp, [bmp]); }

可能会注意到,
大部分

的工作应该在另一个线程上完成,并且不应该阻塞您的UI,但为了100%安全,您可以使用跨源隔离的<iframe>,它将在另一个线程上运行线程,尽管设置要复杂得多。

    

© www.soinside.com 2019 - 2024. All rights reserved.