我正在尝试为扩展传单 GridLayer api 的传单库实现浏览器光栅绘图插件。基本上,对于每个图块,都有一个函数 createTile
返回一个画布,上面有一些绘图。和传单显示了正确位置的瓷砖。
initialize: function(raster_data){
this.raster_data = raster_data;
},
createTile: function (tile_coords) {
let _tile = document.createElement('canvas');
let _tile_ctx = _tile.getContext('2d');
// do some drawing here with values from this.raster_data
return _tile;
}
这个实现到目前为止工作正常。比我想到在 webworker 中使用 offscreen-canvas 卸载绘图。所以我像这样重构了代码
initialize: function(raster_data){
this.raster_data = raster_data;
this.tile_worker = new Worker('tile_renderer.js')
},
createTile: function (tile_coords) {
let _tile = document.createElement('canvas').transferControlToOffscreen();
this.tile_worker.postMessage({
_tile: _tile,
_raster_data: this.raster_data
},[_tile])
return _tile;
}
这有效,但我时不时地看到一个空白的画布。那件事很随机,我不知道从哪里开始以及如何调试它。这可能是我使用单个工作人员渲染每个图块的问题吗?任何帮助表示赞赏。这是一个空白画布的示例。
答案 0 :(得分:1)
这是一个已知错误:https://crbug.com/1202481
当过多的 OffscreenCanvases 串行发送到 Worker 时会出现此问题。
解决方法是在对 postMessage()
的单个调用中批量发送所有这些 OffscreenCanvases。
在您的代码中,您可以通过存储所有要发送的对象并使用简单的去抖动策略(使用 0 超时)一次性发送所有对象来实现这一点:
createTile: function (tile_coords) {
let _tile = document.createElement('canvas');
_tile.setAttribute('width', 512);
_tile.setAttribute('height', 512);
let _off_tile = _tile.transferControlToOffscreen();
this.tiles_to_add.push( _off_tile ); // store for later
clearTimeout( this.batch_timeout_id ); // so that the callback is called only once
this.batch_timeout_id = setTimeout( () => {
// send them all at once
this.tileWorker.postMessage( { tiles: this.tiles_to_add }, this.tiles_to_add );
this.tiles_to_add.length = 0;
});
return _tile;
}