问题
I have a number of tile sources which utilise Bing Maps' Quadkey system in an old Silverlight application and I would like to use them in a new Openlayers 3 map.
I have found several examples of functions which will convert these sources for Leaflet.js but the syntax is somewhat different for OL3 and reading through the API docs indicates that there is an ol.Tile.coord class but if I understand correctly this is an experimental feature and might require a custom build from the source code.
There is reference to such functionality on the GitHub pages but I don't know if I have to compile a build with this source: https://github.com/openlayers/ol3/blob/5c5364bbb7e8df76f18242ad665c87ca08a76e76/src/ol/source/bingmapssource.js
Can anyone provide an example of this type of conversion or indeed does anyone know if the latest (3.8.2) version of OL3 supports the quadkey method?
This is the leaflet example:
var BingLayer = L.TileLayer.extend({
getTileUrl: function (tilePoint) {
this._adjustTilePoint(tilePoint);
return L.Util.template(this._url, {
s: this._getSubdomain(tilePoint),
q: this._quadKey(tilePoint.x, tilePoint.y, this._getZoomForUrl())
});
},
_quadKey: function (x, y, z) {
var quadKey = [];
for (var i = z; i > 0; i--) {
var digit = '0';
var mask = 1 << (i - 1);
if ((x & mask) != 0) {
digit++;
}
if ((y & mask) != 0) {
digit++;
digit++;
}
quadKey.push(digit);
}
return quadKey.join('');
}
});
And this is the exisiting Silverlight code:
public override Uri GetUri(int x, int y, int zoomLevel, bool getPrintLink)
{
Uri uri = null;
if (this.Covers(x, y, zoomLevel))
{
QuadKey qk = new QuadKey(x, y, zoomLevel);
if (getPrintLink)
{
uri = new Uri(this.CurrentHostURL + "/tiles/NL/" + zoomLevel.ToString() + "/" + qk.Key + ".ipic", UriKind.RelativeOrAbsolute);
}
else
{
uri = new Uri("http://tileserver.satmap.com/NL/" + zoomLevel.ToString() + "/" + qk.Key + ".ipic", UriKind.RelativeOrAbsolute);
}
}
return uri;
}
Any insight would be appreciated as I've trawled many forums and countless pages of search results without finding a solution.
回答1:
As far as I can see, your _quadKey function is correct. The issue that might arise is understanding the ol.TileCoord provided to the URL function.
In OpenLayers 3.7 and later, all TileCoord
s are calculated with the top left corner as their origin. Furthermore, both the X and Y coordinates increase naturally, so that the X and Y coordinates of a TileCoord corresponds to the normal concepts of a two-dimensional axis.
The top left tile of a given zoom level will always have X=0 and Y=-1. The tile below that will have X=0 and Y=-2; Y will always be negative.
Some mapping applications, such as Bing, also use the top left corner as the tile origin, but lets the Y coordinate increase downwards. The top left tile would the be X=0 and Y=0, while the tile below would be X=0 and Y=1.
In order to calculate the quadkeys, the Y coordinate has to be inverted and adjusted by one. This should work:
// this is unchanged from the question
var quadkey = function (x, y, z) {
var quadKey = [];
for (var i = z; i > 0; i--) {
var digit = '0';
var mask = 1 << (i - 1);
if ((x & mask) != 0) {
digit++;
}
if ((y & mask) != 0) {
digit++;
digit++;
}
quadKey.push(digit);
}
return quadKey.join('');
};
var quadKeyLayer = new ol.layer.Tile({
source: new ol.source.XYZ({
maxZoom: 19,
tileUrlFunction: function (tileCoord, pixelRatio, projection) {
var z = tileCoord[0];
var x = tileCoord[1];
var y = -tileCoord[2] - 1;
return "//example.com/r" + quadkey(x, y, z);
}
})
});
来源:https://stackoverflow.com/questions/32454234/using-bing-maps-quadkeys-as-openlayers-3-tile-source