281 lines
7.7 KiB
JavaScript
281 lines
7.7 KiB
JavaScript
/* MVT加载类 作者: 木遥(微信: http://marsgis.cn/weixin.html ) */
|
||
(function (window) {
|
||
|
||
function MvtImageryProvider (options) {
|
||
options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
|
||
this.options = options;
|
||
|
||
this._tileWidth = Cesium.defaultValue(options.tileWidth, 512);
|
||
this._tileHeight = Cesium.defaultValue(options.tileHeight, 512);
|
||
this._minimumLevel = Cesium.defaultValue(options.minimumLevel, 0);
|
||
this._maximumLevel = Cesium.defaultValue(options.maximumLevel, 18);
|
||
|
||
|
||
if (options.rectangle && options.rectangle.xmin && options.rectangle.xmax && options.rectangle.ymin && options.rectangle.ymax) {
|
||
var xmin = options.rectangle.xmin;
|
||
var xmax = options.rectangle.xmax;
|
||
var ymin = options.rectangle.ymin;
|
||
var ymax = options.rectangle.ymax;
|
||
options.rectangle = Cesium.Rectangle.fromDegrees(xmin, ymin, xmax, ymax);
|
||
}
|
||
this._tilingScheme = Cesium.defaultValue(options.tilingScheme, new Cesium.WebMercatorTilingScheme({ ellipsoid: options.ellipsoid }));
|
||
this._rectangle = Cesium.defaultValue(options.rectangle, this._tilingScheme.rectangle);
|
||
this._rectangle = Cesium.Rectangle.intersection(this._rectangle, this._tilingScheme.rectangle);
|
||
this._hasAlphaChannel = Cesium.defaultValue(options.hasAlphaChannel, true);
|
||
|
||
this._errorEvent = new Cesium.Event();
|
||
this._readyPromise = Cesium.when.resolve(true);
|
||
this._credit = undefined;
|
||
this._ready = true;
|
||
|
||
//mvt相关的处理
|
||
if (!window.ol) {
|
||
throw new DeveloperError('请引入Openlayers类库!');
|
||
}
|
||
this._ol = window.ol;
|
||
this._mvtParser = new this._ol.format.MVT();
|
||
|
||
switch (options.style) {
|
||
case "mapbox-streets-v6":
|
||
this._styleClass = new mars3d.MapboxStreetsV6()
|
||
break;
|
||
default:
|
||
this._styleClass = options.style;
|
||
break;
|
||
|
||
}
|
||
|
||
this._key = Cesium.defaultValue(options.key, "");
|
||
this._url = Cesium.defaultValue(options.url, "");
|
||
|
||
var sw = this._tilingScheme._rectangleSouthwestInMeters;
|
||
var ne = this._tilingScheme._rectangleNortheastInMeters;
|
||
var mapExtent = [sw.x, sw.y, ne.x, ne.y];
|
||
this._resolutions = ol.tilegrid.resolutionsFromExtent(mapExtent, this._maximumLevel, this._tileWidth);
|
||
|
||
this._pixelRatio = 1;
|
||
this._transform = [0.125, 0, 0, 0.125, 0, 0];
|
||
this._replays = ["Default", "Image", "Polygon", "LineString", "Text"];
|
||
|
||
this._tileQueue = new Cesium.TileReplacementQueue();
|
||
this._cacheSize = 1000;
|
||
}
|
||
|
||
Object.defineProperties(MvtImageryProvider.prototype, {
|
||
proxy: {
|
||
get: function () {
|
||
return undefined;
|
||
}
|
||
},
|
||
|
||
tileWidth: {
|
||
get: function () {
|
||
return this._tileWidth;
|
||
}
|
||
},
|
||
|
||
tileHeight: {
|
||
get: function () {
|
||
return this._tileHeight;
|
||
}
|
||
},
|
||
|
||
maximumLevel: {
|
||
get: function () {
|
||
return undefined;
|
||
}
|
||
},
|
||
|
||
minimumLevel: {
|
||
get: function () {
|
||
return undefined;
|
||
}
|
||
},
|
||
|
||
tilingScheme: {
|
||
get: function () {
|
||
return this._tilingScheme;
|
||
}
|
||
},
|
||
|
||
rectangle: {
|
||
get: function () {
|
||
return this._tilingScheme.rectangle;
|
||
}
|
||
},
|
||
|
||
tileDiscardPolicy: {
|
||
get: function () {
|
||
return undefined;
|
||
}
|
||
},
|
||
|
||
errorEvent: {
|
||
get: function () {
|
||
return this._errorEvent;
|
||
}
|
||
},
|
||
|
||
ready: {
|
||
get: function () {
|
||
return true;
|
||
}
|
||
},
|
||
|
||
readyPromise: {
|
||
get: function () {
|
||
return this._readyPromise;
|
||
}
|
||
},
|
||
|
||
credit: {
|
||
get: function () {
|
||
return undefined;
|
||
}
|
||
},
|
||
|
||
hasAlphaChannel: {
|
||
get: function () {
|
||
return true;
|
||
}
|
||
}
|
||
});
|
||
|
||
MvtImageryProvider.prototype.getTileCredits = function (x, y, level) {
|
||
return undefined;
|
||
};
|
||
|
||
MvtImageryProvider.prototype.pickFeatures = function (x, y, level, longitude, latitude) {
|
||
return undefined;
|
||
};
|
||
|
||
MvtImageryProvider.prototype.requestImage = function (x, y, level, request) {
|
||
var cacheTile = findTileInQueue(x, y, level, this._tileQueue);
|
||
if (cacheTile != undefined) {
|
||
return cacheTile;
|
||
}
|
||
else {
|
||
var that = this;
|
||
var url = this._url;
|
||
|
||
var reverseY = this._tilingScheme.getNumberOfYTilesAtLevel(level) - y - 1;
|
||
url = url.replace('{x}', x).replace('{y}', y).replace('{reverseY}', reverseY).replace('{z}', level).replace('{k}', this._key);
|
||
|
||
var resource = Cesium.Resource.createIfNeeded(url);
|
||
return resource.fetchArrayBuffer().then(function (arrayBuffer) {
|
||
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width = that._tileWidth;
|
||
canvas.height = that._tileHeight;
|
||
var vectorContext = canvas.getContext('2d');
|
||
|
||
var features = that._mvtParser.readFeatures(arrayBuffer);
|
||
|
||
var styleFun = that._styleClass.getStyle();
|
||
|
||
var extent = [0, 0, 4096, 4096];
|
||
var _replayGroup = new ol.render.canvas.ReplayGroup(0, extent,
|
||
8, true, 100);
|
||
|
||
for (var i = 0; i < features.length; i++) {
|
||
var feature = features[i];
|
||
var styles = styleFun(features[i], that._resolutions[level]);
|
||
for (var j = 0; j < styles.length; j++) {
|
||
ol.renderer.vector.renderFeature_(_replayGroup, feature, styles[j], 16);
|
||
}
|
||
}
|
||
_replayGroup.finish();
|
||
|
||
_replayGroup.replay(vectorContext, that._pixelRatio, that._transform, 0, {}, that._replays, true);
|
||
if (that._tileQueue.count > that._cacheSize) {
|
||
trimTiles(that._tileQueue, that._cacheSize / 2);
|
||
}
|
||
|
||
canvas.xMvt = x;
|
||
canvas.yMvt = y;
|
||
canvas.zMvt = level;
|
||
that._tileQueue.markTileRendered(canvas);
|
||
|
||
delete _replayGroup;
|
||
_replayGroup = null;
|
||
|
||
return canvas;
|
||
}).otherwise(function (error) {
|
||
return undefined;
|
||
});
|
||
}
|
||
};
|
||
|
||
function findTileInQueue (x, y, level, tileQueue) {
|
||
var item = tileQueue.head;
|
||
while (item != undefined && !(item.xMvt == x && item.yMvt == y && item.zMvt == level)) {
|
||
item = item.replacementNext;
|
||
}
|
||
return item;
|
||
};
|
||
|
||
function removeQueue (tileReplacementQueue, item) {
|
||
var previous = item.replacementPrevious;
|
||
var next = item.replacementNext;
|
||
|
||
if (item === tileReplacementQueue._lastBeforeStartOfFrame) {
|
||
tileReplacementQueue._lastBeforeStartOfFrame = next;
|
||
}
|
||
|
||
if (item === tileReplacementQueue.head) {
|
||
tileReplacementQueue.head = next;
|
||
} else {
|
||
previous.replacementNext = next;
|
||
}
|
||
|
||
if (item === tileReplacementQueue.tail) {
|
||
tileReplacementQueue.tail = previous;
|
||
} else {
|
||
next.replacementPrevious = previous;
|
||
}
|
||
|
||
item.replacementPrevious = undefined;
|
||
item.replacementNext = undefined;
|
||
|
||
--tileReplacementQueue.count;
|
||
}
|
||
|
||
function trimTiles (tileQueue, maximumTiles) {
|
||
var tileToTrim = tileQueue.tail;
|
||
while (tileQueue.count > maximumTiles &&
|
||
Cesium.defined(tileToTrim)) {
|
||
var previous = tileToTrim.replacementPrevious;
|
||
|
||
removeQueue(tileQueue, tileToTrim);
|
||
delete tileToTrim;
|
||
tileToTrim = null;
|
||
|
||
tileToTrim = previous;
|
||
}
|
||
};
|
||
|
||
|
||
|
||
function createImageryProvider (options) {
|
||
return new MvtImageryProvider(options)
|
||
}
|
||
|
||
class MvtLayer extends mars3d.layer.BaseTileLayer {
|
||
//构建ImageryProvider
|
||
_createImageryProvider (options, urltemplate) {
|
||
return createImageryProvider(options, urltemplate)
|
||
}
|
||
}
|
||
MvtLayer.createImageryProvider = createImageryProvider
|
||
|
||
//注册下
|
||
const layerType = 'mvt'//图层类型
|
||
mars3d.layer.register(layerType, MvtLayer)
|
||
mars3d.layer.registerImageryProvider(layerType, createImageryProvider)
|
||
|
||
//对外接口
|
||
window.mars3d.provider.MvtImageryProvider = MvtImageryProvider;
|
||
window.mars3d.layer.MvtLayer = MvtLayer;
|
||
|
||
})(window);
|