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

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
};
}