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

Major TileLayer + projections refactoring #2247

Merged
merged 35 commits into from Dec 2, 2013

Conversation

Projects
None yet
@mourner
Member

mourner commented Nov 27, 2013

This is a major refactoring of TileLayer code and everything that is related to projections.

The TileLayer part that splits it into GridLayer and TileLayer will make the code much cleaner and allow to build other tile-based implementations easier.

The long-standing projections refactoring will remove all corresponding ugly hacks across the code, consolidate everything projections-related into one place, make creating flat maps much easier, and also remove the need for ugly hacks in Proj4Leaflet plugin for different obscure projections.

GridLayer + TileLayer

  • split TileLayer into GridLayer (with all the grid / tile positioning logic) and its child TileLayer (with logic for loading image tiles from tile servers)
  • remove TileLayer.Anim.js, split animation logic between GridLayer and TileLayer
  • remove all Earth hardcode in Grid/TileLayer implementations, make everything work depending on CRS
  • remove TileLayer.Canvas in favor of a much more flexible and powerful GridLayer
  • fix bounding and wrapping in GridLayer to allow negative coordinate space
  • cover GridLayer with some tests

CRS & Projections

  • add Projection bounds property which determines projected coordinates bounds
  • add CRS properties: wrapLng, wrapLat (determining whether the world wraps and how) and infinite (if true, the layer will not be bounded, with negative tiles etc.)
  • add CRS getProjectedBounds that returns projected world bounds for zoom and corresponding Map getPixelWorldBounds, derived from Projection bounds, used for wrapping/bounding tiles
  • fix EPSG:4326 to have 2x1 tiles at zoom 0, #1207
  • fix Projection.SphericalMercator to project to meter units
  • add CRS unproject
  • remove LatLng wrap and add CRS and Map wrapLatLng that depends on CRS, fix #1618 again
  • remove MapDrag worldCopyJump hardcoded logic to work for other projections
  • update Proj4Leaflet to reflect all projection changes (remove lots of ugly hacks)
  • cover CRS with more tests

Misc. changes

  • improve L.bind to prepend real arguments to bound ones, and use native bind where available (was needed for a part of the code)

Before merge

  • cleanup history with interactive rebase on master
  • update changelog and document breaking changes
    #2210 #1180 #2239
@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 27, 2013

Member

Needs some history cleanup with interactive rebase, will do...

Member

mourner commented Nov 27, 2013

Needs some history cleanup with interactive rebase, will do...

@danzel

This comment has been minimized.

Show comment
Hide comment
@danzel

danzel Nov 27, 2013

Member

Have taken a read through. Seems good so far!

Member

danzel commented Nov 27, 2013

Have taken a read through. Seems good so far!

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 27, 2013

Member

@perliedman had to do some modifications to EPSG:4326 to make the WMS Marble example work and also fix #1207. Could you verify that please?

Member

mourner commented Nov 27, 2013

@perliedman had to do some modifications to EPSG:4326 to make the WMS Marble example work and also fix #1207. Could you verify that please?

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

@perliedman awesome. Could you look at what would be required for Proj4Leaflet to reflect those changes?

Member

mourner commented Nov 28, 2013

@perliedman awesome. Could you look at what would be required for Proj4Leaflet to reflect those changes?

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

@tmcw @jfirebaugh this is pretty much ready for review, only minor stuff left to do.

Member

mourner commented Nov 28, 2013

@tmcw @jfirebaugh this is pretty much ready for review, only minor stuff left to do.

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Nov 28, 2013

Member

@mourner I will try to find time in the next couple of days. Mostly removing stuff I guess.

Member

perliedman commented Nov 28, 2013

@mourner I will try to find time in the next couple of days. Mostly removing stuff I guess.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

@perliedman awesome!

Member

mourner commented Nov 28, 2013

@perliedman awesome!

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

Copying what I said in IRC:

Final issue for the projections refactoring is how LatLng wrapping should be done. We need to move this from LatLng wrap to CRS that determines how to wrap, but how to implement it there? Should we use CRS getSize and convert the given LatLng to pixels, wrap, and then convert back? Or should we convert Projection bounds to LatLngBounds in CRS and use that for wrapping?

Member

mourner commented Nov 28, 2013

Copying what I said in IRC:

Final issue for the projections refactoring is how LatLng wrapping should be done. We need to move this from LatLng wrap to CRS that determines how to wrap, but how to implement it there? Should we use CRS getSize and convert the given LatLng to pixels, wrap, and then convert back? Or should we convert Projection bounds to LatLngBounds in CRS and use that for wrapping?

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Nov 28, 2013

Member

The idea to move wrapping is to handle the flat/other world's scenario, right?

I think it depends on just how weird those other world's might be.

  1. If we assume they will be mostly like LatLng, but with other bounds, putting it in CRS and convert pixels would be sufficient
  2. If we think more esoteric coordinate systems, where wrapping around x/lng would affect y/lat, it should be done in Projection, which knows what wrapping means in this particular projection

I'm leaning against the first, in CRS. I don't know any actual use case that needs the second method.

Member

perliedman commented Nov 28, 2013

The idea to move wrapping is to handle the flat/other world's scenario, right?

I think it depends on just how weird those other world's might be.

  1. If we assume they will be mostly like LatLng, but with other bounds, putting it in CRS and convert pixels would be sufficient
  2. If we think more esoteric coordinate systems, where wrapping around x/lng would affect y/lat, it should be done in Projection, which knows what wrapping means in this particular projection

I'm leaning against the first, in CRS. I don't know any actual use case that needs the second method.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

@perliedman yeah, I agree that esoteric CRS which would have trouble with wrapping don't need it anyway, so I'm inclined to go with a simpler method. The only issue is that wrapping by unprojecting, wrapping and projecting again seems a bit complex, so I thought we could simplify that by wrapping LatLng directly using LatLng values derived from Projection bounds.

Member

mourner commented Nov 28, 2013

@perliedman yeah, I agree that esoteric CRS which would have trouble with wrapping don't need it anyway, so I'm inclined to go with a simpler method. The only issue is that wrapping by unprojecting, wrapping and projecting again seems a bit complex, so I thought we could simplify that by wrapping LatLng directly using LatLng values derived from Projection bounds.

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Nov 28, 2013

Member

Oh. Yes, that makes sense.

Member

perliedman commented Nov 28, 2013

Oh. Yes, that makes sense.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

OK, now the refactoring looks pretty good and feature-complete. The only thing left before merge is to cover all that goodness with more tests.

Member

mourner commented Nov 28, 2013

OK, now the refactoring looks pretty good and feature-complete. The only thing left before merge is to cover all that goodness with more tests.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

Cleaned up and rebased, can be cleanly merged into master now.

Member

mourner commented Nov 28, 2013

Cleaned up and rebased, can be cleanly merged into master now.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 28, 2013

Member

@sheppard @pthorin @leplatrem @calvinmetcalf @turban @moonlite guys, you're welcome to review this as well — let me know what you think.

Member

mourner commented Nov 28, 2013

@sheppard @pthorin @leplatrem @calvinmetcalf @turban @moonlite guys, you're welcome to review this as well — let me know what you think.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Nov 29, 2013

Member

All the projections stuff in Leaflet FINALLY makes complete sense to me after years of "I'll figure this out later" thinking. Big thanks to @perliedman (Proj4Leaflet maintainer) for all the help.

Member

mourner commented Nov 29, 2013

All the projections stuff in Leaflet FINALLY makes complete sense to me after years of "I'll figure this out later" thinking. Big thanks to @perliedman (Proj4Leaflet maintainer) for all the help.

@mourner mourner referenced this pull request Nov 29, 2013

Closed

Projections refactoring #2239

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Nov 29, 2013

Member

This will be a great improvement for anyone not using the already builtin projections. Also lots less to maintain in Proj4Leaflet :)

Happy that I could help!

Member

perliedman commented Nov 29, 2013

This will be a great improvement for anyone not using the already builtin projections. Also lots less to maintain in Proj4Leaflet :)

Happy that I could help!

@mattiasb

This comment has been minimized.

Show comment
Hide comment
@mattiasb

mattiasb Nov 30, 2013

Contributor

This looks great!
Had a quick look on the combined diff and I didn't find anything to comment on. Will hopefully have time for a longer review tomorrow (since you asked :)).

Great work!

Contributor

mattiasb commented Nov 30, 2013

This looks great!
Had a quick look on the combined diff and I didn't find anything to comment on. Will hopefully have time for a longer review tomorrow (since you asked :)).

Great work!

@leplatrem

This comment has been minimized.

Show comment
Hide comment
@leplatrem

leplatrem Nov 30, 2013

Contributor

I feel honored you asked me :)
Looks great! It will help greatly the integration of tiled vector data!

And I guess there is a chance it fixes an inexplicable bug we had on Proj4Leaflet kartena/Proj4Leaflet#37

Contributor

leplatrem commented Nov 30, 2013

I feel honored you asked me :)
Looks great! It will help greatly the integration of tiled vector data!

And I guess there is a chance it fixes an inexplicable bug we had on Proj4Leaflet kartena/Proj4Leaflet#37

@calvinmetcalf

This comment has been minimized.

Show comment
Hide comment
@calvinmetcalf

calvinmetcalf Nov 30, 2013

Contributor

This seems fantastic, still looking through the code, but so far, ❤️

Contributor

calvinmetcalf commented Nov 30, 2013

This seems fantastic, still looking through the code, but so far, ❤️

@turban

This comment has been minimized.

Show comment
Hide comment
@turban

turban Nov 30, 2013

Contributor

Looks promising! I would like to use Leaflet with a Lambert Azimuthal Equal Area Projection (image), but I'm having trouble when I use the fitBounds method for an area around the pole. Leaflet only accept bounds in LatLngs and not in projected coordinates. This still seems to be the case with this refactoring. Any plans to support projected coordinates for the fitBounds method, L.Rectangle etc.?

polar

Contributor

turban commented Nov 30, 2013

Looks promising! I would like to use Leaflet with a Lambert Azimuthal Equal Area Projection (image), but I'm having trouble when I use the fitBounds method for an area around the pole. Leaflet only accept bounds in LatLngs and not in projected coordinates. This still seems to be the case with this refactoring. Any plans to support projected coordinates for the fitBounds method, L.Rectangle etc.?

polar

@pthorin

This comment has been minimized.

Show comment
Hide comment
@pthorin

pthorin Dec 1, 2013

This looks really nice and really helpful for Proj4Leaflet. Well done!

pthorin commented Dec 1, 2013

This looks really nice and really helpful for Proj4Leaflet. Well done!

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Dec 2, 2013

Member

Thanks for the feedback guys! @turban yeah, it's not currently possible to pass projected coordinates to fitBounds and L.rectangle, and L.Circle (radius) but I agree that should be addressed next. With this PR in, I think we're in a much better position to do further improvements in this direction.

Member

mourner commented Dec 2, 2013

Thanks for the feedback guys! @turban yeah, it's not currently possible to pass projected coordinates to fitBounds and L.rectangle, and L.Circle (radius) but I agree that should be addressed next. With this PR in, I think we're in a much better position to do further improvements in this direction.

@mourner mourner merged commit 9cb36d0 into master Dec 2, 2013

@mourner mourner deleted the gridlayer2 branch Dec 2, 2013

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Dec 2, 2013

Member

Merged, yay! 🔨

Member

mourner commented Dec 2, 2013

Merged, yay! 🔨

@aparshin

This comment has been minimized.

Show comment
Hide comment
@aparshin

aparshin Dec 18, 2013

Contributor

I have few comments about TileLayer refactoring (sorry for delay):

  1. Great work! Looks much better then previous version! :)
  2. _tileReady function now can be called for tiles, that are already removed (for example, because of redraw method). As a result events loading and load are fired incorrectly.
  3. tileload/tileunload events are fired with tile as the only parameter. How can user find out what coordinates has loaded tile? Maybe it can be useful to add tile coordinates to event parameters?
  4. _addTile relays on number of formal parameter of createTile function (to distinguish synchronous/asynchronous tile loading). IMHO not very obvious behavior...

Have you considered possibility not to create DOM elements for some tiles (for example, allow createTile to return null)? Real live example is tile-based vector layers. It often happens that there are no data in some tiles. The possibility to remove these empty tiles from the DOM can significantly improve performance of map movements (at least in case of 100+ layers).

Contributor

aparshin commented Dec 18, 2013

I have few comments about TileLayer refactoring (sorry for delay):

  1. Great work! Looks much better then previous version! :)
  2. _tileReady function now can be called for tiles, that are already removed (for example, because of redraw method). As a result events loading and load are fired incorrectly.
  3. tileload/tileunload events are fired with tile as the only parameter. How can user find out what coordinates has loaded tile? Maybe it can be useful to add tile coordinates to event parameters?
  4. _addTile relays on number of formal parameter of createTile function (to distinguish synchronous/asynchronous tile loading). IMHO not very obvious behavior...

Have you considered possibility not to create DOM elements for some tiles (for example, allow createTile to return null)? Real live example is tile-based vector layers. It often happens that there are no data in some tiles. The possibility to remove these empty tiles from the DOM can significantly improve performance of map movements (at least in case of 100+ layers).

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Dec 20, 2013

Member
  1. Thanks for the feedback!
  2. Can you clarify this point? Not sure how that can happen.
  3. Yep, will probably add that.
  4. Maybe not obvious, but it makes the user-facing API simpler as you don't need to specify if the tile layer is async or not when creating it.
  5. Yeah, will consider this.
Member

mourner commented Dec 20, 2013

  1. Thanks for the feedback!
  2. Can you clarify this point? Not sure how that can happen.
  3. Yep, will probably add that.
  4. Maybe not obvious, but it makes the user-facing API simpler as you don't need to specify if the tile layer is async or not when creating it.
  5. Yeah, will consider this.
@aparshin

This comment has been minimized.

Show comment
Hide comment
@aparshin

aparshin Dec 21, 2013

Contributor

Here is a test case for "2": http://jsfiddle.net/dh76y/
If you zoom-in twice fast enough, _tilesToLoad will become negative. load and loading events are fired based on this variable... (By the way, can I find somewhere builded version of Leaflet.js from the master branch?)

Contributor

aparshin commented Dec 21, 2013

Here is a test case for "2": http://jsfiddle.net/dh76y/
If you zoom-in twice fast enough, _tilesToLoad will become negative. load and loading events are fired based on this variable... (By the way, can I find somewhere builded version of Leaflet.js from the master branch?)

@kermit-the-frog

This comment has been minimized.

Show comment
Hide comment
@kermit-the-frog

kermit-the-frog Jan 30, 2014

Shouldn't there be a check if _tileNumBounds is null? It is null if this._map.options.crs is true.

kermit-the-frog commented on src/layer/tile/TileLayer.js in 678a5cb Jan 30, 2014

Shouldn't there be a check if _tileNumBounds is null? It is null if this._map.options.crs is true.

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Jan 30, 2014

Member

But tms doesn't make sense if CRS has no bounds, right?

Member

mourner replied Jan 30, 2014

But tms doesn't make sense if CRS has no bounds, right?

This comment has been minimized.

Show comment
Hide comment
@kermit-the-frog

kermit-the-frog Jan 30, 2014

In my special situation it makes sense. I'm using my own special server that gives me a flat infinite map but the tile.y has to be mirrored. That's why I use tms=true and infinite=true

kermit-the-frog replied Jan 30, 2014

In my special situation it makes sense. I'm using my own special server that gives me a flat infinite map but the tile.y has to be mirrored. That's why I use tms=true and infinite=true

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Jan 30, 2014

Member

How exactly mirrored?

Member

mourner replied Jan 30, 2014

How exactly mirrored?

This comment has been minimized.

Show comment
Hide comment
@kermit-the-frog

kermit-the-frog Jan 30, 2014

I have to send -coords.y instead of coords.y.

kermit-the-frog replied Jan 30, 2014

I have to send -coords.y instead of coords.y.

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Jan 30, 2014

Member

I don't think this should be TMS. You can just pass y: function (data) { return -data.y; } option to TileLayer.

Member

mourner replied Jan 30, 2014

I don't think this should be TMS. You can just pass y: function (data) { return -data.y; } option to TileLayer.

This comment has been minimized.

Show comment
Hide comment
@kermit-the-frog

kermit-the-frog Jan 30, 2014

Like this?

var layer = L.tileLayer(url, {
...
y: function (data) {
return -data.y;
}
});

An why shouldn't I use tms = true. The only reference to this.options.tms in leaflet-src.js is this line. So I won't break anything. But tms = true breaks if there are no _tileNumBounds

kermit-the-frog replied Jan 30, 2014

Like this?

var layer = L.tileLayer(url, {
...
y: function (data) {
return -data.y;
}
});

An why shouldn't I use tms = true. The only reference to this.options.tms in leaflet-src.js is this line. So I won't break anything. But tms = true breaks if there are no _tileNumBounds

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner Jan 30, 2014

Member

Because TMS is a standard that has a bounding box by specification (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification), and your use case is not TMS, it's just a flipped coordinate.

Member

mourner replied Jan 30, 2014

Because TMS is a standard that has a bounding box by specification (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification), and your use case is not TMS, it's just a flipped coordinate.

This comment has been minimized.

Show comment
Hide comment
@kermit-the-frog

kermit-the-frog Jan 30, 2014

Oh, I see. I assumed it to be way to say use -y instead of y when requesting tiles. I didn't no that there is a standard behind it. I'm using leaflet in a non standardway, so I've to find another solution. Actually I started my development with reading http://build-failed.blogspot.de/2012/11/zoomable-image-with-leaflet.html, where tms=true is very important.

kermit-the-frog replied Jan 30, 2014

Oh, I see. I assumed it to be way to say use -y instead of y when requesting tiles. I didn't no that there is a standard behind it. I'm using leaflet in a non standardway, so I've to find another solution. Actually I started my development with reading http://build-failed.blogspot.de/2012/11/zoomable-image-with-leaflet.html, where tms=true is very important.

@dobrych

This comment has been minimized.

Show comment
Hide comment
@dobrych

dobrych Feb 20, 2014

@turban did you get your "Lambert Azimuthal Equal Area Projection" map working after all latest changes? starting same today, just curious about known issues…

dobrych commented Feb 20, 2014

@turban did you get your "Lambert Azimuthal Equal Area Projection" map working after all latest changes? starting same today, just curious about known issues…

@turban

This comment has been minimized.

Show comment
Hide comment
@turban

turban Feb 20, 2014

Contributor

@dobrych Using a polar projection with Leaflet is still difficult I think, because lack of support for projected coordinates. You're better off with D3.js or OpenLayers.

Contributor

turban commented Feb 20, 2014

@dobrych Using a polar projection with Leaflet is still difficult I think, because lack of support for projected coordinates. You're better off with D3.js or OpenLayers.

@dobrych

This comment has been minimized.

Show comment
Hide comment
@dobrych

dobrych Feb 20, 2014

@turban thanks for confirmation, you saved me some time :-) already started D3 version in parallel, will see if tile layer of d3 will work properly with polar projection

dobrych commented Feb 20, 2014

@turban thanks for confirmation, you saved me some time :-) already started D3 version in parallel, will see if tile layer of d3 will work properly with polar projection

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Feb 20, 2014

Member

I'm interested in what issues you're seeing, feel free to report and problems to Proj4Leaflet (which I would assume you would want to use in this case).

There is a branch to be used together with the new projection/CRS changes in Leaflet master: https://github.com/kartena/Proj4Leaflet/tree/leaflet-proj-refactor

Member

perliedman commented Feb 20, 2014

I'm interested in what issues you're seeing, feel free to report and problems to Proj4Leaflet (which I would assume you would want to use in this case).

There is a branch to be used together with the new projection/CRS changes in Leaflet master: https://github.com/kartena/Proj4Leaflet/tree/leaflet-proj-refactor

@turban

This comment has been minimized.

Show comment
Hide comment
@turban

turban Feb 21, 2014

Contributor

@perliedman Proj4Leaflet works good with cylindrical (pseudo)cylindrical projections, I'm using it for various maps in UTM and Mollweide projections. The problem araise with a projection where you need to operate in projected coordinates, not only geographical (latitude and longitude). If you have a polar projection like the one shown one the screenshot above, and want to use fitBounds to set the map view with the North Pole in the middle - it's not possible with the current fitBounds method. There are also issues with L.rectangle and L.Circle. Would be nice if you add a fix for this in Proj4Leaflet :-)

Contributor

turban commented Feb 21, 2014

@perliedman Proj4Leaflet works good with cylindrical (pseudo)cylindrical projections, I'm using it for various maps in UTM and Mollweide projections. The problem araise with a projection where you need to operate in projected coordinates, not only geographical (latitude and longitude). If you have a polar projection like the one shown one the screenshot above, and want to use fitBounds to set the map view with the North Pole in the middle - it's not possible with the current fitBounds method. There are also issues with L.rectangle and L.Circle. Would be nice if you add a fix for this in Proj4Leaflet :-)

@perliedman

This comment has been minimized.

Show comment
Hide comment
@perliedman

perliedman Feb 22, 2014

Member

Sorry that I didn't read your previous comment.

If I understand correctly, the problem is not showing the tiles and not that there are actual bugs related to polar projections, but rather that the API isn't very useful in this use case, since for example bounds in the form of latitudes and longitudes does not make much sense, right? I can definitely see that it would be a problem.

I'll try to think of if there's anything we can do in Proj4Leaflet to help this!

Member

perliedman commented Feb 22, 2014

Sorry that I didn't read your previous comment.

If I understand correctly, the problem is not showing the tiles and not that there are actual bugs related to polar projections, but rather that the API isn't very useful in this use case, since for example bounds in the form of latitudes and longitudes does not make much sense, right? I can definitely see that it would be a problem.

I'll try to think of if there's anything we can do in Proj4Leaflet to help this!

@turban

This comment has been minimized.

Show comment
Hide comment
@turban

turban Feb 22, 2014

Contributor

True, the problem is not showing the tiles, but setting the view and drawing vectors on top when latitude and longitudes don't make sense.

Contributor

turban commented Feb 22, 2014

True, the problem is not showing the tiles, but setting the view and drawing vectors on top when latitude and longitudes don't make sense.

@atombender

This comment has been minimized.

Show comment
Hide comment
@atombender

atombender May 6, 2014

What is the intended replacement for TileLayer.Canvas, which has been removed entirely? That class provided very useful functionality. I don't see any other class that fits the same purpose, and I'd rather not implement my own GridLayer descendant.

atombender commented May 6, 2014

What is the intended replacement for TileLayer.Canvas, which has been removed entirely? That class provided very useful functionality. I don't see any other class that fits the same purpose, and I'd rather not implement my own GridLayer descendant.

@mourner

This comment has been minimized.

Show comment
Hide comment
@mourner

mourner May 6, 2014

Member

@atombender check out the debug/map/canvas.html example. It's almost the same code-wise but uses GridLayer instead of TileLayer.Canvas. It's much more flexible and as easy to use.

Member

mourner commented May 6, 2014

@atombender check out the debug/map/canvas.html example. It's almost the same code-wise but uses GridLayer instead of TileLayer.Canvas. It's much more flexible and as easy to use.

@atombender

This comment has been minimized.

Show comment
Hide comment
@atombender

atombender May 6, 2014

@mourner That's perfect, thank you.

atombender commented May 6, 2014

@mourner That's perfect, thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment