-
-
Save pagameba/1221998 to your computer and use it in GitHub Desktop.
/* | |
* Portions of this code and logic copied from OpenLayers and | |
* redistributed under the original Clear BSD license terms: | |
* | |
* http://trac.osgeo.org/openlayers/browser/license.txt | |
* | |
* Copyright 2005-2010 OpenLayers Contributors, released under | |
* the Clear BSD license. See authors.txt for a list of contributors. | |
* All rights reserved. | |
* | |
* -- | |
* | |
* Leaflet-specific modifications are released under the following | |
* terms: | |
* | |
* This program is free software. It comes without any warranty, to | |
* the extent permitted by applicable law. You can redistribute it | |
* and/or modify it under the terms of the Do What The Fuck You Want | |
* To Public License, Version 2, as published by Sam Hocevar. See | |
* http://sam.zoy.org/wtfpl/COPYING for more details. | |
*/ | |
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++); | |
var 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._map.attributionControl._attributions = {}; | |
this._map.attributionControl._update(); | |
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(); | |
} |
You can see it working at http://opengis.azexperience.org/vae/azcentennial/
Yes, Ryan's changes worked. Thanks! :D
It'll also be nice if you could explicitly state what license this code is under...
Great point. I've updated this Gist with Ryan's changes (untested) and appropriate license and copyright details.
Cheers
Paul
There are still problems, I think, if you want to have more than one Bing layer in your app.
Issue with multiple Bing Layers and attributions being added multiple times:
Replace
`````` this._map.attributionControl.removeAttribution(this.attribution);```
with
this._map.attributionControl._attributions = {};
this._map.attributionControl._update();```
Forked here:
https://gist.github.com/2342958
updated gist with ccgdesigns contribution.
When I try to overlay a custom tilelayer over the bing layer, the bing one always supersedes. As in, I want the custom layer to be on top. The custom layer falls under the aerial imagery, so i don't see it at all!
This code has been incorporated into https://github.com/shramov/leaflet-plugins, I suggest following up there.
Hi,
We are using leaflet with bing map
I am wondering if it is possible to retrieve session id to decrease billable calls to bingmap
If we use session id instead of key after first call they are nonbillable.
For bingmap ajax there is getcredentials function but I could not find anything similar with leaflet.
callback function only includes traceid.
Thanks
Hi everybody, I'm trying to add tile bing to my map, espacially 'AerialWithLabels' type. So do you have any idea how to use that? I'm using leaflet with angularJS. Honestly, I'm beginner in leaflet.
Any help is appreciated. Thankx for advance
:) sorry, its been a busy week. Does Ryan's fork linked above work for you? I haven't tried it yet.