-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow custom done callback for RasterTileSource.loadTile #3123
Comments
@timiyay thanks for raising this. Ergonomic extensibility of I'm thinking that a possible variation to your proposal might be to extend the Then a slightly reworked version of these lines would essentially be the default implementation of loadTileImage. Once this was in place, then implementing a custom raster source could look like: var RasterSource = require('mapbox-gl/js/source/raster_source')
function MyRasterSource (id, options, dispatcher) {
var rasterSource = new RasterSource(id, options, dispatcher, myLoadTileImage);
// delegate Source interface methods to the RasterSource instance:
this.loadTile = rasterSource.loadTile.bind(rasterSource);
this.reloadTile = rasterSource.reloadTile.bind(rasterSource);
this.unloadTile = rasterSource.unloadTile.bind(rasterSource);
this.abortTile = rasterSource.abortTile.bind(rasterSource);
this.serialize = function () {
return Object.assign(rasterSource.serialize(), { type: 'my-source-type' })
}
}
function myLoadTileImage (coord, callback) { /* do custom stuff */ } |
^ cc @lucaswoj |
@anandthakker Yes this sounds like it'd work for my use case. It seems like my issue is related to this PR (#2918), in the sense that we need to customise the way a given Perhaps there's scope to add a couple of hooks into the design of As you say, a reworked version of the AJAX request line (https://github.com/mapbox/mapbox-gl-js/blob/master/js/source/raster_tile_source.js#L45-L47) would achieve this. From what I've seen in other issues, my minimal spec would be:
|
The intent behind using composition to create custom source types from core source types is that custom implementations can be supplied for any method. What would it look like to accommodate this use case by writing a custom implementation for var RasterSource = require('mapbox-gl/js/source/raster_source')
function MyRasterSource (id, options, dispatcher) {
var rasterSource = new RasterSource(id, options, dispatcher);
// delegate Source interface methods to the RasterSource instance:
this.loadTile = function(tile, callback) {
...
}
this.reloadTile = rasterSource.reloadTile.bind(rasterSource);
this.unloadTile = rasterSource.unloadTile.bind(rasterSource);
this.abortTile = rasterSource.abortTile.bind(rasterSource);
this.serialize = function () {
return Object.assign(rasterSource.serialize(), { type: 'my-source-type' })
}
} |
@lucaswoj I think the present difficulty with this approach is that @timiyay's use case involves providing a custom implementation for 1), but not for 2). Supporting this requires some way of separating the two. One way to do this is to accept a custom implementation for 1) as an optional constructor parameter -- that's what I proposed above, and is consistent with how VectorTileSource currently works. But, @lucaswoj, it seems like you're not quite sold on that... |
@lucaswoj, as @anandthakker describes, the issue is that Let's call these actions:
Here's how they break down in the code: loadTile: function(tile, callback) {
// Part 1: sendRequest
var url = normalizeURL(tile.coord.url(this.tiles, null, this.scheme), this.url, this.tileSize);
tile.request = ajax.getImage(url, done.bind(this));
function done(err, img) {
// Part 2: handleResponse
// This is the part I want to customise, so that I can apply custom rules
// to decide whether a WMS raster tile should be considered 404 Not Found or aborted,
// based on the unchangeable constraints of the source WMS server.
delete tile.request;
if (tile.aborted)
return;
if (err) {
return callback(err);
}
// Part 3: setUpGLTextures
// I'm a GL n00b, so this is all voodoo to me. I'd like to have a composable chain
// of functions that ends up with me handing a result to this GL-setup code, and not
// having to know anything about it
var gl = this.map.painter.gl;
tile.texture = this.map.painter.getTexture(img.width);
if (tile.texture) {
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, gl.RGBA, gl.UNSIGNED_BYTE, img);
} else {
tile.texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
tile.texture.size = img.width;
}
gl.generateMipmap(gl.TEXTURE_2D);
this.map.animationLoop.set(this.map.style.rasterFadeDuration);
tile.state = 'loaded';
callback(null);
}
}, The composability shown in #3123 (comment) - overriding Beyond my use case, I noted that another PR (#2918) has asked for similar extensibility in the |
I'm spending some of my downtime looking at this, attempting to find a graceful way to add this change to the I see that |
My ideal architecture would factor the
|
|
Giggity, thanks for the tip. I'll get a PR together by the end of the weekend. Update: PR is delayed, as I've been dragged down a JS modules / browserify rabbit-hole. I want to be able to import In this case, however, I'm hitting issues when:
For each web worker, I'm getting a console error saying The Once I solve this issue of being able to import a file from |
Merging this into #3186 |
I have a use case that requires me to make a custom
SourceType
, for which I was hoping to inherit fromRasterTileSource
.I'm integrating an external WMS into our
mapbox-gl-js
project, as they provide high-quality aerial imagery for my area of interest.The issue is that the WMS will always return a
200
. When tiles are missing for high zoom levels, the WMS return a200
and a blank white tile.I need a custom
SourceType
so that I can programatically-detect these blank tiles, and prevent them being rendered.I realise there are current issues and PRs looking at custom
SourceType
s. Nonetheless, for my use case, I would be greatly aided ifRasterTileSource.loadTile
was refactored into separate methods: https://github.com/mapbox/mapbox-gl-js/blob/master/js/source/raster_tile_source.js#L49If I was able to override the
done()
function and then, on success, pass myimg
object to a separate function that called the GL rendering code from line 59 (https://github.com/mapbox/mapbox-gl-js/blob/master/js/source/raster_tile_source.js#L59), then it'd be an easy switch.As it stands, I'll have to cut'n'paste all of code from
loadTile
into my own version of the function.Would there be any support for this change within the master
mapbox-gl-js
repo, or do you see this use case as being better-solved by existing/upcoming capabilities of customSourceType
s?I'm happy to whip up a PR, if there's support for this change.
The text was updated successfully, but these errors were encountered: