javascript - 生成 Canvas 元素卡住动画

标签 javascript html5-canvas tiff web-worker gsap

我正在使用第 3 方 Javascript 在所有浏览器中渲染 TIFF(只有 safari 本身支持它们) 该库的工作原理是将图像打印到 HTML 5 Canvas (不涉及 img 标签)

使用 Ajax,一旦图像可用, Canvas 渲染时就会出现明显的暂停。为了掩盖这一点,我放入了一个占位符图像,它是一个动画 gif。 除了这个动画 gif 之外,我还使用 greensock.js 和 css3 转换来使加载 gif 从 0 比例放大,一旦主图像准备好,在主图像出现之前缩小到 0 比例。

问题是动画总会有暂停的时刻(包括 greensock/css 驱动的动画和动画 gif)。

我认为我可以通过将导致它的任何内容移动到网络 worker 线程来解决这个问题。 然而,经过多次实验(通过单独删除部分代码,或者在无法在特定代码运行之前停止所有动画的情况下),我发现渲染 Canvas 的代码行是导致它的原因。

var canvas = tiff.toCanvas();

不幸的是,我无法将其移至 webworker,因为它是 DOM 操作。 我也无法在 webworker 上渲染图像/ Canvas 内容(本身不制作 Canvas 元素),然后将其从主线程粘贴到 Canvas 元素中,因为我使用的库不提供此类功能。

我能做的最好的事情就是将运行 AJAX 并接收图像的代码放在 webworker 中,然后将原始图像数据返回到主线程来完成其余的工作。

我尝试过一个提供虚拟 DOM 的 JS 库,但这只是导致了我从未深入了解的依赖 hell 。

最后,我决定让缩小动画在 Web Worker 返回包​​含图像的数据时立即发生,而不是在渲染完成后发生。这可以防止动画出现任何明显的暂停,但这意味着在加载图像消失后,在图像出现之前会出现暂停(在 Canvas 渲染时)。

我的代码如下。有什么想法可以解决这个问题吗?

主线程JS

var worker = new Worker('/javascript/task.js');
worker.addEventListener('message', function(e) {

TweenMax.to(placeHolderImage,0.5,{scale:0,     transformOrigin:"centre",onComplete:function(){
                document.getElementById("pic").removeChild(placeHolderImage);
                var tiff = new Tiff({buffer: e.data});
                var canvas = tiff.toCanvas();
                document.getElementById("pic").appendChild(canvas);
                canvas.className = "canvasReady";
                TweenMax.from(canvas,0.2,{rotationY:90,     transformOrigin:"left"})
            }}
        );

    }, false);

    //Call the worker and send the cover image URL to it.
    var src = /*[[${CoverImageURL}]]*/;
    worker.postMessage(src);
<小时/>

工作线程JS

self.addEventListener('message', function(e) {

importScripts("tiff.js-master/tiff.min.js");

var xhr = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('GET', e.data);
xhr.onload = function (e) {

    self.postMessage(xhr.response);
}

xhr.send();


}, false);

最佳答案

您是正确的,您无法通过网络工作人员操作该文档。您必须找到一种方法在 Web Worker 中完成大部分转换,然后仅将转换后的数据传递回主线程。

This demo来自tiff.js library似乎正在做你想做的事。 The worker it uses明确避免使用 tiff.toCanvas()。它们传递给工作人员的消息包括要使用的总内存以及图像的 URL。然后,他们使用 tiff.readRGBAImage() 来获取数据,并将信息发布回主线程以进行实际渲染。

另请注意工作线程中将数据传递回主线程的调用:

var image = tiff.readRGBAImage();
self.postMessage({ image: image, width: tiff.width(), height: tiff.height() }, [image]);

它将数组中的image 作为第二个参数传递,以利用数组对 Transferrable interface 的实现。 。长话短说,这意味着数据不会在工作线程和主线程之间复制。对于潜在的大型数据集(例如图像),传输数据而不是复制数据效率更高。

关于javascript - 生成 Canvas 元素卡住动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42790775/

相关文章:

javascript - 我正在尝试将 Facebook 推荐按钮添加到产品页面

Javascript - 纯js中的图表,移动点

.net - 如何使用Windows服务中的代码获取tiff文件中的页数

java - 在java中缩放多页TIFF图像

javascript - 如何将数据属性值传递给 map 函数之外的另一个函数?

javascript - “没有打开文档窗口”错误

javascript - 使用 FabricJS 的箭头形状

c++ - C/C++ LIBTIFF : Need to read pixel location of white and black pixels from BW TIFF files

javascript - 如何在 Angular Material 表中获取 <tr> 之间的间隙

design-patterns - 织物 JS 中对象缩放的模式重复