0

I am trying to implement a in browser raster drawing plugin for the leaflet library that that extends the leaflets GridLayer api. Essentially for every tile there is function createTile that returns a canvas with some drawing on it. and leaflet shows the tile in correct position.

    
    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;
    }

This implementation is so far working fine. Than I thought of offloading drawing with offscreen-canvas in a webworker. so I restructured the code like this

    
    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;
    }

This works but every now and then i see a canvas that is just blank. That thing is quite random I don't know start from where and how should I debug this. can this be a problem that I am using a single worker for rendering every tile? any help is appreciated. Here is an example of a blank canvas. example blank canvas

Nazmul Ahasan
  • 34
  • 1
  • 8
  • Could you try to make a [MCVE]? That sounds **very much** like https://crbug.com/1202481 Maybe you could try to batch all the calls to your Worker in a single message since apparently this avoids the aforementioned issue. – Kaiido May 10 '21 at 07:23
  • here is an [example](https://drive.google.com/file/d/1Cp8fFxXXsYiduxv_oeby8eQvNV-sPG_m/view?usp=sharing) if you zoom in and out eventually you will get one. @Kaiido – Nazmul Ahasan May 10 '21 at 08:16
  • So that's it, you could workaround that by storing all your offscreen canvases in an Array, and batching the postMessage in one go using a simple setTimeout(fn, 0) throttler. https://artistic-quill-tote.glitch.me/ and https://glitch.com/edit/#!/artistic-quill-tote But I should note that if all you do with these canvases is to set noise, it would probably be a lot more performant to create a single noise image, and use it as a tileLayer (though I know almost nothing about leaflet): https://longing-humble-rainbow.glitch.me/ and https://glitch.com/edit/#!/longing-humble-rainbow – Kaiido May 10 '21 at 09:12
  • As for this Q/A I hope the Chrome bug will get fixed soone enough, and I'm not sure how useful an answer would be... – Kaiido May 10 '21 at 09:13
  • creating noise was just for the example, main purpose is to render raster grids based on values similar to the image in the question. BTW thank you, I was pulling my hair on this wondering what I am doing wrong. – Nazmul Ahasan May 10 '21 at 09:25
  • the solution is simple and this solves my issue, may be you can post this as answer @Kaiido – Nazmul Ahasan May 10 '21 at 09:27

1 Answers1

1

This a known bug: https://crbug.com/1202481

The issue appears when too many OffscreenCanvases are sent to the Worker serially.

The workaround is then to batch send all these OffscreenCanvases in a single call to postMessage().
In your code you could achieve this by storing all the objects to be sent and use a simple debouncing strategy using a 0 timeout to send them all at once:

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;

}

Live example: https://artistic-quill-tote.glitch.me/

Kaiido
  • 123,334
  • 13
  • 219
  • 285