Skip to content

Conversation

mourner
Copy link
Member

@mourner mourner commented Jun 27, 2013

Implements #1798. Suppose you have a tile layer with maxZoom 18, but you need it up to 20 and OK with scaling of tiles. Then you would do this:

var tiles = L.tileLayer(..., {
    maxZoom: 20,
    maxNativeZoom: 18
});

Tested and seems to work well for both simple tile layers and WMS layers.

@mourner
Copy link
Member Author

mourner commented Jun 27, 2013

@tmcw @jfirebaugh thoughts on the API?

@jfirebaugh
Copy link
Member

I've been calling this "overscaling" -- if that's a legitimate term, maybe use it in one of the option names?

@mourner
Copy link
Member Author

mourner commented Jun 27, 2013

@jfirebaugh The trick is that we want to retain the semantics of maxZoom — it defines on what max zoom level you will still see the tile layer, we just need one more option to define after what level tiles start to be scaled. What would be a better name for it? overscaleAfterZoom?

@DrYSG
Copy link

DrYSG commented Jun 28, 2013

"overscaling", well I always have been fascinating by techniques that magically pull more information out an image than you would think. For example, sub-pixel imaging, pan-sharpening, and now we have compressive sensing with their 1-pixel cameras!

@DrYSG
Copy link

DrYSG commented Jun 28, 2013

Any idea how I would merge this into the FunctionalTileLayer leaflet plug-in https://github.com/ismyrnow/Leaflet.functionaltilelayer by Ishmael Schmorrow?

His initialize uses L.Util.setOptions() so I am hoping that will work:

    initialize: function (tileFunction, options) {
        this._tileFunction = tileFunction;
        L.Util.setOptions(this, options);
    },


L.tileLayer.functional = function (tileFunction, options) {
    return new L.TileLayer.Functional(tileFunction, options);
};

@DrYSG
Copy link

DrYSG commented Jun 28, 2013

His ( @ismyrnow ) code is short, let me post it instead of you having to find it:

L.TileLayer.Functional = L.TileLayer.extend({

    _tileFunction: null,

    initialize: function (tileFunction, options) {
        this._tileFunction = tileFunction;
        L.Util.setOptions(this, options);
    },

    getTileUrl: function (tilePoint) {
        // Note: bbox code untested; pulled from TileLayer.WMS
        var map = this._map,
            crs = map.options.crs,
            tileSize = this.options.tileSize,
            zoom = this._map.getZoom(),
            nwPoint = tilePoint.multiplyBy(tileSize),
            sePoint = nwPoint.add(new L.Point(tileSize, tileSize)),
            nw = crs.project(map.unproject(nwPoint, zoom)),
            se = crs.project(map.unproject(sePoint, zoom)),
            bbox = [nw.x, se.y, se.x, nw.y].join(','),
            view = {
                bbox: bbox,
                width: tileSize,
                height: tileSize,
                zoom: zoom,
                tile: {
                    row: tilePoint.y,
                    column: tilePoint.x
                },
                subdomain: this._getSubdomain(tilePoint)
            };

        return this._tileFunction(view);
    },

    _loadTile: function (tile, tilePoint) {
        var tileUrl = this.getTileUrl(tilePoint);

        tile._layer = this;
        tile.onload = this._tileOnLoad;
        tile.onerror = this._tileOnError;

        if (typeof tileUrl === "string") {
            tile.src = tileUrl;
        } else if (tileUrl) {
            // assume jQuery.Deferred
            tileUrl.done(function (tileUrl) {
                tile.src = tileUrl;
            });
        }
    }
});

L.tileLayer.functional = function (tileFunction, options) {
    return new L.TileLayer.Functional(tileFunction, options);
};

@ismyrnow
Copy link
Contributor

You should (theoretically) be able to add in those new settings when you initialize the functional tile layer. Since the plugin extends the existing L.TileLayer, it should apply any native settings to the underlying layer.

I don't know how L.TileLayer does the scaling under the hood, but it may work, since the only function I'm overriding is getTileUrl().

@mourner
Copy link
Member Author

mourner commented Jul 2, 2013

It should work, as this pull doesn't affect getTileUrl. What it essentially does is making tileSize dynamic, changing it when it goes beyond max native zoom but getting urls for tiles as if they were loaded on max native zoom.

@mourner
Copy link
Member Author

mourner commented Jul 2, 2013

OK, merging the pull.

mourner added a commit that referenced this pull request Jul 2, 2013
TileLayer maxNativeZoom option for scaling tiles on unsupported zoom levels
@mourner mourner merged commit 8f2dc24 into master Jul 2, 2013
@mourner mourner deleted the scaledtiles branch July 2, 2013 09:32
@TwistaTim
Copy link

Hey mourner, I have found an issue when you zoom to the Maxnative zoom level and then add another maxnativezoom enabled layer it will not load the maxzoom level tiles and scale them up to the current level zoom.

mourner added a commit that referenced this pull request Jul 10, 2013
This reverts commit 8f2dc24, reversing
changes made to 71e851f.
@DrYSG
Copy link

DrYSG commented Jul 29, 2013

I was very pleased with this fix, and it worked fine for tiles that I have in the local file system. But when I tried the same code for my variant of @ismyrnow FunctionalTiles (where the tiles are stored in an IDB), then it is ignoring the scaling beyond the naturalZoom. I.e. it just shows gray tiles. I am not seeing errors so I am not sure what is going on.

In case I am doing something obviously stupid, I am attaching snaphots of the state of the TileLayer just after it is created (Chrome). First for the simple case (local files) and then for the Functional Tile extension.

It is going to take me few days to create a CodePen to show the issue.

croppercapture 1

Here is what it looks like as a functional tile layer, realize that the tiles are all fetched with the _tileFunction(), so it is the options that are things to look at.

croppercapture 2

ismyrnow added a commit to ismyrnow/Leaflet.functionaltilelayer that referenced this pull request Nov 5, 2013
@nothingisnecessary
Copy link

Sorry if off-topic, but seems related: Is there a 'tweening' option for tile services that do not provide tiles at each zoom level? (Perhaps using the scaling that is visible when animating the zoom). (For example, on offline mobile devices with local tile servers where space is at a premium and may only store tiles at every other zoom level). See related SO question: http://stackoverflow.com/questions/28904160/how-to-use-chunky-coarse-grained-zoom-levels-with-leaflet-maps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants