
我正在使用 PanoJS 创建一个可以查看和修改巨大图像的平台。
我需要做的是用 canvas 渲染多个 图像切片,并且能改变图像的亮度,对比度,不透明度。
但问题是,当我运行这个 updateTiles 函数时,切片 没有被逐个更新,它们会等待所有的 tiles 被更新以后一起渲染,图像大了以后要卡住好几秒,一开始设置的 loading 透明度也在所有切片都更新以后才会生效。
希望有了解这方面的大神指点一下,多谢!
... PanoJS.prototype.updateTiles = function () { const handleCanvasUpdate = (element) => { const ctx = element.getContext('2d') const imgData = new ImageData(new Uint8ClampedArray(JSON.parse(element._imgData.data)), element._imgData.height, element._imgData.width) const changedImgData = this.changeImgData(imgData) // -1 ~ 1 ctx.putImageData(changedImgData, 0, 0); } const tag = this.showLoading('updateTiles') for (let i = 0; i < this.well.children.length; i++) { const element = this.well.children[i]; if (element.tagName.toUpperCase() === 'CANVAS') { handleCanvasUpdate(element) } } this.hideLoading(tag) } PanoJS.prototype.changeImgData = function (imgdata) { // this imgdata can be very large const data = imgdata.data; for (let i = 0; i < data.length; i += 4) { // brightness const hsv = this.rgb2hsv([data[i], data[i + 1], data[i + 2]]); hsv[2] *= 1 + this.luminance; const rgb = this.hsv2rgb([...hsv]); data[i] = rgb[0]; data[i + 1] = rgb[1]; data[i + 2] = rgb[2]; // contrast const _cOntrast= (this.contrast / 100) + 1; //convert to decimal & shift range: [0..2] const intercept = 128 * (1 - _contrast); data[i] = data[i] * _contrast + intercept; data[i + 1] = data[i + 1] * _contrast + intercept; data[i + 2] = data[i + 2] * _contrast + intercept; // opacity data[i + 3] = data[i + 3] * this.opacity; } return imgdata; } PanoJS.prototype.showLoading = function (name) { counter++ const tag = `${counter}${name}` console.time(tag) this.loadingMask.style.opacity = 1 this.loadingCount++ return tag } PanoJS.prototype.hideLoading = function (tag) { // requestAnimationFrame(() => { if (this.loadingCount) { this.loadingCount-- } // console.log(this.loadingMask.style.opacity); if (this.loadingCount === 0) { this.loadingMask.style.opacity = 0 } console.timeEnd(tag) // console.log(this.loadingCount); // }) } ... 1 tsanie 2022 年 6 月 10 日 用 setTimeout 吧,否则 UI 刷新要等到同步方法执行完成后才会触发。 !function (e) { setTimeout(() => handleCanvasUpdate(e), 0) }(element) |
2 MegrezZhu 2022 年 6 月 10 日 看能不能用 worker 把运算量放到后台线程去 |
3 thinkershare 2022 年 6 月 10 日 将所有重度运算移动到 Web Worker 中去, 不要再浏览器的主线程上做 CPU 重度操作. |
4 oldshensheep 2022 年 6 月 10 日 Web Workers 我这里有一个简单的图像处理程序,没有使用第三方处理图像的库,使用了 Web Workers 你可以参考一下。 https://blog.oldshensheep.com/toyweb/dip/ 这里是源码 https://github.com/oldshensheep/toyweb/tree/main/dip 之前我也是图片大了就卡住了,换成 Web Worker 就没事了。 其实如果有更高的需求建议使用 WebGL |
5 codehz 2022 年 6 月 11 日 (worker 里也可以跑 canvas ,transferControlToOffscreen 到 worker 之后就可以直接画了 |