-
-
Save rclark/2017109 to your computer and use it in GitHub Desktop.
Leaflet Bing layer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
L.TileLayer.Bing = L.TileLayer.extend({ | |
supportedTypes: ['Road', 'Aerial', 'AerialWithLabels'], | |
attributionTemplate: '<span style="display:inline-block">' + | |
'<a target="_blank" href="http://www.bing.com/maps/">' + | |
'<img src="{logo}" /></a><br><span>{copyrights}' + | |
'<a style="white-space: nowrap" target="_blank" '+ | |
'href="http://www.microsoft.com/maps/product/terms.html">' + | |
'Terms of Use</a></span></span>', | |
initialize: function(/*String*/ apiKey, /*String*/ mapType, /*Object*/ options) { | |
this._apiKey = apiKey; | |
this._mapType = mapType; | |
this._loadMetadata(); | |
L.Util.setOptions(this, options); | |
}, | |
_loadMetadata: function() { | |
this._callbackId = "_l_tilelayer_bing_" + (L.TileLayer.Bing._callbackId++); | |
//window[this._callbackId] = L.Util.bind(L.TileLayer.Bing.processMetadata, this); | |
that = this; | |
window[this._callbackId] = function() { L.TileLayer.Bing.processMetadata.apply(that, arguments); } | |
var params = { | |
key: this._apiKey, | |
jsonp: this._callbackId, | |
include: 'ImageryProviders' | |
}, | |
url = "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/" + | |
this._mapType + L.Util.getParamString(params), | |
script = document.createElement("script"); | |
script.type = "text/javascript"; | |
script.src = url; | |
script.id = this._callbackId; | |
document.getElementsByTagName("head")[0].appendChild(script); | |
}, | |
_onMetadataLoaded: function() {}, | |
onAdd: function(map, insertAtTheBottom) { | |
if (!this.metadata) { | |
this._onMetadataLoaded = L.Util.bind(function() { | |
L.TileLayer.prototype.onAdd.call(this, map, insertAtTheBottom); | |
map.on('moveend', this._updateAttribution, this); | |
this._updateAttribution(); | |
}, this); | |
} else { | |
L.TileLayer.prototype.onAdd.call(this, map, insertAtTheBottom); | |
map.on('moveend', this._updateAttribution, this); | |
this._updateAttribution(); | |
} | |
}, | |
onRemove: function(map) { | |
if (this._map.attributionControl) { | |
this._map.attributionControl.removeAttribution(this.attribution); | |
} | |
this._map.off('moveend', this._updateAttribution, this); | |
L.TileLayer.prototype.onRemove.call(this, map); | |
}, | |
getTileUrl: function(xy, z) { | |
var subdomains = this.options.subdomains, | |
quadDigits = [], | |
i = z, | |
digit, | |
mask, | |
quadKey; | |
// borrowed directly from OpenLayers | |
for (; i > 0; --i) { | |
digit = '0'; | |
mask = 1 << (i - 1); | |
if ((xy.x & mask) != 0) { | |
digit++; | |
} | |
if ((xy.y & mask) != 0) { | |
digit++; | |
digit++; | |
} | |
quadDigits.push(digit); | |
} | |
return this._url | |
.replace('{subdomain}', subdomains[(xy.x + xy.y) % subdomains.length]) | |
.replace('{quadkey}', quadDigits.join("")); | |
}, | |
_updateAttribution: function() { | |
if (this._map.attributionControl) { | |
var metadata = this.metadata; | |
var res = metadata.resourceSets[0].resources[0]; | |
var bounds = this._map.getBounds(); | |
var providers = res.imageryProviders, zoom = this._map.getZoom() + 1, | |
copyrights = "", provider, i, ii, j, jj, bbox, coverage; | |
for (i=0,ii=providers.length; i<ii; ++i) { | |
provider = providers[i]; | |
for (j=0,jj=provider.coverageAreas.length; j<jj; ++j) { | |
coverage = provider.coverageAreas[j]; | |
if (zoom <= coverage.zoomMax && zoom >= coverage.zoomMin && coverage.bbox.intersects(bounds)) { | |
copyrights += provider.attribution + " "; | |
j = jj; | |
} | |
} | |
} | |
this._map.attributionControl.removeAttribution(this.attribution); | |
this.attribution = this.attributionTemplate | |
.replace('{logo}', metadata.brandLogoUri) | |
.replace('{copyrights}', copyrights); | |
this._map.attributionControl.addAttribution(this.attribution); | |
} | |
} | |
}); | |
L.TileLayer.Bing._callbackId = 0; | |
L.TileLayer.Bing.processMetadata = function(metadata) { | |
if (metadata.authenticationResultCode != 'ValidCredentials') { | |
throw "Invalid Bing Maps API Key" | |
} | |
if (!metadata.resourceSets.length || !metadata.resourceSets[0].resources.length) { | |
throw "No resources returned, perhaps " + this._mapType + " is an invalid map type?"; | |
} | |
if (metadata.statusCode != 200) { | |
throw "Bing Maps API request failed with status code " + metadata.statusCode; | |
} | |
this.metadata = metadata; | |
var res = metadata.resourceSets[0].resources[0], | |
providers = res.imageryProviders, | |
i = 0, | |
j, | |
provider, | |
bbox, | |
script = document.getElementById(this._callbackId); | |
for (; i<providers.length; i++) { | |
provider = providers[i]; | |
for (j=0; j<provider.coverageAreas.length; j++) { | |
bbox = provider.coverageAreas[j].bbox; | |
provider.coverageAreas[j].bbox = new L.LatLngBounds(new L.LatLng(bbox[0],bbox[1],true),new L.LatLng(bbox[2],bbox[3], true)); | |
} | |
} | |
this._url = res.imageUrl.replace('{culture}','en-US'); | |
this.options.subdomains = [].concat(res.imageUrlSubdomains); | |
script.parentNode.removeChild(script); | |
window[this._callbackId] = undefined; // cannot delete from window in IE | |
delete this._callbackId; | |
this._onMetadataLoaded(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I know this thread has been closed for awhile, but I wanted to let you guys know that I've modified the Bing.js file to allow for multiple options for the map types. This also allows the API code to be put into the .js file and out of the main display file, while simplifying the front-end coding.
/* add your API code to the top _/
var key= 'your_API_code';
L.BingLayer = L.TileLayer.extend({
options: {
subdomains: [0, 1, 2, 3],
/_type: 'Road', / /<================== Comment out or remove the type option */
attribution: 'Bing',
culture: ''
},
initialize: function(/key,/ mtype, options) { /_<=== Comment out or remove the key option
and add the type as an option */
L.Util.setOptions(this, options);
this._key = key;
this.type = mtype; /<================== Add the type option to the function call */
this._url = null;
this.meta = {};
this.loadMetadata();
},
.
.
.
/* Change the this.options.type to _this.type in the url definition */
var url = document.location.protocol + '//dev.virtualearth.net/REST/v1/Imagery/Metadata/' + this._type + ...
In your display page you can now simply your code and add display options without having to triple the number of JS files.
var map = new L.Map('map', {center: new L.LatLng(67.6755, 33.936), zoom: 10 });
var bingr = new L.BingLayer("Road");
var binga = new L.BingLayer("Aerial");
var bingl = new L.BingLayer("AerialWithLabels");
map.addLayer(bingl);
map.addLayer(binga);
map.addLayer(bingr);
map.addControl(new L.Control.Layers({'Road':bingr, "Aerial":binga, "Hybrid":bingl}, {}));