-
-
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(); | |
} |
Hi, sorry I don't have a working example any more, I deleted it somewhere along the way. I will be coming back to this experiment in a few weeks as I will have need of it again, until then I don't have time to debug problems. I expect the issue is that Bing has changed something in their API and this code would need to be updated to accommodate the changes. This code was adapted from OpenLayers Bing support, I notice the OpenLayers Bing example is still working so perhaps you could start there if you need to get it working sooner .. http://openlayers.org/dev/examples/bing-tiles.html
Cheers
Paul
I had some trouble with the processMetadata function. It looks to me like Leaflet commit e5f934e changed L.Utils.bind in such a way as to break your callback. A clumsy adjustment to your _loadMetadata
routine fixed it for me:
//window[this._callbackId] = L.Util.bind(L.TileLayer.Bing.processMetadata, this);
that = this;
window[this._callbackId] = function() { L.TileLayer.Bing.processMetadata.apply(that, arguments); };
I forked your Gist with my changes
Thanks,
Ryan
/me pokes
:) sorry, its been a busy week. Does Ryan's fork linked above work for you? I haven't tried it yet.
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
Hello! I'm trying to get this to work but Bing is giving me '400 Bad Request' responses. Is there someplace with a working example of this I could look at? Thanks!