屏幕外画布有时不渲染

时间:2021-05-10 07:13:32

标签: javascript canvas leaflet web-worker offscreen-canvas

我正在尝试为扩展传单 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;
    }

这有效,但我时不时地看到一个空白的画布。那件事很随机,我不知道从哪里开始以及如何调试它。这可能是我使用单个工作人员渲染每个图块的问题吗?任何帮助表示赞赏。这是一个空白画布的示例。 example blank canvas

1 个答案:

答案 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;

}

现场示例:https://artistic-quill-tote.glitch.me/

相关问题