first
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
L.MapboxGL = L.Layer.extend({
|
||||
options: {
|
||||
updateInterval: 32
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
L.setOptions(this, options);
|
||||
|
||||
if (options.accessToken) {
|
||||
mapboxgl.accessToken = options.accessToken;
|
||||
} else {
|
||||
throw new Error('You should provide a Mapbox GL access token as a token option.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a version of `fn` that only fires once every `time` millseconds.
|
||||
*
|
||||
* @param {Function} fn the function to be throttled
|
||||
* @param {number} time millseconds required between function calls
|
||||
* @param {*} context the value of `this` with which the function is called
|
||||
* @returns {Function} debounced function
|
||||
* @private
|
||||
*/
|
||||
var throttle = function (fn, time, context) {
|
||||
var lock, args, wrapperFn, later;
|
||||
|
||||
later = function () {
|
||||
// reset lock and call if queued
|
||||
lock = false;
|
||||
if (args) {
|
||||
wrapperFn.apply(context, args);
|
||||
args = false;
|
||||
}
|
||||
};
|
||||
|
||||
wrapperFn = function () {
|
||||
if (lock) {
|
||||
// called too soon, queue to call later
|
||||
args = arguments;
|
||||
|
||||
} else {
|
||||
// call and lock until later
|
||||
fn.apply(context, arguments);
|
||||
setTimeout(later, time);
|
||||
lock = true;
|
||||
}
|
||||
};
|
||||
|
||||
return wrapperFn;
|
||||
};
|
||||
|
||||
// setup throttling the update event when panning
|
||||
this._throttledUpdate = throttle(L.Util.bind(this._update, this), this.options.updateInterval);
|
||||
},
|
||||
|
||||
onAdd: function (map) {
|
||||
if (!this._glContainer) {
|
||||
this._initContainer();
|
||||
}
|
||||
|
||||
map._panes.tilePane.appendChild(this._glContainer);
|
||||
|
||||
this._initGL();
|
||||
|
||||
this._offset = this._map.containerPointToLayerPoint([0, 0]);
|
||||
|
||||
// work around https://github.com/mapbox/mapbox-gl-leaflet/issues/47
|
||||
if (map.options.zoomAnimation) {
|
||||
L.DomEvent.on(map._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this);
|
||||
}
|
||||
},
|
||||
|
||||
onRemove: function (map) {
|
||||
if (this._map.options.zoomAnimation) {
|
||||
L.DomEvent.off(this._map._proxy, L.DomUtil.TRANSITION_END, this._transitionEnd, this);
|
||||
}
|
||||
|
||||
map.getPanes().tilePane.removeChild(this._glContainer);
|
||||
this._glMap.remove();
|
||||
this._glMap = null;
|
||||
},
|
||||
|
||||
getEvents: function () {
|
||||
return {
|
||||
move: this._throttledUpdate, // sensibly throttle updating while panning
|
||||
zoomanim: this._animateZoom, // applys the zoom animation to the <canvas>
|
||||
zoom: this._pinchZoom, // animate every zoom event for smoother pinch-zooming
|
||||
zoomstart: this._zoomStart, // flag starting a zoom to disable panning
|
||||
zoomend: this._zoomEnd
|
||||
};
|
||||
},
|
||||
|
||||
_initContainer: function () {
|
||||
var container = this._glContainer = L.DomUtil.create('div', 'leaflet-gl-layer');
|
||||
|
||||
var size = this._map.getSize();
|
||||
container.style.width = size.x + 'px';
|
||||
container.style.height = size.y + 'px';
|
||||
},
|
||||
|
||||
_initGL: function () {
|
||||
var center = this._map.getCenter();
|
||||
|
||||
var options = L.extend({}, this.options, {
|
||||
container: this._glContainer,
|
||||
interactive: false,
|
||||
center: [center.lng, center.lat],
|
||||
zoom: this._map.getZoom() - 1,
|
||||
attributionControl: false
|
||||
});
|
||||
|
||||
this._glMap = new mapboxgl.Map(options);
|
||||
|
||||
// allow GL base map to pan beyond min/max latitudes
|
||||
this._glMap.transform.latRange = null;
|
||||
|
||||
// treat child <canvas> element like L.ImageOverlay
|
||||
L.DomUtil.addClass(this._glMap._canvas, 'leaflet-image-layer');
|
||||
L.DomUtil.addClass(this._glMap._canvas, 'leaflet-zoom-animated');
|
||||
},
|
||||
|
||||
_update: function (e) {
|
||||
// update the offset so we can correct for it later when we zoom
|
||||
this._offset = this._map.containerPointToLayerPoint([0, 0]);
|
||||
|
||||
if (this._zooming) {
|
||||
return;
|
||||
}
|
||||
|
||||
var size = this._map.getSize(),
|
||||
container = this._glContainer,
|
||||
gl = this._glMap,
|
||||
topLeft = this._map.containerPointToLayerPoint([0, 0]);
|
||||
|
||||
L.DomUtil.setPosition(container, topLeft);
|
||||
|
||||
var center = this._map.getCenter();
|
||||
|
||||
// gl.setView([center.lat, center.lng], this._map.getZoom() - 1, 0);
|
||||
// calling setView directly causes sync issues because it uses requestAnimFrame
|
||||
|
||||
var tr = gl.transform;
|
||||
tr.center = mapboxgl.LngLat.convert([center.lng, center.lat]);
|
||||
tr.zoom = this._map.getZoom() - 1;
|
||||
|
||||
if (gl.transform.width !== size.x || gl.transform.height !== size.y) {
|
||||
container.style.width = size.x + 'px';
|
||||
container.style.height = size.y + 'px';
|
||||
if (gl._resize !== null && gl._resize !== undefined){
|
||||
gl._resize();
|
||||
} else {
|
||||
gl.resize();
|
||||
}
|
||||
} else {
|
||||
gl._update();
|
||||
}
|
||||
},
|
||||
|
||||
// update the map constantly during a pinch zoom
|
||||
_pinchZoom: function (e) {
|
||||
this._glMap.jumpTo({
|
||||
zoom: this._map.getZoom() - 1,
|
||||
center: this._map.getCenter()
|
||||
});
|
||||
},
|
||||
|
||||
// borrowed from L.ImageOverlay https://github.com/Leaflet/Leaflet/blob/master/src/layer/ImageOverlay.js#L139-L144
|
||||
_animateZoom: function (e) {
|
||||
var scale = this._map.getZoomScale(e.zoom),
|
||||
offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), e.zoom, e.center);
|
||||
|
||||
L.DomUtil.setTransform(this._glMap._canvas, offset.subtract(this._offset), scale);
|
||||
},
|
||||
|
||||
_zoomStart: function (e) {
|
||||
this._zooming = true;
|
||||
},
|
||||
|
||||
_zoomEnd: function () {
|
||||
var scale = this._map.getZoomScale(this._map.getZoom()),
|
||||
offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), this._map.getZoom(), this._map.getCenter());
|
||||
|
||||
L.DomUtil.setTransform(this._glMap._canvas, offset.subtract(this._offset), scale);
|
||||
|
||||
this._zooming = false;
|
||||
},
|
||||
|
||||
_transitionEnd: function (e) {
|
||||
L.Util.requestAnimFrame(function () {
|
||||
var zoom = this._map.getZoom(),
|
||||
center = this._map.getCenter(),
|
||||
offset = this._map.latLngToContainerPoint(this._map.getBounds().getNorthWest());
|
||||
|
||||
// reset the scale and offset
|
||||
L.DomUtil.setTransform(this._glMap._canvas, offset, 1);
|
||||
|
||||
// enable panning once the gl map is ready again
|
||||
this._glMap.once('moveend', L.Util.bind(function () {
|
||||
this._zoomEnd();
|
||||
}, this));
|
||||
|
||||
// update the map position
|
||||
this._glMap.jumpTo({
|
||||
center: center,
|
||||
zoom: zoom - 1
|
||||
});
|
||||
}, this);
|
||||
}
|
||||
});
|
||||
|
||||
L.mapboxGL = function (options) {
|
||||
return new L.MapboxGL(options);
|
||||
};
|
||||
Reference in New Issue
Block a user