257 lines
8.3 KiB
JavaScript
257 lines
8.3 KiB
JavaScript
L.Control.ResetView = L.Control.extend({
|
|
statics: {
|
|
ICON: 'url(images/reset-view.png)',
|
|
TITLE: "Reset view"
|
|
},
|
|
|
|
options: {
|
|
position: 'topleft'
|
|
},
|
|
|
|
initialize: function (bounds, options) {
|
|
// Accept function as argument to bounds
|
|
this.getBounds = typeof(bounds) == 'function' ? bounds :
|
|
function () {
|
|
return bounds;
|
|
};
|
|
|
|
L.Util.setOptions(this, options);
|
|
},
|
|
|
|
onAdd: function (map) {
|
|
if (map.resetviewControl) {
|
|
map.removeControl(map.resetviewControl);
|
|
}
|
|
map.resetviewControl = this;
|
|
|
|
var container = L.DomUtil.create('div', 'leaflet-control-zoom leaflet-bar');
|
|
var link = L.DomUtil.create('a', 'leaflet-control-zoom-out leaflet-bar-part', container);
|
|
link.href = '#';
|
|
link.title = L.Control.ResetView.TITLE;
|
|
link.style.backgroundImage = L.Control.ResetView.ICON;
|
|
|
|
L.DomEvent.addListener(link, 'click', L.DomEvent.stopPropagation)
|
|
.addListener(link, 'click', L.DomEvent.preventDefault)
|
|
.addListener(link, 'click', L.Util.bind(function () {
|
|
map.fitBounds(this.getBounds());
|
|
}, this));
|
|
return container;
|
|
}
|
|
});
|
|
|
|
|
|
L.Map.DjangoMap = L.Map.extend({
|
|
|
|
initialize: function (id, options) {
|
|
// Merge compatible options
|
|
// (can be undefined)
|
|
var djoptions = options.djoptions;
|
|
options.zoom = djoptions.zoom;
|
|
options.center = djoptions.center;
|
|
|
|
if (!isNaN(parseInt(djoptions.minzoom, 10)))
|
|
options.minZoom = djoptions.minzoom;
|
|
|
|
if (!isNaN(parseInt(djoptions.maxzoom, 10)))
|
|
options.maxZoom = djoptions.maxzoom;
|
|
|
|
// Translate to native options
|
|
options = L.Util.extend(options,
|
|
this._projectionOptions(djoptions));
|
|
if (djoptions.extent) {
|
|
options.maxBounds = djoptions.extent;
|
|
}
|
|
|
|
L.Map.prototype.initialize.call(this, id, options);
|
|
|
|
this._djAddLayers();
|
|
this._djSetupControls();
|
|
|
|
if (djoptions.fitextent && djoptions.extent && !(djoptions.center || djoptions.zoom)) {
|
|
this.fitBounds(options.maxBounds);
|
|
}
|
|
},
|
|
|
|
_projectionOptions: function (djoptions) {
|
|
if (!djoptions.srid)
|
|
return {};
|
|
|
|
var projopts = {};
|
|
|
|
var bbox = djoptions.tilesextent,
|
|
maxResolution = computeMaxResolution(bbox);
|
|
// See https://github.com/ajashton/TileCache/blob/master/tilecache/TileCache/Layer.py#L197
|
|
var resolutions = [];
|
|
for (var z = 0; z < 20; z++) {
|
|
resolutions.push(maxResolution / Math.pow(2, z));
|
|
}
|
|
if (L.CRS['EPSG' + djoptions.srid] !== undefined) {
|
|
var crs = L.CRS['EPSG' + djoptions.srid];
|
|
} else {
|
|
var crs = new L.Proj.CRS('EPSG:' + djoptions.srid,
|
|
proj4.defs['EPSG:' + djoptions.srid],
|
|
{
|
|
origin: [bbox[0], bbox[3]],
|
|
resolutions: resolutions
|
|
}
|
|
);
|
|
}
|
|
return {
|
|
crs: crs,
|
|
scale: crs.scale,
|
|
continuousWorld: true
|
|
};
|
|
|
|
function computeMaxResolution(bbox) {
|
|
// See https://github.com/ajashton/TileCache/blob/master/tilecache/TileCache/Layer.py#L185-L196
|
|
var size = 256,
|
|
width = bbox[2] - bbox[0],
|
|
height = bbox[3] - bbox[1];
|
|
var aspect = Math.floor(Math.max(width, height) / Math.min(width, height) + 0.5);
|
|
return Math.max(width, height) / (size * aspect);
|
|
}
|
|
},
|
|
|
|
_djAddLayers: function () {
|
|
var layers = this.options.djoptions.layers;
|
|
var overlays = this.options.djoptions.overlays || [];
|
|
var continuousWorld = this.options.continuousWorld;
|
|
|
|
if (!layers || !layers.length) {
|
|
// No layers, we're done (ignoring overlays)
|
|
return;
|
|
}
|
|
|
|
if (layers.length == 1 && overlays.length == 0) {
|
|
var layer = l2d(layers[0]);
|
|
// Make the only layer match the map max/min_zoom
|
|
layer.options = L.Util.extend(layer.options, {
|
|
minZoom: this.options.minZoom,
|
|
maxZoom: this.options.maxZoom
|
|
});
|
|
L.tileLayer(layer.url, layer.options).addTo(this);
|
|
return;
|
|
}
|
|
|
|
this.layerscontrol = L.control.layers().addTo(this);
|
|
for (var i = 0, n = layers.length; i < n; i++) {
|
|
var layer = l2d(layers[i]),
|
|
l = L.tileLayer(layer.url, layer.options);
|
|
this.layerscontrol.addBaseLayer(l, layer.name);
|
|
// Show first one as default
|
|
if (i === 0) l.addTo(this);
|
|
}
|
|
for (var i = 0, n = overlays.length; i < n; i++) {
|
|
var layer = l2d(overlays[i]),
|
|
l = L.tileLayer(layer.url, layer.options);
|
|
this.layerscontrol.addOverlay(l, layer.name);
|
|
}
|
|
|
|
function l2d(l) {
|
|
var options = {'continuousWorld': continuousWorld};
|
|
if (typeof l[2] === 'string') {
|
|
// remain compatible with django-leaflet <= 0.15.0
|
|
options = L.Util.extend(options, {'attribution': l[2]});
|
|
} else {
|
|
options = L.Util.extend(options, l[2]);
|
|
}
|
|
return {name: l[0], url: l[1], options: options};
|
|
}
|
|
},
|
|
|
|
_djSetupControls: function () {
|
|
// Attribution prefix ?
|
|
if (this.attributionControl &&
|
|
this.options.djoptions.attributionprefix !== null) {
|
|
this.attributionControl.setPrefix(this.options.djoptions.attributionprefix);
|
|
}
|
|
|
|
// Scale control ?
|
|
if (this.options.djoptions.scale) {
|
|
this.whenReady(function () {
|
|
var scale_opt = this.options.djoptions.scale;
|
|
var show_imperial = /both|imperial/.test(scale_opt);
|
|
var show_metric = /both|metric/.test(scale_opt);
|
|
new L.Control.Scale({imperial: show_imperial, metric: show_metric}).addTo(this);
|
|
}, this);
|
|
}
|
|
|
|
// Minimap control ?
|
|
if (this.options.djoptions.minimap) {
|
|
for (var firstLayer in this._layers) break;
|
|
var url = this._layers[firstLayer]._url;
|
|
var layer = L.tileLayer(url);
|
|
this.minimapcontrol = null;
|
|
this.whenReady(function () {
|
|
this.minimapcontrol = new L.Control.MiniMap(layer,
|
|
{toggleDisplay: true}).addTo(this);
|
|
}, this);
|
|
}
|
|
|
|
// ResetView control ?
|
|
if (this.options.djoptions.resetview) {
|
|
var bounds = this.options.djoptions.extent;
|
|
if (bounds) {
|
|
// Add reset view control
|
|
this.whenReady(function () {
|
|
new L.Control.ResetView(bounds).addTo(this);
|
|
}, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
|
|
L.Map.djangoMap = function (id, options) {
|
|
var container = L.DomUtil.get(id);
|
|
if (container._leaflet) // Already initialized
|
|
return;
|
|
|
|
var map = new L.Map.DjangoMap(id, options);
|
|
|
|
if (options.globals) {
|
|
// Register document maps, like window.forms :)
|
|
window.maps = window.maps || [];
|
|
window.maps.push(map);
|
|
}
|
|
|
|
if (options.callback === null) {
|
|
/*
|
|
* Deprecate django-leaflet < 0.7 default callback
|
|
*/
|
|
var defaultcb = window[id + 'Init'];
|
|
if (typeof(defaultcb) == 'function') {
|
|
options.callback = defaultcb;
|
|
if (console) console.warn('DEPRECATED: Use of default callback ' + defaultcb.name + '() is deprecated (see documentation).');
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Trigger custom map:init Event
|
|
*/
|
|
triggerEvent(window, 'map:init', {id: id, map: map, options: options});
|
|
|
|
/*
|
|
* Run callback if specified
|
|
*/
|
|
if (typeof(options.callback) == 'function') {
|
|
options.callback(map, options);
|
|
}
|
|
|
|
return map;
|
|
|
|
|
|
function triggerEvent(target, type, data) {
|
|
if (typeof window.CustomEvent == 'function') {
|
|
var evt = new CustomEvent(type, {detail: data});
|
|
target.dispatchEvent(evt);
|
|
}
|
|
else if (window.jQuery) {
|
|
var evt = jQuery.Event(type);
|
|
evt.detail = data;
|
|
jQuery(target).trigger(evt);
|
|
}
|
|
}
|
|
};
|