You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
425 lines
13 KiB
425 lines
13 KiB
import { reactive } from 'vue';
|
|
import * as SyCim from 'sy-cesium-sdk';
|
|
import { LayerTypeEnum } from '@/enums/projectEnum';
|
|
import { queryLayersByPos } from "@/utils/mapUtils";
|
|
import axios from 'axios';
|
|
import { throttle } from "lodash-es";
|
|
const clustering = reactive({
|
|
enabled: true,
|
|
pixelRange: 200,
|
|
minimumClusterSize: 5,
|
|
});
|
|
// import { getLayerStyle } from '@/api/project';
|
|
const createXyzLayer = (data: any) =>
|
|
new SyCim.XyzLayer(data.id, {
|
|
...data,
|
|
maximumLevel: data.maximumLevel || 22
|
|
});
|
|
|
|
const layerActions: Record<string, any> = {
|
|
'011100': (data: any) =>
|
|
new SyCim.BaiduLayer(data.id, {
|
|
...data,
|
|
style: data.layerTable,
|
|
crs: 'WGS84'
|
|
}),
|
|
'012000': (data: any) => new SyCim.PrimitiveLayer(data.id),
|
|
'013000': (data: any) => new SyCim.TilesetLayer(data.id),
|
|
'014000': createXyzLayer,
|
|
'021102': (data: any) =>
|
|
new SyCim.ArcgisDynamicLayer(data.id, {
|
|
url: data.url
|
|
}),
|
|
'030200': (data: any) =>
|
|
new SyCim.WmsLayer(data.id, {
|
|
...data,
|
|
url: data.url,
|
|
layer: data.layerTable,
|
|
parameters: {
|
|
version: '1.3.0'
|
|
}
|
|
}),
|
|
'030300': async (data: any) => {
|
|
const options: any = {
|
|
version: '2.0.0',
|
|
TYPENAMES: data.layerTable,
|
|
outputFormat: 'json'
|
|
};
|
|
// TODO: 后续获取真实数据
|
|
// if (data.relationStyleId) {
|
|
// const res = await getLayerStyle(data.relationStyleId);
|
|
// options.styleConfig = res.information ? JSON.parse(res.information) : '';
|
|
// }
|
|
return new SyCim.WfsLayer(data.id, data.url, data.layerTable, options);
|
|
},
|
|
'030100': (data: any) =>
|
|
new SyCim.WmtsLayer(data.id, {
|
|
...data,
|
|
url: data.url,
|
|
layer: data.layerTable,
|
|
tileMatrixSetID: data.tileMatrixSet,
|
|
style: data.style || ''
|
|
}),
|
|
'030400': async (data: any) => {
|
|
const options: any = {};
|
|
// TODO: 后续获取真实数据
|
|
// if (data.relationStyleId) {
|
|
// const res = await getLayerStyle(data.relationStyleId);
|
|
// options.styleConfig = res.information ? JSON.parse(res.information) : '';
|
|
// }
|
|
return new SyCim.GeoJsonLayer(data.id, data.url, options);
|
|
},
|
|
'040003': (data: any) =>
|
|
new SyCim.WfsLayer(data.id, data.url, data.layerTable, {
|
|
cql_filter: data.filter,
|
|
propertyName: '*'
|
|
}),
|
|
'050100': (data: any) => {
|
|
let url = `${data.proxyUrl}${data.url}`;
|
|
if (!url.includes('?tk=') && data.serviceToken) {
|
|
url = `${url}?tk=${data.serviceToken}`;
|
|
}
|
|
return new SyCim.TdtWmtsLayer(data.id, {
|
|
...data,
|
|
url,
|
|
layer: data.layerTable,
|
|
tileMatrixSetID: data.tileMatrixSet,
|
|
spatialReference: {
|
|
wkid: data.epsg
|
|
}
|
|
});
|
|
},
|
|
'060100': createXyzLayer,
|
|
'070100': (data: any) =>
|
|
new SyCim.BingMapLayer(data.id, {
|
|
...data
|
|
}),
|
|
'081100': (data: any) =>
|
|
// if (data.serviceToken) {
|
|
// new SyCim.SuperMapRestLayer(data.id, { url: data.url, k: data.serviceToken });
|
|
// } else {
|
|
// new SyCim.SuperMapRestLayer(data.id, {
|
|
// ...data
|
|
// });
|
|
// }
|
|
new SyCim.SuperMapRestLayer(data.id, { url: data.url, k: data.serviceToken })
|
|
};
|
|
|
|
export const getFeatures: any = (data: any, filter: '1=1') => {
|
|
return new Promise(async (resolve, reject) => {
|
|
const { url, serviceToken } = data;
|
|
let newUrl = decodeURI(url).split("maps/")[0].replace("map-", "data-");
|
|
const reg2 = /([^/]+)$/;
|
|
const decodeUrl: any = decodeURI(url);
|
|
const newLayerName: any = decodeUrl?.match?.(reg2)?.[1];
|
|
const l = newLayerName?.split("%40");
|
|
const datasourceName = `${l?.[1]}:${l?.[0]}`;
|
|
let queryUrl = `${newUrl}data/featureResults.geojson?returnContent=true`;
|
|
let params: any = {
|
|
getFeatureMode: 'SQL',
|
|
datasetNames: [datasourceName],
|
|
maxFeatures: 100000000,
|
|
queryParameter: {
|
|
attributeFilter: filter
|
|
}
|
|
};
|
|
if (serviceToken) {
|
|
params.k = serviceToken;
|
|
}
|
|
const result = await axios.post(
|
|
queryUrl,
|
|
JSON.stringify(params),
|
|
{
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
}
|
|
}
|
|
);
|
|
if (result?.data?.features?.length > 0) {
|
|
resolve(result.data);
|
|
} else {
|
|
resolve({
|
|
type: "FeatureCollection",
|
|
features: []
|
|
});
|
|
}
|
|
});
|
|
};
|
|
const defaultZoomToLayer = (data: any) => {
|
|
const { mapParam } = data;
|
|
if (!mapParam?.tileCenter) return;
|
|
const p = mapParam.tileCenter.split(',');
|
|
window.viewer.flyToPosition(new SyCim.Position(+p[0], +p[1], 500, 0, -90, 0));
|
|
};
|
|
const zoomToLayerByType = (data: any) => {
|
|
const { id, layerType } = data;
|
|
if (!layerType) return;
|
|
const type: any = SyCim.LayerType[LayerTypeEnum[layerType as never]];
|
|
const layer = window.viewer._layerCache[type][id];
|
|
|
|
if (layer?.zoomToLayer) {
|
|
layer.zoomToLayer();
|
|
} else {
|
|
defaultZoomToLayer(data);
|
|
}
|
|
};
|
|
|
|
const supermapLayer: any = {};
|
|
function zoomToS3MLayer(data: any) {
|
|
if (supermapLayer[data.id] && data.url) {
|
|
const resource: any = SyCim.Resource;
|
|
let requestScenesUrl = data.url + "/scenes.json";
|
|
if (data.serviceToken) {
|
|
requestScenesUrl = data.url + "/scenes.json?k=" + data.serviceToken;
|
|
}
|
|
resource.fetchJson(requestScenesUrl).then((scenes: any) => {
|
|
let sname = scenes && scenes[0].name;
|
|
let requestSceneUrl = data.url + "/scenes/" + sname + ".json";
|
|
if (data.serviceToken) {
|
|
requestSceneUrl =
|
|
data.url + "/scenes/" + sname + ".json?k=" + data.serviceToken;
|
|
}
|
|
resource.fetchJson(requestSceneUrl).then((jsonData: any) => {
|
|
const cameraPosition = jsonData.camera;
|
|
const tilt = SyCim.Math.toRadians(cameraPosition.tilt - 90);
|
|
//设置相机位置、视角,便于观察场景
|
|
window.viewer.scene.camera.setView({
|
|
destination: SyCim.Cartesian3.fromDegrees(
|
|
cameraPosition.longitude,
|
|
cameraPosition.latitude,
|
|
cameraPosition.altitude
|
|
),
|
|
orientation: {
|
|
heading: cameraPosition.heading,
|
|
pitch: tilt,
|
|
roll: 0
|
|
}
|
|
});
|
|
});
|
|
});
|
|
} else {
|
|
alert('请先加载s3m图层');
|
|
}
|
|
}
|
|
|
|
const zoomToLayerActions: Record<string, any> = {
|
|
'011100': zoomToLayerByType,
|
|
'012000': (data: any) => {
|
|
// modal
|
|
const { modelInitPosition } = data;
|
|
if (!modelInitPosition) return;
|
|
const p = JSON.parse(modelInitPosition);
|
|
window.viewer.flyToPosition(new SyCim.Position(p.lng, p.lat, p.alt + 500, 0, -90, 0));
|
|
},
|
|
'013000': zoomToLayerByType,
|
|
'014000': zoomToLayerByType,
|
|
'021102': zoomToLayerByType,
|
|
'030200': zoomToLayerByType,
|
|
'030300': zoomToLayerByType,
|
|
'030100': zoomToLayerByType,
|
|
'030400': zoomToLayerByType,
|
|
'040003': zoomToLayerByType,
|
|
'050100': zoomToLayerByType,
|
|
'060100': zoomToLayerByType,
|
|
'070100': zoomToLayerByType,
|
|
'080100': zoomToS3MLayer,
|
|
'081100': zoomToLayerByType
|
|
};
|
|
|
|
const baseLayerActions: Record<string, any> = {
|
|
// 百度
|
|
'011100': async (data: any) =>
|
|
await SyCim.ImageryLayerFactory.createImageryLayer(SyCim.ImageryType.BAIDU, {
|
|
...data,
|
|
style: data.layerTable,
|
|
crs: 'WGS84'
|
|
}),
|
|
// 天地图
|
|
'050100': async (data: any) => {
|
|
let url = `${data.proxyUrl}${data.url}`;
|
|
if (!url.includes('?tk=') && data.serviceToken) {
|
|
url = `${url}?tk=${data.serviceToken}`;
|
|
}
|
|
return await SyCim.ImageryLayerFactory.createImageryLayer(SyCim.ImageryType.TDTWMTS, {
|
|
...data,
|
|
url,
|
|
layer: data.layerTable,
|
|
tileMatrixSetID: data.tileMatrixSet,
|
|
spatialReference: {
|
|
wkid: data.epsg
|
|
}
|
|
});
|
|
},
|
|
// 必应影像
|
|
'070100': async (data: any) =>
|
|
await SyCim.ImageryLayerFactory.createImageryLayer(SyCim.ImageryType.BINGMAP, {
|
|
...data
|
|
}),
|
|
// 必应地图离线瓦片
|
|
'060100': async (data: any) =>
|
|
await SyCim.ImageryLayerFactory.createImageryLayer(SyCim.ImageryType.XYZ, {
|
|
...data,
|
|
maximumLevel: data.maximumLevel || 22
|
|
})
|
|
};
|
|
|
|
export function useLayer() {
|
|
const addLayer = async (layerData: any) => {
|
|
const { layerType, url, id, isNeedCluster } = layerData;
|
|
let action = null;
|
|
// 超图 S3M图层
|
|
if (layerType === '080100') {
|
|
if (supermapLayer[id]) {
|
|
supermapLayer[id].show = true;
|
|
} else {
|
|
const scene: any = window.viewer.scene;
|
|
let requestUrl = url;
|
|
if (layerData.serviceToken) {
|
|
requestUrl = url + "?k=" + layerData.serviceToken;
|
|
}
|
|
const layerPromise = scene.open(requestUrl, {
|
|
autoSetView: false //不自动定位
|
|
});
|
|
layerPromise.then((layer: any) => {
|
|
supermapLayer[id] = layer?.[0];
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
if (!layerType || !(action = layerActions[layerType as string])) return;
|
|
let layer: any = await action(layerData);
|
|
if (isNeedCluster === '1' && layerData.nameCn === "水库点") {
|
|
let baseUrl = import.meta.env.VITE_BASE_URL;
|
|
const data = await getFeatures(layerData);
|
|
if (data?.features?.[0]?.geometry?.type === 'Point') {
|
|
let layerConfig = {};
|
|
switch (layerData.nameCn) {
|
|
case "水库点":
|
|
layerConfig = {
|
|
isUniqueRender: true,
|
|
field: "ENG_SCAL",
|
|
fieldOptions: [
|
|
{ name: "1.0", attr: "image", value: "reservoir_big.png" },
|
|
{ name: "2.0", attr: "image", value: "reservoir_big.png" },
|
|
{ name: "3.0", attr: "image", value: "reservoir_normal.png" },
|
|
{ name: "4.0", attr: "image", value: "reservoir_small.png" },
|
|
{ name: "5.0", attr: "image", value: "reservoir_small.png" },
|
|
],
|
|
image: "map-title-o.png",
|
|
};
|
|
break;
|
|
}
|
|
layer = new SyCim.ClusterWfsLayer(layerData.id, {
|
|
data,
|
|
symbol: {
|
|
type: "billboardP",
|
|
imageProxy: `${baseUrl}/img/map/`, // 图片代理
|
|
style: {
|
|
clampToGround: false,
|
|
image: "reservoir_small.png",
|
|
...layerConfig,
|
|
},
|
|
},
|
|
clustering: {
|
|
enabled: clustering.enabled,
|
|
pixelRange: clustering.pixelRange,
|
|
minimumClusterSize: clustering.minimumClusterSize,
|
|
clusterEvent: undefined,
|
|
clusterColors: undefined, // 聚合点颜色
|
|
getImage: undefined, // 获取聚合图片的函数
|
|
},
|
|
});
|
|
}
|
|
}
|
|
layer && window.viewer.addLayer(layer);
|
|
if (['013000'].includes(layerType)) {
|
|
// 3d tiles
|
|
const tileset = new SyCim.Tileset(url);
|
|
tileset.id = layerData.id;
|
|
layer.addGraphic(tileset);
|
|
} else if (['012000'].includes(layerType)) {
|
|
// modal
|
|
if (!layerData.modelInitPosition) return;
|
|
const p = JSON.parse(layerData.modelInitPosition);
|
|
const model = new SyCim.ModelPrimitive(new SyCim.Position(p.lng, p.lat, p.alt, p.heading, p.pitch, p.roll), url);
|
|
model.id = layerData.id;
|
|
layer.addGraphic(model);
|
|
}
|
|
};
|
|
const removeLayer = (layerData: any) => {
|
|
const { id, layerType } = layerData;
|
|
if (!layerType) return;
|
|
const type: any = LayerTypeEnum[layerType as never];
|
|
|
|
if (layerType === '080100') {
|
|
if (supermapLayer[id]) {
|
|
supermapLayer[id].show = false;
|
|
}
|
|
} else {
|
|
window.viewer.removeLayer({
|
|
id,
|
|
type: SyCim.LayerType[type]
|
|
} as any);
|
|
}
|
|
};
|
|
const zoomToLayer = (data: any) => {
|
|
const { layerType } = data;
|
|
zoomToLayerActions[layerType as string]?.(data);
|
|
};
|
|
const viewerClick = throttle((e) => {
|
|
console.log(e);
|
|
}, 500);
|
|
const addViewerMouseClick = () => {
|
|
window.viewer?.on(SyCim.MouseEventType.MOUSE_MOVE, viewerClick);
|
|
};
|
|
const removeViewerMouseClick = () => {
|
|
window.viewer?.off(SyCim.MouseEventType.MOUSE_MOVE, viewerClick);
|
|
};
|
|
return {
|
|
addLayer,
|
|
removeLayer,
|
|
zoomToLayer,
|
|
addViewerMouseClick,
|
|
removeViewerMouseClick
|
|
};
|
|
}
|
|
|
|
export function useBaseLayer() {
|
|
const changeBaseLayer = (layerData: any) => {
|
|
if (!layerData.layerType || !baseLayerActions[layerData.layerType as string]) {
|
|
return;
|
|
}
|
|
const baseLayer = baseLayerActions[layerData.layerType as string](layerData);
|
|
window.viewer.addBaseLayer(baseLayer, {
|
|
id: layerData.id,
|
|
name: layerData.nameCn,
|
|
iconUrl: layerData.picture || '/WGS84.png'
|
|
});
|
|
window.viewer.changeBaseLayerById(layerData.id);
|
|
};
|
|
|
|
return {
|
|
changeBaseLayer
|
|
};
|
|
}
|
|
|
|
export function useTerrain() {
|
|
const changeTerrain = (terrainData: any) => {
|
|
if (terrainData.layerType === '014000') {
|
|
// 地形
|
|
const url = `${terrainData.proxyUrl}${terrainData.url}`;
|
|
const terrain = SyCim.TerrainFactory.createTerrain(SyCim.TerrainType.XYZ, {
|
|
...terrainData,
|
|
url
|
|
});
|
|
window.viewer.setTerrain(terrain);
|
|
}
|
|
};
|
|
const removeTerrain = () => {
|
|
window.viewer.removeTerrain();
|
|
};
|
|
return {
|
|
changeTerrain,
|
|
removeTerrain
|
|
};
|
|
}
|
|
|