|
define([
|
'Util/turf',
|
"Util/Shp",
|
'Data/Geojson/LonLatProjection',
|
'Util/Path',
|
//'Util/Contour/PolyLine',
|
//'Util/Contour/Polygon',
|
'VectorRenderer/VectorStyle'
|
//,'Core/Resources'
|
], function (
|
turf,
|
shp,
|
LonLatProjection,
|
Path,
|
//PolyLine,
|
//Polygon,
|
VectorStyle
|
//,Resources
|
) {
|
|
if (Cesium.Resource) {
|
Cesium.loadText = Cesium.Resource.fetchText;
|
Cesium.loadJson = Cesium.Resource.fetchJson;
|
Cesium.loadBlob = Cesium.Resource.fetchBlob;
|
Cesium.loadArrayBuffer = Cesium.Resource.fetchArrayBuffer;
|
Cesium.loadImage = Cesium.Resource.fetchImage;
|
}
|
var defaultColor = new Cesium.Color(1.0, 1.0, 1.0, 0.4);
|
var defaultGlowColor = new Cesium.Color(0.0, 1.0, 0.0, 0.05);
|
var defaultBackgroundColor = new Cesium.Color(0.0, 0.5, 0.0, 0.2);
|
function isShpLocalFiles(files) {
|
var isFile = files.length >= 3;
|
if (!isFile) return false;
|
var shpFile, dbfFile, prjFile;
|
for (var i = 0; i < files.length; i++) {
|
var file = files[i];
|
if (!(file instanceof File || (file instanceof Blob && file.name))) {
|
return false;
|
}
|
if (files[i].name.toLocaleLowerCase().indexOf(".shp") > 0) {
|
shpFile = files[i];
|
}
|
if (files[i].name.toLocaleLowerCase().indexOf(".prj") > 0) {
|
prjFile = files[i];
|
}
|
if (files[i].name.toLocaleLowerCase().indexOf(".dbf") > 0) {
|
dbfFile = files[i];
|
}
|
}
|
if (!shpFile || !prjFile || !dbfFile) {
|
return false;
|
}
|
return true;
|
}
|
|
/**
|
*动态矢量切片提供程序,支持esri shapefile、geojson文件,也可以直接加载geojson对象和Polygon,PolyLine
|
* <ul class="see-list">
|
* <li><a href="https://mikeswei.github.io/CesiumVectorTile/" target="_blank">VectorTileImageryProviderDemo</a></li>
|
* </ul>
|
*@param {Object}options 参数如下:
|
*@param {String|turf.FeatureCollection|Object|Array<MeteoLib.Util.Contour.PolyLine|MeteoLib.Util.Contour.Polygon|File>}options.source MeteoLib.Util.Contour.PolyLine及MeteoLib.Util.Contour.Polygon数组、矢量文件url、矢量文件列表或者geojson对象
|
*@param {Cesium.VectorStyle}[options.defaultStyle=Cesium.VectorStyle.Default] 默认样式
|
*@param {Boolean}[options.simplify=false] true则简化,默认不简化
|
*@param {Boolean}[options.simplifyTolerance=0.01] 简化公差
|
*@param {Boolean}[options.minimumLevel=3] 最小级别
|
*@param {Boolean}[options.maximumLevel=22] 最大级别
|
*@param {Boolean}[options.showMaximumLevel=true] 当超出最大级别时是否继续显示
|
*@param {Boolean}[options.removeDuplicate=true] 是否剔除重复(有相同的坐标)的多边形
|
*@param {Boolean}[options.allowPick=false] 是否支持要素查询,如果支持要素查询则保留原始的geojson,会多占用系统内存
|
*
|
*@param {Cesium.VectorTileImageryProvider~StyleFilterCallback}[options.styleFilter=undefined] 样式函数
|
*@constructor
|
*@memberof Cesium
|
*@extends Cesium.ImageryProvider
|
*@example
|
//1.面数据
|
viewer.imageryLayers.addImageryProvider(new VectorTileImageryProvider({
|
source: appConfig.BaseURL + "Assets/VectorData/中国数据/陕西/榆林/county_sshanxi_yulin.shp",
|
defaultStyle:{ outlineColor: Cesium.Color.WHITE,
|
fill: true
|
},
|
maximumLevel: 22,
|
minimumLevel: 0
|
}))
|
//2.点数据
|
viewer.imageryLayers.addImageryProvider(new VectorTileImageryProvider({
|
source: appConfig.BaseURL + "Assets/VectorData/中国数据/陕西/榆林/town_sshanxi_yulin.shp"
|
,defaultStyle:{
|
fontColor: Cesium.Color.WHITE
|
, fontSize: 20
|
, fontFamily: '微软雅黑'
|
, makerImage: appConfig.BaseURL + "Assets/Images/Stations/autonew.png"
|
, labelOffsetY: 5
|
, labelOffsetX: 10
|
}
|
, maximumLevel: 22
|
, minimumLevel: 9
|
}))
|
//3.线数据
|
viewer.imageryLayers.addImageryProvider(new VectorTileImageryProvider({
|
source: appConfig.BaseURL + "Assets/VectorData/中国数据/中国边界.shp"
|
}))
|
|
//4.geojson
|
viewer.imageryLayers.addImageryProvider(new VectorTileImageryProvider({
|
source: appConfig.BaseURL + "Assets/SampleData/simplestyles.geojson",//VectorData/中国数据/中国边界.shp",
|
defaultStyle:{
|
fill: true
|
},
|
minimumLevel: 0
|
}))
|
|
5.使用样式函数(styleFilter)设置样式
|
viewer.imageryLayers.addImageryProvider(new Cesium.VectorTileImageryProvider({
|
source: appConfig.BaseURL + "Assets/VectorData/世界数据/Countries.shp",
|
defaultStyle: {
|
outlineColor: Cesium.Color.YELLOW,
|
lineWidth: 2,
|
fillColor: Cesium.Color.fromBytes(2, 24, 47, 200),
|
fill: false,
|
tileCacheSize: 200,
|
showMaker: false,
|
showCenterLabel: true,
|
fontColor: "rgba(255,0,0,1)",
|
labelOffsetX: -10,
|
labelOffsetY: -5,
|
fontSize: 13,
|
fontFamily: "黑体",
|
centerLabelPropertyName: "NAME"
|
},
|
maximumLevel: 20,
|
minimumLevel: 1,
|
simplify: false ,
|
styleFilter: function (feature, style) {
|
if (feature.properties.hasOwnProperty("NAME") && feature.properties["NAME"].toLocaleLowerCase().indexOf("china") >= 0) {
|
style.outlineColor = Cesium.Color.RED;
|
style.fill = true;
|
style.fillColor = Cesium.Color.AZURE.withAlpha(0.5);
|
}
|
}
|
}))
|
|
6.配图示例
|
appConfig.map = appConfig.map ? appConfig.map : {
|
focusAdminNames: ['北京', '天津', '河北'],
|
focusPropertyName: "NAME"
|
};
|
imageryProviders.seaLandImgProvider = new VectorTileImageryProvider({
|
source: appConfig.BaseURL + 'Assets/SampleData/sealand.geojson',
|
zIndex: 999,
|
minimumLevel: 0,
|
defaultStyle: {
|
fill: true,//是否填充海陆颜色
|
outlineColor: 'rgba(138,138,138,1)',//边界颜色
|
fillColor: 'rgba(235,235,235,1)',//陆地颜色
|
backgroundColor: 'rgba(89,129,188,1)'//海区颜色
|
}
|
});
|
imageryProviders.chinaBorderImgProvider = new VectorTileImageryProvider({
|
source: appConfig.BaseURL + 'Assets/SampleData/ChinaBorder.geojson',
|
zIndex: 999,
|
minimumLevel: 0,
|
defaultStyle: {
|
lineWidth: 1.25,
|
outlineColor: 'rgba(88,88,88,1)'
|
}
|
});
|
|
imageryProviders.provinceImgProvider = new VectorTileImageryProvider({
|
source: appConfig.BaseURL + 'Assets/SampleData/Province.geojson',
|
zIndex: 998,
|
minimumLevel: 0,
|
defaultStyle: {
|
lineWidth: 1,
|
//lineDash: [1, 4],
|
fill: true,
|
outline: true,
|
shadowColor: Cesium.Color.WHITE,
|
outlineColor: 'rgba(118,118,118,1)',
|
fillColor: 'rgba(225,225,225, .5)'
|
},
|
styleFilter: function (feature, style) {
|
|
if (appConfig.map) {
|
var highlight = false;
|
for (var i = 0; i < appConfig.map.focusAdminNames.length; i++) {
|
highlight = feature.properties[appConfig.map.focusPropertyName]
|
&& feature.properties[appConfig.map.focusPropertyName].indexOf(appConfig.map.focusAdminNames[i]) >= 0;
|
if (highlight) break;
|
}
|
if (highlight) {
|
style.fill = false;
|
style.outlineColor = Cesium.Color.BLACK;
|
style.fillColor = Cesium.Color.WHITE;
|
style.lineWidth = 1.25;
|
style.lineDash = null;
|
}
|
}
|
|
return style;
|
}
|
});
|
|
imageryProviders.adminLabelImgProvider = new VectorTileImageryProvider({
|
source: appConfig.BaseURL + 'Assets/SampleData/placeName.geojson',
|
minimumLevel: 3,
|
defaultStyle: {
|
showLabel: true,
|
labelPropertyName: "name",
|
fontFamily: 'heiti',
|
showMaker: true,
|
labelOffsetY: -12,
|
pointColor: 'rgba(118,118,118,1)',
|
labelStrokeWidth: 4,
|
fontSize: 12,
|
labelStroke: true,
|
fontColor: Cesium.Color.WHITE,
|
labelStrokeColor: 'rgba(118,118,118,1)'//Cesium.Color.BLACK
|
},
|
styleFilter: function (fc, style, x, y, level) {
|
var highlight = false;
|
if (appConfig.map && fc.properties.province) {
|
|
for (var i = 0; i < appConfig.map.focusAdminNames.length; i++) {
|
highlight = fc.properties.province.indexOf(
|
appConfig.map.focusAdminNames[i]
|
) >= 0;
|
if (highlight) break;
|
}
|
}
|
if (highlight) {
|
style.pointColor = Cesium.Color.BLACK;
|
}
|
if (fc.properties.adminType == 'province') {
|
if (level > 14) {
|
style.show = false;
|
}
|
style.showMaker = false;
|
style.labelOffsetY = 0;
|
style.fontSize = 16;
|
if (highlight) {
|
style.labelStrokeColor = Cesium.Color.fromBytes(160, 99, 57);
|
} else {
|
style.labelStrokeColor = Cesium.Color.fromBytes(140, 89, 47);
|
}
|
} else {
|
|
if (fc.properties.adminType == 'city') {
|
if (level < 6) {
|
style.show = false;
|
}
|
}
|
if (fc.properties.adminType == 'county' && level < 10) {
|
style.show = false;
|
}
|
if (fc.properties.adminType == 'country') {
|
style.show = false;
|
}
|
|
if (level > 14) {
|
style.fontSize = 18;
|
}
|
|
if (highlight) {
|
style.labelStrokeColor = Cesium.Color.BLACK;
|
}
|
}
|
if (level < 6) {
|
style.fontSize = 9;
|
}
|
if (level > 4) {
|
style.labelPropertyName = "name";
|
} else {
|
style.labelPropertyName = "nameabbrevation";
|
}
|
|
return style;
|
}
|
})
|
imageryProviderViewModels.push(new Cesium.ProviderViewModel({
|
name: '海陆模版',
|
iconUrl: appConfig.BaseURL + 'Assets/Images/ImageryProviders/sealand.png',
|
tooltip: '海陆模版',
|
creationFunction: function () {
|
setTimeout(function () {
|
imageryProviderViewModels.onSelected(imageryProviders.seaLandImgProvider);
|
}, 200);
|
return imageryProviders.seaLandImgProvider;
|
}
|
}));
|
*/
|
function VectorTileImageryProvider(options) {
|
///@param {Boolean}[options.multipleTask=true] 是否使用多个VectorTileImageryProvider实例,使用多个实例是设置该参数为true可以提高ui响应速度,使用唯一一个实例时设置该参数为false则可以提高切片速度。
|
//@param {Boolean}[options.taskWaitTime=10] 使用多个实例时,每个实例的切片任务延迟结束的时间,以此来避免多个矢量图层同时存在时出现某个图层一直更新而其他图层一直没有更新的bug
|
|
options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
|
if (!Cesium.defined(options.source)) {
|
throw new Cesium.DeveloperError("source is required");
|
}
|
var ext = null;
|
var isLocalShpFile = false;
|
if (typeof options.source == 'string') {
|
var source = options.source.toLowerCase();
|
ext = Path.GetExtension(source)
|
if (ext !== '.shp' && ext !== '.json' && ext !== '.geojson' && ext !== '.topojson') {
|
throw new Cesium.DeveloperError("The data options.source provider is not supported.");
|
}
|
} else if (options.source.type && options.source.type == "FeatureCollection") {
|
|
} else if (isShpLocalFiles(options.source)) {
|
isLocalShpFile = true;
|
}
|
else if (Cesium.isArray(options.source)) {
|
if (!(options.source[0] instanceof PolyLine) && (options.source[0] instanceof Polygon)) {
|
throw new Cesium.DeveloperError("The data options.source provider is not supported.");
|
}
|
} else {
|
throw new Cesium.DeveloperError("The data options.source provider is not supported.");
|
}
|
|
this._tilingScheme = new Cesium.GeographicTilingScheme({ ellipsoid: options.ellipsoid });
|
this._tileWidth = Cesium.defaultValue(options.tileWidth, 256);
|
this._tileHeight = Cesium.defaultValue(options.tileHeight, 256);
|
|
//if (ext && ext == '.shp') {
|
// ext = Path.GetExtension(options.source)
|
// this._url = options.source.replace(ext, '');
|
//} else {
|
this._url = options.source;
|
//}
|
this._fileExtension = ext;
|
|
this._removeDuplicate = Cesium.defaultValue(options.removeDuplicate, true);
|
this._allowPick = Cesium.defaultValue(options.allowPick, false);
|
this._simplifyTolerance = Cesium.defaultValue(options.simplifyTolerance, 0.01);
|
this._simplify = Cesium.defaultValue(options.simplify, false);
|
//this._multipleTask = Cesium.defaultValue(options.multipleTask, true);
|
//this._taskWaitTime = Cesium.defaultValue(options.taskWaitTime, 10);
|
this._maximumLevel = Cesium.defaultValue(options.maximumLevel, 22)
|
this._minimumLevel = Cesium.defaultValue(options.minimumLevel, 3)
|
this._showMaximumLevel = Cesium.defaultValue(options.showMaximumLevel, true)
|
this._makerImage = options.makerImage;
|
this._tileCacheSize = Cesium.defaultValue(options.tileCacheSize, 200);
|
if (typeof options.defaultStyle == 'object' && !(options.defaultStyle instanceof VectorStyle)) {
|
options.defaultStyle = new VectorStyle(options.defaultStyle);
|
}
|
this._defaultStyle = Cesium.defaultValue(options.defaultStyle, VectorStyle.Default.clone());
|
this._styleFilter = typeof options.styleFilter == 'function' ? options.styleFilter : undefined;
|
|
|
this._errorEvent = new Cesium.Event();
|
this._featuresPicked = new Cesium.Event();
|
this._readyPromise = Cesium.when.defer();
|
this._ready = false;
|
this._state = VectorTileImageryProvider.State.READY;
|
|
this._cache = {};
|
this._count = 0;
|
this.zIndex = options.zIndex;
|
this._bbox = null;
|
this._geoJSON = null;
|
var that = this;
|
var promises = [];
|
var makerImagePromise = null;
|
if (typeof this._makerImage == 'string') {
|
makerImagePromise = Cesium.when.defer();
|
var image = new Image();
|
image.onload = function () {
|
makerImagePromise.resolve(this);
|
that._makerImageEl = this;
|
}
|
image.onerror = function (err) {
|
makerImagePromise.resolve(err);
|
}
|
image.src = this._makerImage;
|
promises.push(makerImagePromise);
|
}
|
|
var shpPromise = Cesium.when.defer();
|
promises.push(shpPromise);
|
this._state = VectorTileImageryProvider.State.SHPLOADING;
|
if (ext) {
|
switch (ext) {
|
case '.shp':
|
shp(this._url).then(onSuccess, function (err) {
|
console.log("load shp file error:" + err);
|
});
|
break;
|
case '.json':
|
case '.geojson':
|
case '.topojson':
|
//Resources.get(this._url)
|
Cesium.loadText(this._url)
|
.then(function (geojson) {
|
eval("(" + geojson + ")")
|
onSuccess(geojson);
|
}).otherwise(function (err) {
|
console.log(err);
|
})
|
break;
|
default:
|
throw new Cesium.DeveloperError("The file options.source provider is not supported.");
|
}
|
} else {
|
if (isLocalShpFile) {
|
var prms = shp.parseShpFiles(that._url);
|
if (prms) {
|
prms.then(onSuccess).otherwise(function (err) {
|
console.log(err);
|
throw new Cesium.DeveloperError("The file options.source provider is not supported.");
|
});
|
} else {
|
throw new Cesium.DeveloperError("The file options.source provider is not supported.");
|
}
|
} else {
|
setTimeout(function () {
|
if (Cesium.isArray(that._url)) {
|
var contourLines = that._url;
|
|
if (contourLines[0] instanceof PolyLine) {
|
var coords = [];
|
var multiLineString = [];
|
for (var lineNum = 0; lineNum < contourLines.length; lineNum++) {
|
coords = [];
|
contourLines[lineNum].PointList.forEach(function (pt) {
|
coords.push(pt.getCoordArray());
|
})
|
multiLineString.push(coords);
|
}
|
multiLineString = turf.multiLineString(multiLineString);
|
multiLineString = turf.featureCollection([multiLineString]);
|
onSuccess(multiLineString);
|
}
|
else if (contourLines[0] instanceof Polygon) {
|
var multiPolygon = [];
|
for (var lineNum = 0; lineNum < contourLines.length; lineNum++) {
|
var coords = [];
|
contourLines[lineNum].OutLine.PointList.forEach(function (pt) {
|
coords.push(pt.getCoordArray());
|
})
|
var polygon = turf.polygon(coords, contourLines[0].getProperties());
|
multiPolygon.push(polygon);
|
}
|
multiPolygon = turf.featureCollection(multiPolygon);
|
onSuccess(multiPolygon);
|
} else {
|
throw new Cesium.DeveloperError("The data options.source provide is not supported.");
|
}
|
|
} else {
|
onSuccess(that._url);
|
}
|
}, 10)
|
}
|
|
}
|
|
this._lineGeoJSON = null;
|
this._outlineGeoJSON = null;
|
this._pointGeoJSON = null;
|
this._polygonJSON = null;
|
this._onlyPoint = false;
|
this._lineOnly = false;
|
this._polygonOnly = false;
|
|
function onSuccess(geoJSON) {
|
if (that._allowPick)
|
that._geoJSON = geoJSON;
|
var tolerance = that._simplifyTolerance;
|
var lines = [], outlines = [], points = [], polygons = [];
|
var onlyPoint = true, lineOnly = true, polygonOnly = true;
|
var simplified;
|
|
function groupByCenterLabelPropertyName(geoJSON, centerLabelPropertyName) {
|
var dic = {};
|
turf.featureEach(geoJSON, function (fc) {
|
|
if ((fc.geometry.type == 'Polygon'
|
|| fc.geometry.type == 'MultiPolygon')
|
&& that._defaultStyle.showCenterLabel
|
&& that._defaultStyle.centerLabelPropertyName
|
&& fc.properties.hasOwnProperty(centerLabelPropertyName)) {
|
|
if (!dic[fc.properties[centerLabelPropertyName]]) {
|
dic[fc.properties[centerLabelPropertyName]] = [];
|
}
|
dic[fc.properties[centerLabelPropertyName]].push(fc);
|
}
|
|
});
|
var keys = Object.keys(dic);
|
for (var i = 0; i < keys.length; i++) {
|
var fc = dic[keys[i]][0];
|
var fcs = turf.featureCollection(dic[keys[i]]);
|
var center = turf.center(fcs)
|
points.push(center);
|
center.properties = fc.properties;
|
delete dic[keys[i]];
|
}
|
|
}
|
|
if (that._defaultStyle.showCenterLabel
|
&& that._defaultStyle.centerLabelPropertyName) {
|
that._defaultStyle.showLabel = true;
|
that._defaultStyle.labelPropertyName = that._defaultStyle.centerLabelPropertyName;
|
|
groupByCenterLabelPropertyName(geoJSON, that._defaultStyle.centerLabelPropertyName);
|
}
|
|
turf.featureEach(geoJSON, function (fc) {
|
|
if (fc.geometry.type == 'MultiPolygon') {
|
var polygonCoords = turf.getCoords(fc);
|
polygonCoords.forEach(function (coords) {
|
geoJSON.features.push(turf.polygon(coords, fc.properties));
|
})
|
polygonCoords = [];
|
}
|
})
|
|
for (var i = 0; i < geoJSON.features.length; i++) {
|
if (geoJSON.features[i].geometry.type == 'MultiPolygon') {
|
geoJSON.features.splice(i, 1)
|
}
|
}
|
if (that._removeDuplicate) {
|
geoJSON = turf.removeDuplicate(geoJSON);
|
}
|
|
|
turf.featureEach(geoJSON, function (feature, index) {
|
if (feature.geometry.type == "Point"
|
|| feature.geometry.type == "MultiPoint") {
|
points.push(feature);
|
lineOnly = false;
|
polygonOnly = false;
|
} else if (that._defaultStyle.showCenterLabel
|
&& that._defaultStyle.centerLabelPropertyName
|
&& feature.geometry.type !== "Polygon"
|
&& feature.geometry.type !== "MultiPolygon") {
|
that._defaultStyle.showLabel = true;
|
that._defaultStyle.labelPropertyName = that._defaultStyle.centerLabelPropertyName;
|
var center = turf.centerOfMass(feature)
|
points.push(center);
|
center.properties = feature.properties;
|
}
|
|
if (feature.geometry.type == "Polygon"
|
|| feature.geometry.type == "MultiPolygon") {
|
outlines = outlines.concat(turf.polygonToLineString(feature).features);
|
onlyPoint = false;
|
lineOnly = false;
|
|
if (that._simplify) {
|
simplified = turf.simplify(feature, tolerance, false);
|
polygons.push(simplified);
|
|
simplified = null;
|
} else {
|
polygons.push(feature);
|
|
}
|
}
|
if (feature.geometry.type == "MultiLineString"
|
|| feature.geometry.type == "LineString") {
|
|
if (that._simplify) {
|
simplified = turf.simplify(feature, tolerance, false);
|
lines.push(simplified);
|
|
simplified = null;
|
|
} else {
|
lines.push(feature);
|
|
}
|
onlyPoint = false;
|
polygonOnly = false;
|
}
|
})
|
|
if (lines.length > 0) {
|
that._lineGeoJSON = turf.featureCollection(lines);
|
lines = null;
|
}
|
|
if (outlines.length > 0) {
|
outlines.forEach(function (outline) {
|
outline.properties.isOutline = true;
|
})
|
that._outlineGeoJSON = turf.featureCollection(outlines);
|
outlines = null;
|
}
|
|
if (points.length > 0) {
|
that._pointGeoJSON = turf.featureCollection(points);
|
points = null;
|
}
|
|
if (polygons.length > 0) {
|
that._polygonJSON = turf.featureCollection(polygons);
|
polygons = null;
|
}
|
|
that._lineOnly = lineOnly;
|
that._polygonOnly = polygonOnly;
|
that._onlyPoint = onlyPoint;
|
that._state = VectorTileImageryProvider.State.LOADED;
|
that._bbox = turf.bbox(geoJSON);
|
// that.rectangle = Cesium.Rectangle.fromDegrees(that._bbox[0], that._bbox[1], that._bbox[2], that._bbox[3]);
|
that._bbox = Cesium.Rectangle.fromDegrees(that._bbox[0], that._bbox[1], that._bbox[2], that._bbox[3]);
|
geoJSON = null;
|
shpPromise.resolve(that);
|
}
|
|
Cesium.when.all(promises, function () {
|
that._ready = that._state == VectorTileImageryProvider.State.LOADED;
|
that._createCanvas();
|
VectorTileImageryProvider.instanceCount++;
|
that._readyPromise.resolve(true);
|
that._state = VectorTileImageryProvider.State.COMPELTED;
|
});
|
}
|
|
/**
|
*样式设置函数
|
*@callback Cesium.VectorTileImageryProvider~StyleFilterCallback
|
*@param {Geojson.Feature}feature 当前要素(用Geojson.Feature存储)
|
*@param {Cesium.VectorStyle}style 即将应用与当前要素的样式,可以通过修改该参数中的各样式设置选项来针对当前要素进行特殊的样式设置。
|
*修改后只对当前要素有效,不会修改Cesium.VectorTileImageryProvider的默认样式
|
*@param {Number}x
|
*@param {Number}y
|
*@param {Number}level
|
*@example
|
*/
|
|
VectorTileImageryProvider.instanceCount = 0;
|
VectorTileImageryProvider._currentTaskCount = 0;
|
VectorTileImageryProvider._maxTaskCount = 3;
|
VectorTileImageryProvider.State = {
|
READY: 0,
|
SHPLOADING: 1,
|
CLIPPING: 3,
|
GEOJSONDRAWING: 4,
|
COMPELTED: 5
|
}
|
Cesium.defineProperties(VectorTileImageryProvider.prototype, {
|
/**
|
*
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Cesium.VectorTileImageryProvider~StyleFilterCallback}
|
*/
|
styleFilter: {
|
get: function () {
|
return this._styleFilter;
|
},
|
set: function (val) {
|
this._styleFilter = val;
|
}
|
},
|
/**
|
*
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Cesium.VectorStyle}
|
* @readonly
|
*/
|
defaultStyle: {
|
get: function () {
|
return this._defaultStyle;
|
}
|
},
|
/**
|
* Gets the proxy used by this provider.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Proxy}
|
* @readonly
|
*/
|
proxy: {
|
get: function () {
|
return undefined;
|
}
|
},
|
|
/**
|
* Gets the width of each tile, in pixels. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Number}
|
* @readonly
|
*/
|
tileWidth: {
|
get: function () {
|
return this._tileWidth;
|
}
|
},
|
|
/**
|
* Gets the height of each tile, in pixels. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Number}
|
* @readonly
|
*/
|
tileHeight: {
|
get: function () {
|
return this._tileHeight;
|
}
|
},
|
|
/**
|
* Gets the maximum level-of-detail that can be requested. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Number}
|
* @readonly
|
*/
|
maximumLevel: {
|
get: function () {
|
return this._showMaximumLevel ? this._maximumLevel : 22;
|
}
|
},
|
|
/**
|
* Gets the minimum level-of-detail that can be requested. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Number}
|
* @readonly
|
*/
|
minimumLevel: {
|
get: function () {
|
//if (this._minimumLevel <5) {
|
// return this._minimumLevel;
|
//}
|
return 0;
|
}
|
},
|
|
/**
|
* Gets the tiling scheme used by this provider. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {TilingScheme}
|
* @readonly
|
*/
|
tilingScheme: {
|
get: function () {
|
return this._tilingScheme;
|
}
|
},
|
|
/**
|
* Gets the rectangle, in radians, of the imagery provided by this instance. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Rectangle}
|
* @readonly
|
*/
|
rectangle: {
|
get: function () {
|
return this._bbox;//_tilingScheme.rectangle;
|
}
|
},
|
|
/**
|
* Gets the tile discard policy. If not undefined, the discard policy is responsible
|
* for filtering out "missing" tiles via its shouldDiscardImage function. If this function
|
* returns undefined, no tiles are filtered. This function should
|
* not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {TileDiscardPolicy}
|
* @readonly
|
*/
|
tileDiscardPolicy: {
|
get: function () {
|
return undefined;
|
}
|
},
|
|
/**
|
* Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing
|
* to the event, you will be notified of the error and can potentially recover from it. Event listeners
|
* are passed an instance of {@link TileProviderError}.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Event}
|
* @readonly
|
*/
|
errorEvent: {
|
get: function () {
|
return this._errorEvent;
|
}
|
},
|
/**
|
* 要素查询时触发事件(如果允许执行要素查询的话)
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Event}
|
* @readonly
|
*/
|
featuresPicked: {
|
get: function () {
|
return this._featuresPicked;
|
}
|
},
|
/**
|
* Gets a value indicating whether or not the provider is ready for use.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Boolean}
|
* @readonly
|
*/
|
ready: {
|
get: function () {
|
return this._ready;
|
}
|
},
|
|
/**
|
* Gets a promise that resolves to true when the provider is ready for use.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Promise.<Boolean>}
|
* @readonly
|
*/
|
readyPromise: {
|
get: function () {
|
return this._readyPromise;
|
}
|
},
|
|
/**
|
* Gets the credit to display when this imagery provider is active. Typically this is used to credit
|
* the source of the imagery. This function should not be called before {@link Cesium.VectorTileImageryProvider#ready} returns true.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Credit}
|
* @readonly
|
*/
|
credit: {
|
get: function () {
|
return undefined;
|
}
|
},
|
|
/**
|
* Gets a value indicating whether or not the images provided by this imagery provider
|
* include an alpha channel. If this property is false, an alpha channel, if present, will
|
* be ignored. If this property is true, any images without an alpha channel will be treated
|
* as if their alpha is 1.0 everywhere. When this property is false, memory usage
|
* and texture upload time are reduced.
|
* @memberof Cesium.VectorTileImageryProvider.prototype
|
* @type {Boolean}
|
* @readonly
|
*/
|
hasAlphaChannel: {
|
get: function () {
|
return true;
|
}
|
}
|
});
|
|
VectorTileImageryProvider.prototype._createCanvas = function () {
|
this._canvas = document.createElement("canvas");
|
this._canvas.width = this._tileWidth;
|
this._canvas.height = this._tileHeight;
|
this._context = this._canvas.getContext("2d");
|
if (this._defaultStyle.backgroundColor) {
|
this._context.fillStyle = this._defaultStyle.backgroundColor.toCssColorString();
|
this._context.fillRect(0, 0, this._canvas.width, this._canvas.height);
|
}
|
|
this._context.lineWidth = this._defaultStyle.lineWidth;
|
this._context.strokeStyle = this._defaultStyle.outlineColor.toCssColorString();// "rgb(255,255,0)";
|
this._context.fillStyle = this._defaultStyle.fillColor.toCssColorString();// "rgba(0,255,255,0.0)";
|
|
}
|
|
var isWorking = false;
|
//用当前瓦片(Tile)矩形裁剪geojson并返回裁剪结果
|
VectorTileImageryProvider.prototype._clipGeojson = function (rectangle) {
|
var that = this;
|
var bbox = [Cesium.Math.toDegrees(rectangle.west),
|
Cesium.Math.toDegrees(rectangle.south),
|
Cesium.Math.toDegrees(rectangle.east),
|
Cesium.Math.toDegrees(rectangle.north)];
|
|
var polygonBBox = turf.polygon([[
|
[bbox[0], bbox[1]],//sw
|
[bbox[2], bbox[1]],//se
|
[bbox[2], bbox[3]],//ne
|
[bbox[0], bbox[3]],//nw
|
[bbox[0], bbox[1]],//sw
|
]]);
|
//poly = turf.featureCollection([poly]);
|
|
//var polygonBBox = turf.bboxPolygon(bbox);
|
// turf.polygon([[
|
// [bbox[0], bbox[1]],//sw
|
// [bbox[2], bbox[1]],//se
|
// [bbox[2], bbox[3]],//ne
|
// [bbox[0], bbox[3]],//nw
|
// [bbox[0], bbox[1]],//sw
|
//]]);
|
var pointsBBox = [
|
[bbox[0], bbox[1]],
|
[bbox[2], bbox[1]],
|
[bbox[2], bbox[3]],
|
[bbox[0], bbox[3]],
|
[bbox[0], bbox[1]]
|
];
|
for (var i = 0; i < pointsBBox.length; i++) {
|
var point = turf.point(pointsBBox[i]);
|
pointsBBox[i] = point;
|
}
|
pointsBBox = turf.featureCollection(pointsBBox);
|
|
|
var features = [];
|
if (this._pointGeoJSON) {
|
//为了避免出现在边界的文字只画到一半,同时把周边切片包含的点也放在本切片绘制
|
var lonW = (bbox[2] - bbox[0]) / 2, latH = (bbox[3] - bbox[1]) / 2;
|
var polygonBBox4Points =
|
//turf.bboxPolygon([
|
// bbox[0] - lonW,
|
// bbox[1] - latH,
|
// bbox[2] + lonW,
|
// bbox[3] + latH,
|
// ]);
|
turf.polygon([[
|
[bbox[0] - lonW, bbox[1] - latH],//sw
|
[bbox[2] + lonW, bbox[1] - latH],//se
|
[bbox[2] + lonW, bbox[3] + latH],//ne
|
[bbox[0] - lonW, bbox[3] + latH],//nw
|
[bbox[0] - lonW, bbox[1] - latH],//sw
|
]]);
|
var fcBBox = turf.featureCollection([polygonBBox4Points]);
|
var pts = turf.within(this._pointGeoJSON, fcBBox);
|
features = features.concat(pts.features);
|
}
|
var canClipGeojsons = [];
|
|
|
if (this._polygonJSON) {
|
canClipGeojsons.push(this._polygonJSON);
|
}
|
if (this._lineGeoJSON) {
|
canClipGeojsons.push(this._lineGeoJSON);
|
}
|
if (this._outlineGeoJSON) {
|
canClipGeojsons.push(this._outlineGeoJSON);
|
}
|
|
var clipped;
|
function clippedExists() {
|
var clippedCoords = turf.getCoords(clipped);
|
var exists = false;
|
for (var i = 0; i < features.length; i++) {
|
var keys1 = Object.keys(clipped.properties);
|
var keys2 = Object.keys(features[i].properties);
|
|
if (keys1.length != keys2.length) {
|
break;
|
}
|
var kEquals = true;
|
for (var k_i = 0; k_i < keys1.length; k_i++) {
|
if (keys1[k_i] != keys2[k_i]) {
|
kEquals = false;
|
break;
|
}
|
}
|
if (!kEquals) {
|
break;
|
}
|
kEquals = true;
|
for (var k_i = 0; k_i < keys1.length; k_i++) {
|
if (clipped.properties[keys1[k_i]] != features[i].properties[keys1[k_i]]) {
|
kEquals = false;
|
break;
|
}
|
}
|
if (!kEquals) {
|
break;
|
}
|
|
var tempCoords = turf.getCoords(features[i]);
|
|
if (clippedCoords.length && clippedCoords.length == tempCoords.length) {
|
var equals = true;
|
for (var j = 0; j < clippedCoords.length; j++) {
|
var c1 = clippedCoords[j], c2 = tempCoords[j];
|
if (!Cesium.isArray(c1[0])) {
|
try {
|
equals = c1[0] == c2[0] && c1[1] == c2[1];
|
} catch (e) {
|
console.log(e)
|
}
|
|
} else if (c1.length == c2.length) {
|
for (var k = 0; k < c1.length; k++) {
|
|
if (c1[k][0] != c2[k][0] || c1[k][1] != c2[k][1]) {
|
equals = false;
|
break;
|
}
|
}
|
|
} else {
|
equals = false;
|
break;
|
}
|
if (equals) {
|
break;
|
}
|
}
|
if (equals) {
|
exists = true;
|
break;
|
}
|
}
|
|
}
|
|
return exists;
|
}
|
|
canClipGeojsons.forEach(function (geojson) {
|
turf.featureEach(geojson, function (currentFeature, currentIndex) {
|
|
clipped = null;
|
try {
|
//if (currentFeature.geometry.type == "Polygon"
|
// || currentFeature.geometry.type == "MultiPolygon") {
|
// //var fcs = turf.featureCollection([currentFeature]);
|
// //if (!turf.within(pointsBBox, fcs))
|
// clipped = turf.intersect(currentFeature, polygonBBox);
|
// //else
|
// // clipped = polygonBBox;
|
// //fcs = null;
|
//}
|
if (!clipped) {
|
clipped = turf.bboxClip(currentFeature, bbox);
|
}
|
if (clipped && clipped.geometry.coordinates.length > 0) {
|
var empty = true;
|
for (var i = 0; i < clipped.geometry.coordinates.length; i++) {
|
if (clipped.geometry.coordinates[i].length > 0) {
|
empty = false;
|
break;
|
}
|
}
|
if (!empty) {
|
|
// if (!clippedExists()) {
|
features.push(clipped);
|
//}
|
} else {
|
//clipped = turf.intersect(currentFeature, polygonBBox);
|
//if (clipped) {
|
// features.push(clipped);
|
//}
|
//var fcs = turf.featureCollection([currentFeature]);
|
//if (turf.within(pointsBBox, fcs)) {
|
// features.push(polygonBBox);
|
//}
|
//fcs = null;
|
}
|
|
}
|
} catch (e) {
|
var coordinates = [];
|
currentFeature.geometry.coordinates.forEach(function (contour) {
|
if (contour.length > 3) {
|
coordinates.push(contour);
|
}
|
})
|
currentFeature.geometry.coordinates = coordinates;
|
clipped = turf.bboxClip(currentFeature, bbox);
|
if (clipped && clipped.geometry.coordinates.length > 0) {
|
|
//if (!clippedExists()) {
|
features.push(clipped);
|
//}
|
}
|
}
|
})
|
})
|
clipped = null;
|
if (features.length > 0) {
|
|
features = turf.featureCollection(features);
|
return features;
|
}
|
return null;
|
}
|
|
/**
|
* 挖孔
|
* @param {any} context
|
* @param {any} projection
|
* @param {any} boundingRect
|
* @param {any} x
|
* @param {any} y
|
* @param {any} holes
|
*/
|
function createHoles(context, projection, boundingRect, x, y, holes) {
|
var tileCanvas = context.canvas;
|
var imgData = context.getImageData(0, 0, tileCanvas.width, tileCanvas.height);
|
|
var holeMaskCanvas = document.createElement("canvas");
|
holeMaskCanvas.width = tileCanvas.width;
|
holeMaskCanvas.height = tileCanvas.height;
|
var holeMaskCtx = holeMaskCanvas.getContext("2d");
|
|
var mask = [];
|
holes.map(function (hole) {
|
holeMaskCtx.clearRect(0, 0, holeMaskCanvas.width, holeMaskCanvas.height);
|
holeMaskCtx.beginPath();
|
var pointIndex = 0;
|
hole.map(function (coordinate) {
|
var pt = projection.project(coordinate, boundingRect)
|
if (pointIndex == 0) {
|
holeMaskCtx.moveTo(x + pt.x, y + pt.y);
|
} else {
|
holeMaskCtx.lineTo(x + pt.x, y + pt.y);
|
}
|
pointIndex++;
|
})
|
holeMaskCtx.closePath();
|
|
|
holeMaskCtx.fillStyle = "rgba(255,255,255,1)";
|
holeMaskCtx.fill();
|
mask = holeMaskCtx.getImageData(0, 0, holeMaskCanvas.width, holeMaskCanvas.height).data;
|
for (var i = 3; i < mask.length; i += 4) {
|
if (mask[i] > 0) {
|
imgData.data[i] = 0;
|
}
|
}
|
|
});
|
context.putImageData(imgData, 0, 0);
|
}
|
|
//绘制多边形(面或线)
|
function drawContours(context, projection, boundingRect, x, y, contours, fill, stroke, style) {
|
|
var count = 0;
|
var holes = [];
|
contours.map(function (contour) {
|
if (!fill || count <= 0) {
|
var pointIndex = 0;
|
context.beginPath();
|
contour.map(function (coordinate) {
|
var pt = projection.project(coordinate, boundingRect)
|
if (pointIndex == 0) {
|
context.moveTo(x + pt.x, y + pt.y);
|
} else {
|
context.lineTo(x + pt.x, y + pt.y);
|
}
|
pointIndex++;
|
})
|
|
if (fill) {
|
context.closePath();
|
context.fill(); //context.stroke();
|
}
|
if (stroke) {
|
context.stroke();
|
}
|
|
} else {
|
holes.push(contour);
|
}
|
count++;
|
})
|
if (fill) {
|
return holes;
|
} else {
|
holes = null;
|
}
|
}
|
|
if (!Object.assign) {
|
Object.assign = function (target, source) {
|
var result = {};
|
for (var key in target) {
|
if (target.hasOwnProperty(key)) {
|
result[key] = target[key];
|
}
|
}
|
for (var key in source) {
|
if (source.hasOwnProperty(key)) {
|
result[key] = source[key];
|
}
|
}
|
return target;
|
}
|
}
|
|
//画点
|
function drawMarker(context, projection, boundingRect, x, y, pointFeature, fill, stroke, labelPropertyName, makerStyle) {
|
if (typeof labelPropertyName == 'undefined') {
|
labelPropertyName = "NAME";
|
}
|
|
var style = Object.assign({
|
pointSize: 3,
|
fontSize: 9,
|
fontFamily: 'courier',
|
color: 'rgb(0,0,0)',
|
backgroundColor: 'rgb(255,0,0)',
|
pointStyle: "Solid",//'Solid','Ring','Circle'
|
ringRadius: 2,
|
circleLineWidth: 1,
|
showMaker: true,
|
showLabel: true,
|
labelOffsetX: 0.0,
|
labelOffsetY: 0.0,
|
markerSymbol: undefined
|
}, makerStyle);
|
|
context.font = style.fontSize + 'px ' + style.fontFamily + ' bold'
|
|
var coordinate = pointFeature.geometry.coordinates
|
|
var percentX = (coordinate[0] - boundingRect.xMin) / (boundingRect.xMax - boundingRect.xMin);
|
var percentY = (coordinate[1] - boundingRect.yMax) / (boundingRect.yMin - boundingRect.yMax);
|
|
var pt = { x: percentX * context.canvas.width, y: percentY * context.canvas.height };
|
|
if (style.showMaker) {
|
|
var px = pt.x + x,
|
py = pt.y + y;
|
//if (px + style.pointSize > context.canvas.width) {
|
// px -= style.pointSize * 2;
|
//}
|
//if (px >= 0 && px - style.pointSize <= 0) {
|
// px += style.pointSize;
|
//}
|
|
//if (py + style.pointSize > context.canvas.width) {
|
// py -= style.pointSize * 2;
|
//}
|
//if (py >= 0 && py - style.pointSize <= 0) {
|
// py += style.pointSize;
|
//}
|
|
if (style.markerSymbol && style.markerSymbol instanceof Image) {
|
//if (px - style.markerSymbol.width / 2 < 0) {
|
// px += style.markerSymbol.width / 2;
|
//}
|
//if (py - style.markerSymbol.width / 2 < 0) {
|
// py += style.markerSymbol.width / 2;
|
//}
|
|
//if (px + style.markerSymbol.width / 2 > context.canvas.width) {
|
// px -= style.markerSymbol.width / 2;
|
//}
|
//if (py + style.markerSymbol.width / 2 > context.canvas.height) {
|
// py -= style.markerSymbol.width / 2;
|
//}
|
px -= style.markerSymbol.width / 2;
|
py -= style.markerSymbol.height / 2;
|
context.drawImage(style.markerSymbol, px, py);//, style.pointSize, style.pointSize);
|
|
} else {
|
px -= style.pointSize;
|
py -= style.pointSize;
|
context.fillStyle = style.backgroundColor
|
context.beginPath();
|
context.arc(px, py, style.pointSize, 0, Math.PI * 2);
|
if (style.pointStyle == 'Solid') {
|
context.fill();
|
}
|
else if (style.pointStyle == 'Circle') {
|
context.lineWidth = style.circleLineWidth;
|
context.strokeStyle = style.backgroundColor
|
context.stroke();
|
} else if (style.pointStyle == 'Ring') {
|
context.strokeStyle = style.backgroundColor
|
context.stroke();
|
context.beginPath();
|
context.arc(px, py, style.ringRadius, 0, Math.PI * 2);
|
context.closePath();
|
context.fill();
|
}
|
}
|
}
|
if (style.showLabel) {
|
if (typeof pointFeature.properties[labelPropertyName] === 'string') {
|
context.fillStyle = style.color;
|
var px = pt.x + x + style.labelOffsetX;//+ 4,
|
py = pt.y + y + style.labelOffsetY;// + style.fontSize / 2;
|
|
var text = pointFeature.properties[labelPropertyName];
|
if (text) {
|
text = text.trim();
|
var textImg = Cesium.writeTextToCanvas(text, {
|
fill: true,
|
font: style.fontSize + 'px ' + style.fontFamily,
|
stroke: style.labelStroke,
|
strokeWidth: style.labelStrokeWidth,
|
strokeColor: style.labelStrokeColor,
|
fillColor: Cesium.Color.fromCssColorString(style.color)
|
})
|
|
var textHeight = textImg.height;
|
var textWidth = textImg.width;//context.measureText(text).width;
|
px -= textWidth / 2 + style.pointSize;
|
py -= textHeight / 2 + style.pointSize;
|
//if (px + textWidth > context.canvas.width) {
|
// var delt = px + textWidth - context.canvas.width;
|
// px -= delt + style.pointSize;//(textWidth + style.pointSize + 6) / 2.0;
|
//} else if (px - textWidth / 2 < 0) {
|
// px = 0;
|
//} else {
|
// px -= textWidth / 2;
|
//}
|
|
//if (py + textHeight * 2.5 > context.canvas.height) {
|
// py = py - style.labelOffsetY - textHeight;
|
//} else if (py < textHeight * 1.8) {
|
// py = pt.y + textHeight / 2.0 - style.labelOffsetY;
|
//} else {
|
// py += textHeight / 2.0;
|
//}
|
|
//if (py + style.fontSize * 2.5 > context.canvas.height) {
|
// py = py - style.labelOffsetY - style.fontSize;
|
//} else if (py < style.fontSize * 1.8) {
|
// py = pt.y + style.fontSize / 2.0 - style.labelOffsetY;
|
//} else {
|
// py += style.fontSize / 2.0;
|
//}
|
context.drawImage(textImg, px, py)
|
//context.fillText(text, px, py);
|
}
|
}
|
}
|
context.restore();
|
}
|
|
/**
|
*
|
*@param {Number}x
|
*@param {Number}y
|
*@param {Object}geojson
|
*@param {Object}[boundingRect=undefined]
|
*@param {Number}width
|
*@param {Number}height
|
*@param {Object}[fill=true]
|
*@param {Object}[stroke=true]
|
*@private
|
*/
|
VectorTileImageryProvider.prototype._drawGeojson = function (context, x, y, geojson, boundingRect, width, height, fill, stroke, row, col, level) {
|
var that = this;
|
if (typeof fill == 'undefined') {
|
fill = true;
|
}
|
if (typeof stroke == 'undefined') {
|
stroke = true;
|
}
|
if (!fill && !stroke) {
|
return undefined;
|
}
|
if (typeof width == 'undefined') {
|
width = context.canvas.width - x;
|
}
|
if (typeof height == 'undefined') {
|
height = context.canvas.height - y;
|
}
|
|
var projection = new LonLatProjection(width, height);
|
|
var style = this._defaultStyle;
|
|
var makerStyle = {
|
labelStroke: style.labelStroke,
|
labelStrokeWidth: style.labelStrokeWidth,
|
labelStrokeColor: style.labelStrokeColor,
|
pointSize: style.pointSize,
|
fontSize: style.fontSize,
|
fontFamily: style.fontFamily,
|
color: style.fontColor.toCssColorString(),
|
backgroundColor: style.pointColor.toCssColorString(),
|
pointStyle: style.pointStyle,//'Solid','Ring','Circle'
|
ringRadius: style.ringRadius,
|
circleLineWidth: style.circleLineWidth,
|
showMaker: style.showMaker,
|
showLabel: style.showLabel,
|
labelOffsetX: style.labelOffsetX,
|
labelOffsetY: style.labelOffsetY,
|
markerSymbol: style.makerImage instanceof Image ? style.makerImage : style.makerImageEl
|
};
|
var holes = [];
|
if (that._styleFilter) {
|
turf.featureEach(geojson, function (currentFeature, currentFeatureIndex) {
|
if (that._styleFilter) {
|
style = that._defaultStyle.clone();
|
that._styleFilter(currentFeature, style, row, col, level);
|
currentFeature.style = style;
|
}
|
});
|
geojson.features.sort(function (a, b) {
|
if (a.style && a.style.lineDash) {
|
return 1;
|
}
|
if (b.style && b.style.lineDash) {
|
return -1;
|
}
|
return 0;
|
})
|
}
|
|
function drawFeature(currentFeature, currentFeatureIndex) {
|
|
if (that._styleFilter) {
|
style = currentFeature.style;
|
if (style.show == false) {
|
return;
|
}
|
|
makerStyle = {
|
labelStroke: style.labelStroke,
|
labelStrokeWidth: style.labelStrokeWidth,
|
labelStrokeColor: style.labelStrokeColor,
|
pointSize: style.pointSize,
|
fontSize: style.fontSize,
|
fontFamily: style.fontFamily,
|
color: style.fontColor.toCssColorString(),
|
backgroundColor: style.pointColor.toCssColorString(),
|
pointStyle: style.pointStyle,//'Solid','Ring','Circle'
|
ringRadius: style.ringRadius,
|
circleLineWidth: style.circleLineWidth,
|
showMaker: style.showMaker,
|
showLabel: style.showLabel,
|
labelOffsetX: style.labelOffsetX,
|
labelOffsetY: style.labelOffsetY,
|
markerSymbol: style.makerImage instanceof Image ? style.makerImage : style.makerImageEl
|
};
|
} else {
|
style = that._defaultStyle;
|
}
|
|
context.lineWidth = style.lineWidth;
|
context.strokeStyle = style.outlineColor.toCssColorString();// "rgb(255,255,0)";
|
context.fillStyle = style.fillColor.toCssColorString();// "rgba(0,255,255,0.0)";
|
if (style.lineDash) {
|
context.setLineDash(style.lineDash);
|
}
|
|
context.lineCap = style.lineCap;
|
if (style.shadowColor && style.shadowColor instanceof Cesium.Color) {
|
context.shadowColor = style.shadowColor.toCssColorString();
|
} else {
|
context.shadowColor = style.shadowColor;
|
}
|
context.shadowBlur = style.shadowBlur;
|
context.shadowOffsetX = style.shadowOffsetX;
|
context.shadowOffsetY = style.shadowOffsetY;
|
context.miterLimit = style.miterLimit;
|
context.lineJoin = style.lineJoin;
|
|
if (currentFeature.geometry.type == "Point") {
|
drawMarker(context, projection, boundingRect, x, y, currentFeature, fill, stroke, style.labelPropertyName, makerStyle);
|
}
|
else if (currentFeature.geometry.type == "Polygon" && style.fill) {
|
|
var contours = turf.getCoords(currentFeature);
|
var tempHoles = drawContours(context, projection, boundingRect, x, y, contours, true, false, style);
|
if (tempHoles) {
|
tempHoles.map(function (hole) {
|
hole.style = style;
|
holes.push(hole);
|
})
|
}
|
//drawContours(context, projection, boundingRect, x, y, contours, true, false, style);
|
} else if (currentFeature.geometry.type == "MultiPolygon" && style.fill) {
|
var polygons;
|
try {
|
|
polygons = turf.getCoords(currentFeature);
|
polygons.map(function (contours) {
|
var tempHoles = drawContours(context, projection, boundingRect, x, y, contours, true, false, style);
|
if (tempHoles) {
|
tempHoles.map(function (hole) {
|
hole.style = style;
|
holes.push(hole);
|
})
|
|
}
|
})
|
|
} catch (e) {
|
// console.log(e);
|
}
|
} else if (currentFeature.geometry.type == "MultiLineString") {
|
if (currentFeature.properties.isOutline && !style.outline) {
|
|
} else {
|
var contours = turf.getCoords(currentFeature);
|
drawContours(context, projection, boundingRect, x, y, contours, false, true, style);
|
contours = null;
|
}
|
|
}
|
else if (currentFeature.geometry.type == "LineString") {
|
if (currentFeature.properties.isOutline && !style.outline) {
|
|
} else {
|
var contour = turf.getCoords(currentFeature);
|
var contours = [contour]
|
drawContours(context, projection, boundingRect, x, y, contours, false, true, style);
|
contour = null;
|
contours = null;
|
|
}
|
}
|
}
|
|
turf.featureEach(geojson, function (fc, idx) {
|
if (fc.geometry.type == "Polygon" || fc.geometry.type == "MultiPolygon") {
|
drawFeature(fc, idx)
|
}
|
})
|
if (holes && holes.length) {
|
createHoles(context, projection, boundingRect, x, y, holes)
|
}
|
turf.featureEach(geojson, function (fc, idx) {
|
if (fc.geometry.type == "LineString" || fc.geometry.type == "MultiLineString") {
|
drawFeature(fc, idx)
|
}
|
})
|
turf.featureEach(geojson, function (fc, idx) {
|
if (fc.geometry.type == "Point" || fc.geometry.type == "MultiPoint") {
|
drawFeature(fc, idx)
|
}
|
})
|
|
}
|
|
VectorTileImageryProvider.prototype._createTileImage = function (x, y, level, rectangle, defer) {
|
|
var that = this;
|
var cacheId = x + "," + y + "," + level;
|
|
var boundingRect = {
|
xMin: Cesium.Math.toDegrees(rectangle.west),
|
yMin: Cesium.Math.toDegrees(rectangle.south),
|
xMax: Cesium.Math.toDegrees(rectangle.east),
|
yMax: Cesium.Math.toDegrees(rectangle.north)
|
};
|
this._state = VectorTileImageryProvider.State.CLIPPING;
|
Cesium.requestAnimationFrame(function () {
|
var clippedGeojson = that._clipGeojson(rectangle);
|
|
if (!clippedGeojson) {
|
if (that._onlyPoint) {
|
defer.resolve(getEmpty(that._defaultStyle.backgroundColor));
|
}
|
else {
|
defer.resolve(undefined);
|
}
|
that._state = VectorTileImageryProvider.State.COMPELTED;
|
VectorTileImageryProvider._currentTaskCount--;
|
} else {
|
|
Cesium.requestAnimationFrame(function () {
|
that._state = VectorTileImageryProvider.State.GEOJSONDRAWING;
|
that._createCanvas();
|
if (!that._defaultStyle.backgroundColor) {
|
that._context.clearRect(0, 0, that._canvas.width, that._canvas.height);
|
}
|
|
//if (level < 8) {
|
// var v = 1.5 / Math.pow(2, (level + 0));
|
// try {
|
// clippedGeojson = turf.simplify(clippedGeojson, v);
|
// } catch (e) {
|
|
// }
|
|
//}
|
|
that._drawGeojson(that._context, 0, 0, clippedGeojson, boundingRect, that._tileWidth, that._tileHeight, that._fill, that._outline, x, y, level);
|
|
that.cache[cacheId] = that._canvas;
|
that.cache[cacheId].srcJson = clippedGeojson;
|
that.cacheCount++;
|
VectorTileImageryProvider._currentTaskCount--;
|
|
defer.resolve(that._canvas);
|
|
Cesium.requestAnimationFrame(function () {
|
that._state = VectorTileImageryProvider.State.COMPELTED;
|
});
|
});
|
|
}
|
});
|
}
|
|
VectorTileImageryProvider.prototype._getTileImage = function (x, y, level, rectangle) {
|
|
var defer = Cesium.when.defer();
|
var that = this;
|
|
//从缓存中查询
|
var cacheId = x + "," + y + "," + level;
|
if (!that.cacheCount) {
|
that.cacheCount = 0;
|
}
|
if (!that.cache || that.cacheCount > that._tileCacheSize) {
|
for (var cacheId in that.cache) {
|
if (that.cache.hasOwnProperty(cacheId)) {
|
that.cache[cacheId].srcJson = null;
|
delete that.cache[cacheId];
|
}
|
}
|
that.cache = {};
|
that.cacheCount = 0;
|
}
|
if (that.cache[cacheId]) {
|
return that.cache[cacheId]
|
}
|
|
//处理并发
|
if (VectorTileImageryProvider._maxTaskCount < VectorTileImageryProvider._currentTaskCount) {
|
return undefined;
|
}
|
VectorTileImageryProvider._currentTaskCount++;
|
that._state = VectorTileImageryProvider.State.READY;
|
setTimeout(function () {
|
return that._createTileImage(x, y, level, rectangle, defer)
|
}, 1);
|
return defer;
|
}
|
|
var emptycv;
|
|
function getEmpty(bgColor) {
|
if (!emptycv) {
|
|
emptycv = document.createElement("canvas");
|
emptycv.width = 256;
|
emptycv.height = 256;
|
}
|
if (bgColor) {
|
var ctx = emptycv.getContex('2d');
|
ctx.fillStyle = bgColor.toCssColorString();
|
ctx.fillRect(0, 0, emptycv.width, emptycv.height);
|
}
|
return emptycv;
|
}
|
var scratchRectangleIntersection = new Cesium.Rectangle();
|
VectorTileImageryProvider.prototype.requestImage = function (x, y, level, distance) {
|
if (!this._ready || this._state != VectorTileImageryProvider.State.COMPELTED) {
|
return undefined;
|
}
|
if (level < this._minimumLevel) {
|
this._createCanvas();
|
this._context.clearRect(0, 0, this._tileWidth, this._tileHeight);
|
return this._canvas;
|
} else if (level > this._maximumLevel) {
|
return getEmpty(this._defaultStyle.backgroundColor)
|
}
|
var rectangle = this.tilingScheme.tileXYToRectangle(x, y, level);
|
return this._getTileImage(x, y, level, rectangle);
|
}
|
VectorTileImageryProvider.prototype.pickFeatures = function (x, y, level, longitude, latitude) {
|
//alert(longitude+","+ latitude);
|
}
|
|
|
|
var scratchRect = new Cesium.Rectangle();
|
/**
|
* 重写此函数,实现:要素被点击时准备好并返回要素查询结果信息。
|
* @param {Feature}feature geojson要素
|
* @param {Number}x 当前点所在tms瓦片编号x部分
|
* @param {Number}y 当前点所在tms瓦片编号y部分
|
* @param {Number}level 当前点所在tms瓦片级别
|
* @param {Number}longitude 当前点击的点经度(单位是弧度)
|
* @param {Number}latitude 当前点击的点纬度(单位是弧度)
|
* @return {Promise.<Cesium.ImageryLayerFeatureInfo>|Cesium.ImageryLayerFeatureInfo}
|
*/
|
VectorTileImageryProvider.prototype.prepareFeatureInfo = function (feature, x, y, level, longitude, latitude) {
|
return undefined;
|
}
|
/**
|
* 实现Cesium.ImageryProvidery要素查询(拾取)接口,除了返回结果可以在Cesium内置的InfoBox显示之外,还触发featuresPicked事件。
|
* @param {Number}x
|
* @param {Number}y
|
* @param {Number}level
|
* @param {Number}longitude
|
* @param {Number}latitude
|
*/
|
VectorTileImageryProvider.prototype.pickFeatures = function (x, y, level, longitude, latitude) {
|
if (!this._allowPick || !this._geoJSON) {
|
this._featuresPicked.raiseEvent(this, undefined);
|
return undefined;
|
}
|
this.tilingScheme.tileXYToRectangle(x, y, level, scratchRect);
|
var res = turf.radiansToLength(scratchRect.width / 256, 'kilometers');//分辨率,单位公里,即当前视图下一个像素点边长所表示距离
|
|
var pt = turf.point([Cesium.Math.toDegrees(longitude), Cesium.Math.toDegrees(latitude)]);
|
|
var pickedFeatures = [];
|
var style = this.defaultStyle;
|
var that = this;
|
turf.featureEach(this._geoJSON, function (fc) {
|
var srcFc = fc;
|
var found = false;
|
if (style.fill && (fc.geometry.type == 'Polygon' || fc.geometry.type == 'MultiPolygon')) {
|
// if (turf.pointInPolygon(pt, fc)) { //
|
if (turf.booleanPointInPolygon(pt, fc)) {
|
found = true;
|
}
|
} else {
|
var dist = turf.pointToFeatureDistance(pt, fc, {
|
units: "kilometers"
|
})
|
|
if ((style.outline && (fc.geometry.type == 'Polygon' || fc.geometry.type == 'MultiPolygon'))
|
|| (fc.geometry.type == "LineString" || fc.geometry.type == "MultiLineString")
|
) {
|
found = dist <= res * 2.0;
|
} else if (style.showMarker && (fc.geometry.type == 'Point' || fc.geometry.type == 'MultiPoint')) {
|
|
switch (style.pointStyle) {
|
case "Solid":
|
found = dist <= style.pointSize * 2.0;
|
break;
|
case "Ring":
|
case "Circle": found = dist <= (style.circleLineWidth + style.ringRadius) * 2.0;
|
break;
|
}
|
}
|
}
|
|
if (found) {//查找成功
|
var fcInfo;
|
if (typeof that.prepareFeatureInfo == 'function') {
|
fcInfo = that.prepareFeatureInfo(srcFc, x, y, level, longitude, latitude)
|
}
|
if (!fcInfo) {
|
var fcInfo = new Cesium.ImageryLayerFeatureInfo();
|
fcInfo.data = srcFc;
|
fcInfo.description = JSON.stringify(srcFc.properties, null, 2);
|
if (style.labelPropertyName) {
|
fcInfo.name = srcFc.properties[style.labelPropertyName]
|
}
|
else if (style.centerLabelPropertyName) {
|
fcInfo.name = srcFc.properties[style.centerLabelPropertyName]
|
}
|
|
if (srcFc.geometry.type == 'Point' || srcFc.geometry.type == 'MultiPoint') {
|
fcInfo.position = new Cesium.Cartographic(longitude, latitude)
|
} else {
|
var centroidPt = turf.centroid(srcFc);
|
var coord = turf.getCoords(centroidPt);
|
fcInfo.position = Cesium.Cartographic.fromDegrees(coord[0], coord[1])
|
}
|
}
|
pickedFeatures.push(fcInfo)
|
}
|
})
|
if (pickedFeatures.length) {
|
var df = Cesium.when.defer();
|
var startTime = new Date();
|
Cesium.when.all(pickedFeatures, function (pickedFeatures) {
|
var timespan = new Date() - startTime;
|
if (timespan < 100) {
|
setTimeout(function () {
|
that._featuresPicked.raiseEvent(that, pickedFeatures);
|
df.resolve(pickedFeatures);
|
}, 100);
|
} else {
|
that._featuresPicked.raiseEvent(that, pickedFeatures);
|
df.resolve(pickedFeatures);
|
}
|
}, function (err) {
|
console.error(err);
|
that._featuresPicked.raiseEvent(that, undefined);
|
})
|
return df.promise;
|
} else {
|
that._featuresPicked.raiseEvent(that, undefined);
|
}
|
}
|
/**
|
* @callback Cesium.VectorTileImageryProvider~featuresPickedCallback
|
* @param {Cesium.VectorTileImageryProvider}ImageryProvider
|
* @param {Array.<Cesium.ImageryLayerFeatureInfo>}pickedFeatures
|
*/
|
|
/**
|
*
|
*/
|
VectorTileImageryProvider.prototype.clearCache = function () {
|
for (var key in this.cache) {
|
if (this.cache.hasOwnProperty(key)) {
|
delete this.cache[key];
|
}
|
}
|
this.cache = {}
|
}
|
/**
|
*
|
*/
|
VectorTileImageryProvider.prototype.destroy = function () {
|
this.clearCache()
|
for (var key in this) {
|
if (this.hasOwnProperty(key)) {
|
delete this[key];
|
}
|
}
|
}
|
return VectorTileImageryProvider;
|
})
|