refactor(map): 迁移至 Cesium 模块化导入
parent
9f3bf572fd
commit
6c3cac4dc1
|
|
@ -1,3 +1,14 @@
|
||||||
|
const path = require("node:path");
|
||||||
|
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
|
||||||
|
const cesiumBuildPath = path.join(
|
||||||
|
path.dirname(require.resolve("cesium/package.json")),
|
||||||
|
"Build/Cesium",
|
||||||
|
);
|
||||||
|
const appIdentifier = "bi-h5";
|
||||||
|
const cesiumStaticPath = `${appIdentifier}/static/cesium`;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// 应用后端git地址,部署上线需要
|
// 应用后端git地址,部署上线需要
|
||||||
javaGit: "<git-url>",
|
javaGit: "<git-url>",
|
||||||
|
|
@ -9,7 +20,7 @@ module.exports = {
|
||||||
// 应用后端分支名称,部署上线需要
|
// 应用后端分支名称,部署上线需要
|
||||||
javaGitBranch: "<branch-name>",
|
javaGitBranch: "<branch-name>",
|
||||||
// 接口服务地址
|
// 接口服务地址
|
||||||
API_HOST: "https://gbs-gateway.qhdsafety.com",
|
API_HOST: "http://192.168.198.8:30140",
|
||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
// 应用后端分支名称,部署上线需要
|
// 应用后端分支名称,部署上线需要
|
||||||
|
|
@ -19,7 +30,7 @@ module.exports = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// 应用唯一标识符
|
// 应用唯一标识符
|
||||||
appIdentifier: "bi-h5",
|
appIdentifier,
|
||||||
// 应用上下文注入全局变量
|
// 应用上下文注入全局变量
|
||||||
contextInject: {
|
contextInject: {
|
||||||
// 应用Key
|
// 应用Key
|
||||||
|
|
@ -71,5 +82,16 @@ module.exports = {
|
||||||
// 自动注入编译后的文件到public/index.html中
|
// 自动注入编译后的文件到public/index.html中
|
||||||
inject: true,
|
inject: true,
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new CopyWebpackPlugin({
|
||||||
|
patterns: ["Assets", "ThirdParty", "Widgets", "Workers"].map(name => ({
|
||||||
|
from: path.join(cesiumBuildPath, name),
|
||||||
|
to: `${cesiumStaticPath}/${name}`,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
CESIUM_BASE_URL: JSON.stringify(`/${cesiumStaticPath}/`),
|
||||||
|
}),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"antd": "6.5.0",
|
"antd": "6.5.0",
|
||||||
"autofit.js": "^3.2.8",
|
"autofit.js": "^3.2.8",
|
||||||
|
"cesium": "1.144.0",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"echarts": "^6.0.0",
|
"echarts": "^6.0.0",
|
||||||
"immer": "^11.1.4",
|
"immer": "^11.1.4",
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,4 @@
|
||||||
<% const { root } = $element; %>
|
<% const { root } = $element; %>
|
||||||
<div id="<%= root.id %>" style="width: 100%; height: 100%; position: relative;overflow-y: auto;"></div>
|
<div id="<%= root.id %>" style="width: 100%; height: 100%; position: relative;overflow-y: auto;"></div>
|
||||||
</body>
|
</body>
|
||||||
<script src="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Cesium.js"></script>
|
|
||||||
<link href="https://cesium.com/downloads/cesiumjs/releases/1.91/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,13 @@
|
||||||
const Cesium = window.Cesium;
|
import {
|
||||||
|
Cartesian2,
|
||||||
|
Cartographic,
|
||||||
|
Cesium3DTileFeature,
|
||||||
|
Cesium3DTileset,
|
||||||
|
Math as CesiumMath,
|
||||||
|
EllipsoidTerrainProvider,
|
||||||
|
Model,
|
||||||
|
SceneTransforms,
|
||||||
|
} from "cesium";
|
||||||
|
|
||||||
export class Coord {
|
export class Coord {
|
||||||
viewer;
|
viewer;
|
||||||
|
|
@ -18,19 +27,19 @@ export class Coord {
|
||||||
if (!Number.isNaN(Number(i))) {
|
if (!Number.isNaN(Number(i))) {
|
||||||
const pick = picks[i];
|
const pick = picks[i];
|
||||||
isOn3dtiles
|
isOn3dtiles
|
||||||
= (pick && pick.primitive instanceof Cesium.Cesium3DTileFeature)
|
= (pick && pick.primitive instanceof Cesium3DTileFeature)
|
||||||
|| (pick && pick.primitive instanceof Cesium.Cesium3DTileset)
|
|| (pick && pick.primitive instanceof Cesium3DTileset)
|
||||||
|| (pick && pick.primitive instanceof Cesium.Model);
|
|| (pick && pick.primitive instanceof Model);
|
||||||
if (isOn3dtiles) {
|
if (isOn3dtiles) {
|
||||||
viewer.scene.pick(position);
|
viewer.scene.pick(position);
|
||||||
cartesian3 = viewer.scene.pickPosition(position);
|
cartesian3 = viewer.scene.pickPosition(position);
|
||||||
if (cartesian3) {
|
if (cartesian3) {
|
||||||
const cartographic
|
const cartographic
|
||||||
= Cesium.Cartographic.fromCartesian(cartesian3);
|
= Cartographic.fromCartesian(cartesian3);
|
||||||
if (cartographic.height < 0)
|
if (cartographic.height < 0)
|
||||||
cartographic.height = 0;
|
cartographic.height = 0;
|
||||||
const lon = Cesium.CesiumMath.toDegrees(cartographic.longitude);
|
const lon = CesiumMath.toDegrees(cartographic.longitude);
|
||||||
const lat = Cesium.CesiumMath.toDegrees(cartographic.latitude);
|
const lat = CesiumMath.toDegrees(cartographic.latitude);
|
||||||
const height = cartographic.height;
|
const height = cartographic.height;
|
||||||
cartesian3 = this.lnglatToCartesian3(lon, lat, height);
|
cartesian3 = this.lnglatToCartesian3(lon, lat, height);
|
||||||
return cartesian3;
|
return cartesian3;
|
||||||
|
|
@ -42,7 +51,7 @@ export class Coord {
|
||||||
// 不在模型上
|
// 不在模型上
|
||||||
if (!isOn3dtiles) {
|
if (!isOn3dtiles) {
|
||||||
const isTerrain
|
const isTerrain
|
||||||
= viewer.terrainProvider instanceof Cesium.EllipsoidTerrainProvider; // 是否存在地形
|
= viewer.terrainProvider instanceof EllipsoidTerrainProvider; // 是否存在地形
|
||||||
if (!isTerrain) {
|
if (!isTerrain) {
|
||||||
// 无地形
|
// 无地形
|
||||||
const ray = viewer.scene.camera.getPickRay(position);
|
const ray = viewer.scene.camera.getPickRay(position);
|
||||||
|
|
@ -80,7 +89,7 @@ export class Coord {
|
||||||
}
|
}
|
||||||
|
|
||||||
cartesian3ToCartesian2(cartesian3) {
|
cartesian3ToCartesian2(cartesian3) {
|
||||||
return Cesium.SceneTransforms.wgs84ToWindowCoordinates(
|
return SceneTransforms.worldToWindowCoordinates(
|
||||||
this.viewer.scene,
|
this.viewer.scene,
|
||||||
cartesian3,
|
cartesian3,
|
||||||
);
|
);
|
||||||
|
|
@ -92,7 +101,7 @@ export class Coord {
|
||||||
if (typeof extend === "undefined") {
|
if (typeof extend === "undefined") {
|
||||||
const coordToLonlat = (viewer, x, y) => {
|
const coordToLonlat = (viewer, x, y) => {
|
||||||
const { camera, scene } = viewer;
|
const { camera, scene } = viewer;
|
||||||
const d2 = new Cesium.Cartesian2(x, y);
|
const d2 = new Cartesian2(x, y);
|
||||||
const ellipsoid = scene.globe.ellipsoid;
|
const ellipsoid = scene.globe.ellipsoid;
|
||||||
// 2D转3D世界坐标
|
// 2D转3D世界坐标
|
||||||
const d3 = camera.pickEllipsoid(d2, ellipsoid);
|
const d3 = camera.pickEllipsoid(d2, ellipsoid);
|
||||||
|
|
@ -101,10 +110,10 @@ export class Coord {
|
||||||
const upperLeftCartographic
|
const upperLeftCartographic
|
||||||
= scene.globe.ellipsoid.cartesianToCartographic(d3);
|
= scene.globe.ellipsoid.cartesianToCartographic(d3);
|
||||||
// 弧度转经纬度
|
// 弧度转经纬度
|
||||||
const lon = Cesium.CesiumMath.toDegrees(
|
const lon = CesiumMath.toDegrees(
|
||||||
upperLeftCartographic.longitude,
|
upperLeftCartographic.longitude,
|
||||||
);
|
);
|
||||||
const lat = Cesium.CesiumMath.toDegrees(
|
const lat = CesiumMath.toDegrees(
|
||||||
upperLeftCartographic.latitude,
|
upperLeftCartographic.latitude,
|
||||||
);
|
);
|
||||||
return { lon, lat };
|
return { lon, lat };
|
||||||
|
|
@ -134,10 +143,10 @@ export class Coord {
|
||||||
else {
|
else {
|
||||||
// 三维视图
|
// 三维视图
|
||||||
bounds = [
|
bounds = [
|
||||||
Cesium.CesiumMath.toDegrees(extend.west),
|
CesiumMath.toDegrees(extend.west),
|
||||||
Cesium.CesiumMath.toDegrees(extend.south),
|
CesiumMath.toDegrees(extend.south),
|
||||||
Cesium.CesiumMath.toDegrees(extend.east),
|
CesiumMath.toDegrees(extend.east),
|
||||||
Cesium.CesiumMath.toDegrees(extend.north),
|
CesiumMath.toDegrees(extend.north),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
return bounds;
|
return bounds;
|
||||||
|
|
@ -168,8 +177,8 @@ export class Coord {
|
||||||
if (cartesian3) {
|
if (cartesian3) {
|
||||||
const radians
|
const radians
|
||||||
= this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
= this.viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian3);
|
||||||
const latitude = Cesium.CesiumMath.toDegrees(radians.latitude); // 弧度转度
|
const latitude = CesiumMath.toDegrees(radians.latitude); // 弧度转度
|
||||||
const longitude = Cesium.CesiumMath.toDegrees(radians.longitude);
|
const longitude = CesiumMath.toDegrees(radians.longitude);
|
||||||
const height = radians.height;
|
const height = radians.height;
|
||||||
return { longitude, latitude, height };
|
return { longitude, latitude, height };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import {
|
||||||
resetBottomUtilsMittKey,
|
resetBottomUtilsMittKey,
|
||||||
} from "./js/mittKey";
|
} from "./js/mittKey";
|
||||||
import useInitMap from "./js/useInitMap";
|
import useInitMap from "./js/useInitMap";
|
||||||
|
import "cesium/Build/Cesium/Widgets/widgets.css";
|
||||||
|
|
||||||
function Map(props) {
|
function Map(props) {
|
||||||
const query = useGetUrlQuery();
|
const query = useGetUrlQuery();
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,25 @@
|
||||||
|
import {
|
||||||
|
Cartesian3,
|
||||||
|
Cartographic,
|
||||||
|
Cesium3DTileset,
|
||||||
|
Math as CesiumMath,
|
||||||
|
createGuid,
|
||||||
|
CustomDataSource,
|
||||||
|
HeightReference,
|
||||||
|
HorizontalOrigin,
|
||||||
|
Matrix4,
|
||||||
|
VerticalOrigin,
|
||||||
|
} from "cesium";
|
||||||
import { getBillboardCanvases } from "./utils";
|
import { getBillboardCanvases } from "./utils";
|
||||||
|
|
||||||
const Cesium = window.Cesium;
|
// 接口经纬度可能以字符串返回,统一在 Cesium 坐标入口转换为数值。
|
||||||
|
|
||||||
// 获取经纬度
|
|
||||||
export const getPosition = (x, y, z = 0.0) => {
|
export const getPosition = (x, y, z = 0.0) => {
|
||||||
return Cesium.Cartesian3.fromDegrees(x, y, z);
|
return Cartesian3.fromDegrees(Number(x), Number(y), Number(z));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建倾斜摄影
|
// 创建倾斜摄影
|
||||||
export const createObliquePhotography = (url, viewer) => {
|
export const createObliquePhotography = async (url, viewer) => {
|
||||||
const tileset = new Cesium.Cesium3DTileset({
|
const tileset = await Cesium3DTileset.fromUrl(url, {
|
||||||
url,
|
|
||||||
skipLevelOfDetail: true,
|
skipLevelOfDetail: true,
|
||||||
baseScreenSpaceError: 1024,
|
baseScreenSpaceError: 1024,
|
||||||
maximumScreenSpaceError: 128, // 数值加大,能让最终成像变模糊
|
maximumScreenSpaceError: 128, // 数值加大,能让最终成像变模糊
|
||||||
|
|
@ -23,42 +32,32 @@ export const createObliquePhotography = (url, viewer) => {
|
||||||
cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
|
cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
|
||||||
preloadWhenHidden: true,
|
preloadWhenHidden: true,
|
||||||
preferLeaves: true,
|
preferLeaves: true,
|
||||||
maximumMemoryUsage: 128, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验
|
cacheBytes: 128 * 1024 * 1024, // 限制瓦片缓存,便于倾斜摄影数据及时回收。
|
||||||
progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
|
progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
|
||||||
dynamicScreenSpaceErrorDensity: 0.5, // 数值加大,能让周边加载变快
|
dynamicScreenSpaceErrorDensity: 0.5, // 数值加大,能让周边加载变快
|
||||||
dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先
|
dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先
|
||||||
dynamicScreenSpaceError: true, // 有了这个后,会在真正的全屏加载完之后才清晰化房屋
|
dynamicScreenSpaceError: true, // 有了这个后,会在真正的全屏加载完之后才清晰化房屋
|
||||||
});
|
});
|
||||||
|
|
||||||
tileset.readyPromise.then((tileset) => {
|
// 新版 Cesium 通过 fromUrl 完成异步初始化,解析完成后再计算模型偏移。
|
||||||
// 笛卡尔转换为弧度
|
const cartographic = Cartographic.fromCartesian(tileset.boundingSphere.center);
|
||||||
const cartographic = Cesium.Cartographic.fromCartesian(
|
const lng = CesiumMath.toDegrees(cartographic.longitude);
|
||||||
tileset.boundingSphere.center,
|
const lat = CesiumMath.toDegrees(cartographic.latitude);
|
||||||
);
|
const surface = Cartesian3.fromDegrees(lng, lat, 0);
|
||||||
const lng = Cesium.Math.toDegrees(cartographic.longitude); // 使用经纬度和弧度的转换,将WGS84弧度坐标系转换到目标值,弧度转度
|
const offset = Cartesian3.fromDegrees(lng, lat, 5);
|
||||||
const lat = Cesium.Math.toDegrees(cartographic.latitude);
|
const translation = Cartesian3.subtract(offset, surface, new Cartesian3());
|
||||||
// 计算中心点位置的地表坐标
|
tileset.modelMatrix = Matrix4.fromTranslation(translation);
|
||||||
const surface = Cesium.Cartesian3.fromDegrees(lng, lat, 0);
|
|
||||||
// 偏移后的坐标
|
|
||||||
const offset = Cesium.Cartesian3.fromDegrees(lng, lat, 5);
|
|
||||||
const translation = Cesium.Cartesian3.subtract(
|
|
||||||
offset,
|
|
||||||
surface,
|
|
||||||
new Cesium.Cartesian3(),
|
|
||||||
);
|
|
||||||
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
|
|
||||||
});
|
|
||||||
viewer.scene.primitives.add(tileset);
|
viewer.scene.primitives.add(tileset);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建唯一Id
|
// 创建唯一Id
|
||||||
export const createId = () => {
|
export const createId = () => {
|
||||||
return Cesium.createGuid();
|
return createGuid();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建数据源
|
// 创建数据源
|
||||||
export const createEntityCollection = (name) => {
|
export const createEntityCollection = (name) => {
|
||||||
return new Cesium.CustomDataSource(`${name}_${createId()}`);
|
return new CustomDataSource(`${name}_${createId()}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建 billboard
|
// 创建 billboard
|
||||||
|
|
@ -68,17 +67,24 @@ export const getBillboard = async ({ image, name = "" }) => {
|
||||||
image: base64,
|
image: base64,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
verticalOrigin: VerticalOrigin.BOTTOM,
|
||||||
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
|
horizontalOrigin: HorizontalOrigin.CENTER,
|
||||||
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
|
heightReference: HeightReference.CLAMP_TO_GROUND,
|
||||||
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
disableDepthTestDistance: Number.POSITIVE_INFINITY,
|
||||||
clampToGround: true,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DataSourceCollection 仅通过公开的 length/get 接口遍历,避免依赖内部数组结构。
|
||||||
|
const getDataSources = (viewer) => {
|
||||||
|
return Array.from(
|
||||||
|
{ length: viewer.dataSources.length },
|
||||||
|
(_, index) => viewer.dataSources.get(index),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// 移除数据源
|
// 移除数据源
|
||||||
export const removeEntityCollection = (viewer, name) => {
|
export const removeEntityCollection = (viewer, name) => {
|
||||||
viewer.dataSources._dataSources
|
getDataSources(viewer)
|
||||||
.filter(ds => ds.name.startsWith(`${name}_`))
|
.filter(ds => ds.name.startsWith(`${name}_`))
|
||||||
.forEach((item) => {
|
.forEach((item) => {
|
||||||
viewer.dataSources.remove(item);
|
viewer.dataSources.remove(item);
|
||||||
|
|
@ -88,7 +94,7 @@ export const removeEntityCollection = (viewer, name) => {
|
||||||
// 合并数据源
|
// 合并数据源
|
||||||
export const createMergedEntityCollection = (viewer, name) => {
|
export const createMergedEntityCollection = (viewer, name) => {
|
||||||
const mergedDataSource = createEntityCollection(name);
|
const mergedDataSource = createEntityCollection(name);
|
||||||
viewer.dataSources._dataSources
|
getDataSources(viewer)
|
||||||
.filter(ds =>
|
.filter(ds =>
|
||||||
ds.name.startsWith(`${name.substring(0, name.indexOf("Merged"))}_`),
|
ds.name.startsWith(`${name.substring(0, name.indexOf("Merged"))}_`),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,81 +1,28 @@
|
||||||
const Cesium = window.Cesium;
|
import { Material } from "cesium";
|
||||||
|
|
||||||
function TrajectoryPolylineTrailLinkMaterialProperty(viewer) {
|
const materialSource = `
|
||||||
this.viewer = viewer;
|
|
||||||
this._definitionChanged = new Cesium.Event();
|
|
||||||
this._uTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperties(TrajectoryPolylineTrailLinkMaterialProperty.prototype, {
|
|
||||||
isConstant: {
|
|
||||||
get() {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
definitionChanged: {
|
|
||||||
get() {
|
|
||||||
return this._definitionChanged;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
uTime: Cesium.createPropertyDescriptor("uTime"),
|
|
||||||
});
|
|
||||||
|
|
||||||
TrajectoryPolylineTrailLinkMaterialProperty.prototype.getType = function () {
|
|
||||||
return "CustomMaterial";
|
|
||||||
};
|
|
||||||
|
|
||||||
TrajectoryPolylineTrailLinkMaterialProperty.prototype.getValue = function (
|
|
||||||
time,
|
|
||||||
result,
|
|
||||||
) {
|
|
||||||
if (!Cesium.defined(result)) {
|
|
||||||
result = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
this._uTime += 0.005;
|
|
||||||
if (this._uTime > 1.0) {
|
|
||||||
this._uTime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.uTime = this._uTime;
|
|
||||||
this.viewer.scene.requestRender();
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
TrajectoryPolylineTrailLinkMaterialProperty.prototype.equals = function (
|
|
||||||
other,
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
this === other
|
|
||||||
|| (other instanceof TrajectoryPolylineTrailLinkMaterialProperty
|
|
||||||
&& this._uTime === other._uTime)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Cesium.Material.CustomMaterialType = "CustomMaterial";
|
|
||||||
Cesium.Material.CustomMaterialSource = `
|
|
||||||
czm_material czm_getMaterial(czm_materialInput materialInput)
|
czm_material czm_getMaterial(czm_materialInput materialInput)
|
||||||
{
|
{
|
||||||
czm_material material = czm_getDefaultMaterial(materialInput);
|
czm_material material = czm_getDefaultMaterial(materialInput);
|
||||||
float progress = mod(1.0 - materialInput.st.s + uTime, 1.0);
|
float progress = mod(1.0 - materialInput.st.s + uTime, 1.0);
|
||||||
float head = smoothstep(0.95, 1.0, progress) * 2.0;
|
float head = smoothstep(0.95, 1.0, progress) * 2.0;
|
||||||
vec3 baseColor = vec3(1, 0, 0);
|
vec3 baseColor = vec3(1.0, 0.0, 0.0);
|
||||||
float tailFade = smoothstep(0.3, 0.0, progress);
|
float tailFade = smoothstep(0.3, 0.0, progress);
|
||||||
vec3 tailColor = mix(vec3(0), vec3(1), tailFade);
|
vec3 tailColor = mix(vec3(0.0), vec3(1.0), tailFade);
|
||||||
material.diffuse = baseColor + tailColor * 0.8 + vec3(head);
|
material.diffuse = baseColor + tailColor * 0.8 + vec3(head);
|
||||||
material.emission = material.diffuse * 0.5;
|
material.emission = material.diffuse * 0.5;
|
||||||
|
material.alpha = 1.0;
|
||||||
return material;
|
return material;
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
Cesium.Material._materialCache.addMaterial(Cesium.Material.CustomMaterialType, {
|
// Primitive 可以直接使用 Fabric 材质,无需向 Cesium 私有材质缓存注册类型。
|
||||||
|
export default function createTrajectoryPolylineTrailMaterial() {
|
||||||
|
return new Material({
|
||||||
fabric: {
|
fabric: {
|
||||||
type: Cesium.Material.CustomMaterialType,
|
|
||||||
uniforms: {
|
uniforms: {
|
||||||
uTime: 0,
|
uTime: 0,
|
||||||
},
|
},
|
||||||
source: Cesium.Material.CustomMaterialSource,
|
source: materialSource,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
}
|
||||||
Cesium.TrajectoryPolylineTrailLinkMaterialProperty
|
|
||||||
= TrajectoryPolylineTrailLinkMaterialProperty;
|
|
||||||
|
|
|
||||||
|
|
@ -1,102 +1,32 @@
|
||||||
|
import { Color, Material } from "cesium";
|
||||||
import PolylineTrailLinkImage from "~/assets/images/map_bi/wall_img.png";
|
import PolylineTrailLinkImage from "~/assets/images/map_bi/wall_img.png";
|
||||||
|
|
||||||
const Cesium = window.Cesium;
|
const materialSource = `
|
||||||
|
czm_material czm_getMaterial(czm_materialInput materialInput)
|
||||||
|
{
|
||||||
|
czm_material material = czm_getDefaultMaterial(materialInput);
|
||||||
|
vec2 st = materialInput.st;
|
||||||
|
vec4 colorImage = texture(image, vec2(fract(st.t - time), st.t));
|
||||||
|
vec4 fragColor = czm_gammaCorrect(color);
|
||||||
|
material.alpha = colorImage.a * color.a;
|
||||||
|
material.diffuse = color.rgb;
|
||||||
|
material.emission = fragColor.rgb;
|
||||||
|
return material;
|
||||||
|
}`;
|
||||||
|
|
||||||
function WallPolylineTrailLinkMaterialProperty(
|
// Primitive 可以直接使用 Fabric 材质,无需向 Cesium 私有材质缓存注册类型。
|
||||||
viewer,
|
export default function createWallPolylineTrailMaterial(
|
||||||
options = {
|
color = Color.fromBytes(201, 118, 243).withAlpha(0.5),
|
||||||
color: Cesium.Color.fromBytes(201, 118, 243).withAlpha(0.5),
|
|
||||||
duration: 2000,
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
this.viewer = viewer;
|
return new Material({
|
||||||
this._definitionChanged = new Cesium.Event();
|
translucent: true,
|
||||||
this._color = undefined;
|
|
||||||
this._colorSubscription = undefined;
|
|
||||||
this.color = options.color;
|
|
||||||
this.duration = options.duration;
|
|
||||||
this._time = new Date().getTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperties(WallPolylineTrailLinkMaterialProperty.prototype, {
|
|
||||||
isConstant: {
|
|
||||||
get() {
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
definitionChanged: {
|
|
||||||
get() {
|
|
||||||
return this._definitionChanged;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
color: Cesium.createPropertyDescriptor("color"),
|
|
||||||
});
|
|
||||||
WallPolylineTrailLinkMaterialProperty.prototype.getType = function () {
|
|
||||||
return "PolylineTrailLink";
|
|
||||||
};
|
|
||||||
WallPolylineTrailLinkMaterialProperty.prototype.getValue = function (
|
|
||||||
time,
|
|
||||||
result,
|
|
||||||
) {
|
|
||||||
if (!Cesium.defined(result)) {
|
|
||||||
result = {};
|
|
||||||
}
|
|
||||||
result.color = Cesium.Property.getValueOrClonedDefault(
|
|
||||||
this._color,
|
|
||||||
time,
|
|
||||||
Cesium.Color.WHITE,
|
|
||||||
result.color,
|
|
||||||
);
|
|
||||||
result.image = Cesium.Material.PolylineTrailLinkImage;
|
|
||||||
|
|
||||||
if (this.duration) {
|
|
||||||
result.time
|
|
||||||
= ((new Date().getTime() - this._time) % this.duration) / this.duration;
|
|
||||||
}
|
|
||||||
this.viewer.scene.requestRender();
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
WallPolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
|
|
||||||
return (
|
|
||||||
this === other
|
|
||||||
|| (other instanceof WallPolylineTrailLinkMaterialProperty
|
|
||||||
&& Cesium.Property.equals(this._color, other._color))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Cesium.WallPolylineTrailLinkMaterialProperty
|
|
||||||
= WallPolylineTrailLinkMaterialProperty;
|
|
||||||
Cesium.Material.PolylineTrailLinkType = "PolylineTrailLink";
|
|
||||||
Cesium.Material.PolylineTrailLinkImage = PolylineTrailLinkImage;
|
|
||||||
Cesium.Material.PolylineTrailLinkSource = `czm_material czm_getMaterial(czm_materialInput
|
|
||||||
materialInput)\n\
|
|
||||||
{\n\
|
|
||||||
czm_material material =
|
|
||||||
czm_getDefaultMaterial(materialInput);\n\
|
|
||||||
vec2 st = materialInput.st;\n\
|
|
||||||
vec4 colorImage = texture2D(image,
|
|
||||||
vec2(fract(st.t - time), st.t));\n\
|
|
||||||
vec4 fragColor;\n\
|
|
||||||
fragColor.rgb = color.rgb / 1.0;\n\
|
|
||||||
fragColor = czm_gammaCorrect(fragColor);\n\
|
|
||||||
material.alpha = colorImage.a * color.a;\n\
|
|
||||||
material.diffuse = color.rgb;\n\
|
|
||||||
material.emission = fragColor.rgb;\n\
|
|
||||||
return material;\n\
|
|
||||||
}`;
|
|
||||||
Cesium.Material._materialCache.addMaterial(
|
|
||||||
Cesium.Material.PolylineTrailLinkType,
|
|
||||||
{
|
|
||||||
fabric: {
|
fabric: {
|
||||||
type: Cesium.Material.PolylineTrailLinkType,
|
|
||||||
uniforms: {
|
uniforms: {
|
||||||
color: new Cesium.Color(1.0, 1.0, 1.0, 1),
|
color,
|
||||||
image: Cesium.Material.PolylineTrailLinkImage,
|
image: PolylineTrailLinkImage,
|
||||||
time: 0,
|
time: 0,
|
||||||
},
|
},
|
||||||
source: Cesium.Material.PolylineTrailLinkSource,
|
source: materialSource,
|
||||||
},
|
},
|
||||||
translucent() {
|
});
|
||||||
return true;
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
|
import {
|
||||||
|
CameraEventType,
|
||||||
|
defined,
|
||||||
|
ImageryLayer,
|
||||||
|
ScreenSpaceEventHandler,
|
||||||
|
ScreenSpaceEventType,
|
||||||
|
Viewer,
|
||||||
|
WebMapTileServiceImageryProvider,
|
||||||
|
} from "cesium";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
import { createObliquePhotography } from "~/pages/Container/Map/js/mapUtils";
|
import { createObliquePhotography } from "~/pages/Container/Map/js/mapUtils";
|
||||||
|
|
||||||
import useMapMethods from "./useMapMethods";
|
import useMapMethods from "./useMapMethods";
|
||||||
import usePointClickEvent from "./usePointClickEvent";
|
import usePointClickEvent from "./usePointClickEvent";
|
||||||
|
|
||||||
const Cesium = window.Cesium;
|
|
||||||
|
|
||||||
export default function useInitMap(options) {
|
export default function useInitMap(options) {
|
||||||
// 页面和地图工具共用同一个 Cesium 引用,避免内外各维护一份实例。
|
// 页面和地图工具共用同一个 Cesium 引用,避免内外各维护一份实例。
|
||||||
const viewer = useRef(null);
|
const viewer = useRef(null);
|
||||||
|
|
@ -22,10 +29,11 @@ export default function useInitMap(options) {
|
||||||
const getViewer = () => viewer.current;
|
const getViewer = () => viewer.current;
|
||||||
|
|
||||||
// 倾斜摄影
|
// 倾斜摄影
|
||||||
|
// 当前按业务要求暂停初始化,保留入口以便服务恢复后重新启用。
|
||||||
|
|
||||||
const initObliquePhotography = () => {
|
const initObliquePhotography = () => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
viewer.scene.globe.depthTestAgainstTerrain = true;
|
viewer.scene.globe.depthTestAgainstTerrain = true;
|
||||||
Cesium.ExperimentalFeatures.enableModelExperimental = true;
|
|
||||||
createObliquePhotography(
|
createObliquePhotography(
|
||||||
"http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/merge_tile.json",
|
"http://192.168.192.215:8021/ware/upload/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/%E6%9B%B9%E5%A6%83%E7%94%B8%E6%B8%AF%E4%B8%9C/merge_tile.json",
|
||||||
viewer,
|
viewer,
|
||||||
|
|
@ -55,26 +63,36 @@ export default function useInitMap(options) {
|
||||||
// 注册点击事件
|
// 注册点击事件
|
||||||
const registerClickEvent = () => {
|
const registerClickEvent = () => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
|
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
|
||||||
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(ScreenSpaceEventType.LEFT_CLICK);
|
||||||
const screenSpaceEventHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
|
const screenSpaceEventHandler = new ScreenSpaceEventHandler(viewer.scene.canvas);
|
||||||
screenSpaceEventHandler.setInputAction((movement) => {
|
screenSpaceEventHandler.setInputAction((movement) => {
|
||||||
const pick = viewer.scene.pick(movement.position);
|
const pick = viewer.scene.pick(movement.position);
|
||||||
if (Cesium.defined(pick) && pick.id?.id) {
|
if (defined(pick) && pick.id?.id) {
|
||||||
pointClickEventRef.current.pointClickEvent(pick.id);
|
pointClickEventRef.current.pointClickEvent(pick.id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pointClickEventRef.current.closePopup();
|
pointClickEventRef.current.closePopup();
|
||||||
}
|
}
|
||||||
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
|
}, ScreenSpaceEventType.LEFT_CLICK);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 初始化地图
|
// 初始化地图
|
||||||
const initMap = () => {
|
const initMap = () => {
|
||||||
const tianDiTuKey = "06494bcf2d4b66df7f3c586cc65af0cb";
|
const tianDiTuKey = "06494bcf2d4b66df7f3c586cc65af0cb";
|
||||||
const subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
|
const subdomains = ["0", "1", "2", "3", "4", "5", "6", "7"];
|
||||||
viewer.current = new Cesium.Viewer("cesiumContainer", {
|
const imageryProvider = new WebMapTileServiceImageryProvider({
|
||||||
// terrainProvider: Cesium.createWorldTerrain()
|
// 影像底图
|
||||||
|
url:
|
||||||
|
`https://t{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${
|
||||||
|
tianDiTuKey}`,
|
||||||
|
subdomains,
|
||||||
|
layer: "tdtImgLayer",
|
||||||
|
style: "default",
|
||||||
|
format: "image/jpeg",
|
||||||
|
tileMatrixSetID: "GoogleMapsCompatible", // 使用谷歌的瓦片切片方式
|
||||||
|
});
|
||||||
|
viewer.current = new Viewer("cesiumContainer", {
|
||||||
animation: false, // 动画
|
animation: false, // 动画
|
||||||
homeButton: true, // home键
|
homeButton: true, // home键
|
||||||
geocoder: true, // 地址编码
|
geocoder: true, // 地址编码
|
||||||
|
|
@ -86,34 +104,23 @@ export default function useInitMap(options) {
|
||||||
navigationInstructionsInitiallyVisible: false, // 导航指令
|
navigationInstructionsInitiallyVisible: false, // 导航指令
|
||||||
navigationHelpButton: false, // 帮助信息
|
navigationHelpButton: false, // 帮助信息
|
||||||
selectionIndicator: false, // 选择
|
selectionIndicator: false, // 选择
|
||||||
imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
|
baseLayer: new ImageryLayer(imageryProvider),
|
||||||
// 影像底图
|
|
||||||
url:
|
|
||||||
`https://t{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=${
|
|
||||||
tianDiTuKey}`,
|
|
||||||
subdomains,
|
|
||||||
layer: "tdtImgLayer",
|
|
||||||
style: "default",
|
|
||||||
format: "image/jpeg",
|
|
||||||
tileMatrixSetID: "GoogleMapsCompatible", // 使用谷歌的瓦片切片方式
|
|
||||||
show: true,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
// 调整 Cesium 默认相机操作:左键旋转地图,右键调整俯仰角,实现从平面俯视到立体视角的切换。
|
// 调整 Cesium 默认相机操作:左键旋转地图,右键调整俯仰角,实现从平面俯视到立体视角的切换。
|
||||||
const cameraController = viewer.current.scene.screenSpaceCameraController;
|
const cameraController = viewer.current.scene.screenSpaceCameraController;
|
||||||
cameraController.rotateEventTypes = Cesium.CameraEventType.LEFT_DRAG;
|
cameraController.rotateEventTypes = CameraEventType.LEFT_DRAG;
|
||||||
cameraController.tiltEventTypes = [
|
cameraController.tiltEventTypes = [
|
||||||
Cesium.CameraEventType.RIGHT_DRAG,
|
CameraEventType.RIGHT_DRAG,
|
||||||
Cesium.CameraEventType.MIDDLE_DRAG,
|
CameraEventType.MIDDLE_DRAG,
|
||||||
Cesium.CameraEventType.PINCH,
|
CameraEventType.PINCH,
|
||||||
];
|
];
|
||||||
cameraController.zoomEventTypes = [
|
cameraController.zoomEventTypes = [
|
||||||
Cesium.CameraEventType.WHEEL,
|
CameraEventType.WHEEL,
|
||||||
Cesium.CameraEventType.PINCH,
|
CameraEventType.PINCH,
|
||||||
];
|
];
|
||||||
viewer.current._cesiumWidget._creditContainer.style.display = "none"; // 隐藏cesium ion
|
viewer.current.creditDisplay.container.style.display = "none"; // 隐藏 Cesium 版权信息容器
|
||||||
viewer.current.imageryLayers.addImageryProvider(
|
viewer.current.imageryLayers.addImageryProvider(
|
||||||
new Cesium.WebMapTileServiceImageryProvider({
|
new WebMapTileServiceImageryProvider({
|
||||||
// 影像注记
|
// 影像注记
|
||||||
url:
|
url:
|
||||||
`https://t{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=${
|
`https://t{s}.tianditu.gov.cn/cia_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cia&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default.jpg&tk=${
|
||||||
|
|
@ -123,7 +130,6 @@ export default function useInitMap(options) {
|
||||||
style: "default",
|
style: "default",
|
||||||
format: "image/jpeg",
|
format: "image/jpeg",
|
||||||
tileMatrixSetID: "GoogleMapsCompatible",
|
tileMatrixSetID: "GoogleMapsCompatible",
|
||||||
show: true,
|
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
initObliquePhotography();
|
initObliquePhotography();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,26 @@
|
||||||
|
import {
|
||||||
|
Cartesian3,
|
||||||
|
ClassificationType,
|
||||||
|
ClockRange,
|
||||||
|
Color,
|
||||||
|
defined,
|
||||||
|
Entity,
|
||||||
|
ExtrapolationType,
|
||||||
|
GeometryInstance,
|
||||||
|
GroundPolylineGeometry,
|
||||||
|
GroundPolylinePrimitive,
|
||||||
|
HeightReference,
|
||||||
|
HorizontalOrigin,
|
||||||
|
JulianDate,
|
||||||
|
MaterialAppearance,
|
||||||
|
PinBuilder,
|
||||||
|
PolylineMaterialAppearance,
|
||||||
|
Primitive,
|
||||||
|
SampledPositionProperty,
|
||||||
|
SceneMode,
|
||||||
|
VerticalOrigin,
|
||||||
|
WallGeometry,
|
||||||
|
} from "cesium";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
import portEntityBillboardImage from "~/assets/images/map_bi/point/dianwei.png";
|
import portEntityBillboardImage from "~/assets/images/map_bi/point/dianwei.png";
|
||||||
import branchOfficeEntityBillboardImage from "~/assets/images/map_bi/point/gongsidianwei.png";
|
import branchOfficeEntityBillboardImage from "~/assets/images/map_bi/point/gongsidianwei.png";
|
||||||
|
|
@ -17,11 +40,11 @@ import {
|
||||||
getPosition,
|
getPosition,
|
||||||
removeEntityCollection,
|
removeEntityCollection,
|
||||||
} from "./mapUtils";
|
} from "./mapUtils";
|
||||||
|
import createTrajectoryPolylineTrailMaterial from "./material/TrajectoryPolylineTrailLinkMaterialProperty";
|
||||||
|
import createWallPolylineTrailMaterial from "./material/WallPolylineTrailLinkMaterialProperty";
|
||||||
import mitt from "./mitt";
|
import mitt from "./mitt";
|
||||||
import { changeCoverMaskVisibleMittKey } from "./mittKey";
|
import { changeCoverMaskVisibleMittKey } from "./mittKey";
|
||||||
import { chunkedLoad, filterNull, formatPolygon } from "./utils";
|
import { chunkedLoad, filterNull, formatPolygon } from "./utils";
|
||||||
import "./material/TrajectoryPolylineTrailLinkMaterialProperty.js";
|
|
||||||
import "./material/WallPolylineTrailLinkMaterialProperty";
|
|
||||||
|
|
||||||
const portPoint = [
|
const portPoint = [
|
||||||
{
|
{
|
||||||
|
|
@ -64,8 +87,6 @@ const peopleImg = {
|
||||||
yellow: people_yellow,
|
yellow: people_yellow,
|
||||||
}; // 人员定位颜色图片
|
}; // 人员定位颜色图片
|
||||||
|
|
||||||
const Cesium = window.Cesium;
|
|
||||||
|
|
||||||
export default function useMapMethods(viewerRef, request) {
|
export default function useMapMethods(viewerRef, request) {
|
||||||
// 获取当前 Cesium 实例:初始化前为空,地图方法会在 initMap 完成后被调用。
|
// 获取当前 Cesium 实例:初始化前为空,地图方法会在 initMap 完成后被调用。
|
||||||
const getViewer = () => viewerRef.current;
|
const getViewer = () => viewerRef.current;
|
||||||
|
|
@ -97,6 +118,10 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
// 当前人员定位会话共用的采样起始时间
|
// 当前人员定位会话共用的采样起始时间
|
||||||
const peoplePositionStartTime = useRef(null);
|
const peoplePositionStartTime = useRef(null);
|
||||||
|
|
||||||
|
// Primitive 不属于 Entity/DataSource,单独保存实例和动画注销函数以便完整清理。
|
||||||
|
const wallPrimitivesRef = useRef([]);
|
||||||
|
const peopleTrajectoryPrimitiveRef = useRef(null);
|
||||||
|
|
||||||
// 设置中心点
|
// 设置中心点
|
||||||
const flyTo = ({ longitude, latitude, height } = defineCenterPoint) => {
|
const flyTo = ({ longitude, latitude, height } = defineCenterPoint) => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
|
|
@ -123,7 +148,7 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
// 切换场景模式
|
// 切换场景模式
|
||||||
const changeSceneMode = (type = "3d") => {
|
const changeSceneMode = (type = "3d") => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
viewer.scene.mode = { "2d": Cesium.SceneMode.COLUMBUS_VIEW, "3d": Cesium.SceneMode.SCENE3D }[type];
|
viewer.scene.mode = { "2d": SceneMode.COLUMBUS_VIEW, "3d": SceneMode.SCENE3D }[type];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 添加港口点
|
// 添加港口点
|
||||||
|
|
@ -133,7 +158,7 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
viewer.dataSources.add(entityCollection);
|
viewer.dataSources.add(entityCollection);
|
||||||
await chunkedLoad(portPoint, 50, async (item) => {
|
await chunkedLoad(portPoint, 50, async (item) => {
|
||||||
entityCollection.entities.add(
|
entityCollection.entities.add(
|
||||||
new Cesium.Entity({
|
new Entity({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
position: getPosition(item.position.x, item.position.y),
|
position: getPosition(item.position.x, item.position.y),
|
||||||
|
|
@ -171,7 +196,7 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
viewer.dataSources.add(entityCollection);
|
viewer.dataSources.add(entityCollection);
|
||||||
await chunkedLoad(branchOfficePoint, 50, async (item) => {
|
await chunkedLoad(branchOfficePoint, 50, async (item) => {
|
||||||
entityCollection.entities.add(
|
entityCollection.entities.add(
|
||||||
new Cesium.Entity({
|
new Entity({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
name: item.corpName,
|
name: item.corpName,
|
||||||
position: getPosition(item.longitude, item.latitude),
|
position: getPosition(item.longitude, item.latitude),
|
||||||
|
|
@ -232,15 +257,15 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
itemsToRender.forEach((item) => {
|
itemsToRender.forEach((item) => {
|
||||||
const latitudeAndLongitude = formatPolygon(item);
|
const latitudeAndLongitude = formatPolygon(item);
|
||||||
entityCollection.entities.add(
|
entityCollection.entities.add(
|
||||||
new Cesium.Entity({
|
new Entity({
|
||||||
id: createId(),
|
id: createId(),
|
||||||
polygon: {
|
polygon: {
|
||||||
hierarchy: Cesium.Cartesian3.fromDegreesArray(latitudeAndLongitude),
|
hierarchy: Cartesian3.fromDegreesArray(latitudeAndLongitude),
|
||||||
extrudedHeight: item.stretchHeight,
|
extrudedHeight: item.stretchHeight,
|
||||||
height: item.height,
|
height: item.height,
|
||||||
material: Cesium.Color.fromCssColorString(item.color),
|
material: Color.fromCssColorString(item.color),
|
||||||
outline: !!item.strokeColor,
|
outline: !!item.strokeColor,
|
||||||
outlineColor: Cesium.Color.fromCssColorString(item.strokeColor),
|
outlineColor: Color.fromCssColorString(item.strokeColor),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
@ -263,15 +288,15 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
viewer.dataSources.add(entityCollection);
|
viewer.dataSources.add(entityCollection);
|
||||||
areaList.forEach((area) => {
|
areaList.forEach((area) => {
|
||||||
entityCollection.entities.add(
|
entityCollection.entities.add(
|
||||||
new Cesium.Entity({
|
new Entity({
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name: area.closedAreaName,
|
name: area.closedAreaName,
|
||||||
polygon: {
|
polygon: {
|
||||||
hierarchy: Cesium.Cartesian3.fromDegreesArray(formatPolygon(area)),
|
hierarchy: Cartesian3.fromDegreesArray(formatPolygon(area)),
|
||||||
material: Cesium.Color.fromCssColorString("rgba(221,0,0,0.4)"),
|
material: Color.fromCssColorString("rgba(221,0,0,0.4)"),
|
||||||
outline: true,
|
outline: true,
|
||||||
outlineColor: Cesium.Color.fromCssColorString("rgba(51,35,108,0.63)"),
|
outlineColor: Color.fromCssColorString("rgba(51,35,108,0.63)"),
|
||||||
classificationType: Cesium.ClassificationType.BOTH,
|
classificationType: ClassificationType.BOTH,
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
@ -297,8 +322,6 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
mitt.emit(changeCoverMaskVisibleMittKey, true);
|
mitt.emit(changeCoverMaskVisibleMittKey, true);
|
||||||
const currentEdge = edgeMap[id]();
|
const currentEdge = edgeMap[id]();
|
||||||
const entityCollection = createEntityCollection("wallEntityCollection");
|
|
||||||
viewer.dataSources.add(entityCollection);
|
|
||||||
const wallList = currentEdge.wallList;
|
const wallList = currentEdge.wallList;
|
||||||
if (!Array.isArray(wallList))
|
if (!Array.isArray(wallList))
|
||||||
return;
|
return;
|
||||||
|
|
@ -306,25 +329,39 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
// 筛选需要渲染的边界墙
|
// 筛选需要渲染的边界墙
|
||||||
const itemsToRender = wallList.filter(item => !corpionId || item.corpinfoId === corpionId);
|
const itemsToRender = wallList.filter(item => !corpionId || item.corpinfoId === corpionId);
|
||||||
|
|
||||||
// 统一渲染
|
const geometryInstances = itemsToRender.map((item) => {
|
||||||
itemsToRender.forEach((item) => {
|
|
||||||
const latitudeAndLongitude = formatPolygon(item);
|
const latitudeAndLongitude = formatPolygon(item);
|
||||||
const positions
|
const positions = Cartesian3.fromDegreesArray(latitudeAndLongitude);
|
||||||
= Cesium.Cartesian3.fromDegreesArray(latitudeAndLongitude);
|
|
||||||
const pointCount = latitudeAndLongitude.length / 2;
|
const pointCount = latitudeAndLongitude.length / 2;
|
||||||
|
|
||||||
entityCollection.entities.add(
|
return new GeometryInstance({
|
||||||
new Cesium.Entity({
|
|
||||||
id: createId(),
|
id: createId(),
|
||||||
wall: {
|
geometry: new WallGeometry({
|
||||||
positions,
|
positions,
|
||||||
material: new Cesium.WallPolylineTrailLinkMaterialProperty(viewer),
|
|
||||||
maximumHeights: Array.from({ length: pointCount }).fill(40),
|
maximumHeights: Array.from({ length: pointCount }).fill(40),
|
||||||
minimumHeights: Array.from({ length: pointCount }).fill(0),
|
minimumHeights: Array.from({ length: pointCount }).fill(0),
|
||||||
},
|
vertexFormat: MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat,
|
||||||
}),
|
}),
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (geometryInstances.length) {
|
||||||
|
const material = createWallPolylineTrailMaterial();
|
||||||
|
const primitive = viewer.scene.primitives.add(new Primitive({
|
||||||
|
geometryInstances,
|
||||||
|
appearance: new MaterialAppearance({
|
||||||
|
material,
|
||||||
|
faceForward: true,
|
||||||
|
translucent: true,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
const startTime = Date.now();
|
||||||
|
const removeAnimation = viewer.scene.preUpdate.addEventListener(() => {
|
||||||
|
material.uniforms.time = ((Date.now() - startTime) % 2000) / 2000;
|
||||||
|
viewer.scene.requestRender();
|
||||||
|
});
|
||||||
|
wallPrimitivesRef.current.push({ primitive, removeAnimation });
|
||||||
|
}
|
||||||
|
|
||||||
mitt.emit(changeCoverMaskVisibleMittKey, false);
|
mitt.emit(changeCoverMaskVisibleMittKey, false);
|
||||||
};
|
};
|
||||||
|
|
@ -332,7 +369,11 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
// 删除墙
|
// 删除墙
|
||||||
const removeWall = () => {
|
const removeWall = () => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
removeEntityCollection(viewer, "wallEntityCollection");
|
wallPrimitivesRef.current.forEach(({ primitive, removeAnimation }) => {
|
||||||
|
removeAnimation();
|
||||||
|
viewer.scene.primitives.remove(primitive);
|
||||||
|
});
|
||||||
|
wallPrimitivesRef.current = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
// 点位聚合
|
// 点位聚合
|
||||||
|
|
@ -342,26 +383,26 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
dataSource.clustering.minimumClusterSize = 5; // 设置最小的聚合点数目,超过此数目才能聚合
|
dataSource.clustering.minimumClusterSize = 5; // 设置最小的聚合点数目,超过此数目才能聚合
|
||||||
let removeListener;
|
let removeListener;
|
||||||
// 按聚合层级创建对应图标
|
// 按聚合层级创建对应图标
|
||||||
const pinBuilder = new Cesium.PinBuilder();
|
const pinBuilder = new PinBuilder();
|
||||||
const pin100 = pinBuilder
|
const pin100 = pinBuilder
|
||||||
.fromText("100+", Cesium.Color.BLUE, 48)
|
.fromText("100+", Color.BLUE, 48)
|
||||||
.toDataURL();
|
.toDataURL();
|
||||||
const pin50 = pinBuilder.fromText("50+", Cesium.Color.BLUE, 48).toDataURL();
|
const pin50 = pinBuilder.fromText("50+", Color.BLUE, 48).toDataURL();
|
||||||
const pin40 = pinBuilder.fromText("40+", Cesium.Color.RED, 48).toDataURL();
|
const pin40 = pinBuilder.fromText("40+", Color.RED, 48).toDataURL();
|
||||||
const pin30 = pinBuilder.fromText("30+", Cesium.Color.RED, 48).toDataURL();
|
const pin30 = pinBuilder.fromText("30+", Color.RED, 48).toDataURL();
|
||||||
const pin20 = pinBuilder.fromText("20+", Cesium.Color.RED, 48).toDataURL();
|
const pin20 = pinBuilder.fromText("20+", Color.RED, 48).toDataURL();
|
||||||
const pin10 = pinBuilder.fromText("10+", Cesium.Color.RED, 48).toDataURL();
|
const pin10 = pinBuilder.fromText("10+", Color.RED, 48).toDataURL();
|
||||||
// 10以内聚合图标
|
// 10以内聚合图标
|
||||||
const singleDigitPins = Array.from({ length: 8 });
|
const singleDigitPins = Array.from({ length: 8 });
|
||||||
for (let i = 0; i < singleDigitPins.length; ++i) {
|
for (let i = 0; i < singleDigitPins.length; ++i) {
|
||||||
singleDigitPins[i] = pinBuilder
|
singleDigitPins[i] = pinBuilder
|
||||||
.fromText(`${i + 2}`, Cesium.Color.VIOLET, 48)
|
.fromText(`${i + 2}`, Color.VIOLET, 48)
|
||||||
.toDataURL();
|
.toDataURL();
|
||||||
}
|
}
|
||||||
customStyle();
|
customStyle();
|
||||||
|
|
||||||
function customStyle() {
|
function customStyle() {
|
||||||
if (Cesium.defined(removeListener)) {
|
if (defined(removeListener)) {
|
||||||
removeListener();
|
removeListener();
|
||||||
removeListener = undefined;
|
removeListener = undefined;
|
||||||
}
|
}
|
||||||
|
|
@ -371,10 +412,10 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
cluster.label.show = false;
|
cluster.label.show = false;
|
||||||
cluster.billboard.show = true;
|
cluster.billboard.show = true;
|
||||||
cluster.billboard.id = cluster.label.id;
|
cluster.billboard.id = cluster.label.id;
|
||||||
cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;
|
cluster.billboard.verticalOrigin = VerticalOrigin.BOTTOM;
|
||||||
cluster.billboard.horizontalOrigin = Cesium.HorizontalOrigin.CENTER;
|
cluster.billboard.horizontalOrigin = HorizontalOrigin.CENTER;
|
||||||
cluster.billboard.heightReference
|
cluster.billboard.heightReference
|
||||||
= Cesium.HeightReference.CLAMP_TO_GROUND;
|
= HeightReference.CLAMP_TO_GROUND;
|
||||||
cluster.billboard.disableDepthTestDistance
|
cluster.billboard.disableDepthTestDistance
|
||||||
= Number.POSITIVE_INFINITY;
|
= Number.POSITIVE_INFINITY;
|
||||||
const thresholdMap = [
|
const thresholdMap = [
|
||||||
|
|
@ -422,7 +463,7 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
await chunkedLoad(filterNull(pointList), 50, async (item) => {
|
await chunkedLoad(filterNull(pointList), 50, async (item) => {
|
||||||
const name = item[options.titleKey] || "";
|
const name = item[options.titleKey] || "";
|
||||||
entityCollection.entities.add(
|
entityCollection.entities.add(
|
||||||
new Cesium.Entity({
|
new Entity({
|
||||||
id: createId(),
|
id: createId(),
|
||||||
name,
|
name,
|
||||||
position: getPosition(item.longitude || item.lng, item.latitude || item.lat),
|
position: getPosition(item.longitude || item.lng, item.latitude || item.lat),
|
||||||
|
|
@ -456,7 +497,12 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
// 查询新轨迹前先移除旧轨迹,确保地图上始终只展示当前筛选结果。
|
// 查询新轨迹前先移除旧轨迹,确保地图上始终只展示当前筛选结果。
|
||||||
const removePeopleTrajectory = () => {
|
const removePeopleTrajectory = () => {
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
viewer.entities.removeById("peopleTrajectoryEntity");
|
const current = peopleTrajectoryPrimitiveRef.current;
|
||||||
|
if (!current)
|
||||||
|
return;
|
||||||
|
current.removeAnimation();
|
||||||
|
viewer.scene.primitives.remove(current.primitive);
|
||||||
|
peopleTrajectoryPrimitiveRef.current = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 将接口返回的经纬高点位绘制为动态轨迹线,少于两个点时不创建无意义的线段。
|
// 将接口返回的经纬高点位绘制为动态轨迹线,少于两个点时不创建无意义的线段。
|
||||||
|
|
@ -466,26 +512,34 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
const coordinates = points.flatMap(point => [point.lon, point.lat, point.alt || 0]);
|
const coordinates = points.flatMap(point => [Number(point.lon), Number(point.lat)]);
|
||||||
viewer.entities.add({
|
const material = createTrajectoryPolylineTrailMaterial();
|
||||||
id: "peopleTrajectoryEntity",
|
const primitive = viewer.scene.primitives.add(new GroundPolylinePrimitive({
|
||||||
polyline: {
|
geometryInstances: new GeometryInstance({
|
||||||
positions: Cesium.Cartesian3.fromDegreesArrayHeights(coordinates),
|
id: "peopleTrajectoryPrimitive",
|
||||||
|
geometry: new GroundPolylineGeometry({
|
||||||
|
positions: Cartesian3.fromDegreesArray(coordinates),
|
||||||
width: 5,
|
width: 5,
|
||||||
material: new Cesium.TrajectoryPolylineTrailLinkMaterialProperty(viewer),
|
}),
|
||||||
clampToGround: true,
|
}),
|
||||||
},
|
appearance: new PolylineMaterialAppearance({ material }),
|
||||||
|
}));
|
||||||
|
const startTime = Date.now();
|
||||||
|
const removeAnimation = viewer.scene.preUpdate.addEventListener(() => {
|
||||||
|
material.uniforms.uTime = ((Date.now() - startTime) % 3300) / 3300;
|
||||||
|
viewer.scene.requestRender();
|
||||||
});
|
});
|
||||||
|
peopleTrajectoryPrimitiveRef.current = { primitive, removeAnimation };
|
||||||
};
|
};
|
||||||
|
|
||||||
// 人员定位使用 Viewer 的全局时钟;每次开启定位仅初始化一次,避免首批点位互相重置时钟。
|
// 人员定位使用 Viewer 的全局时钟;每次开启定位仅初始化一次,避免首批点位互相重置时钟。
|
||||||
const initPeoplePositionClock = () => {
|
const initPeoplePositionClock = () => {
|
||||||
const start = Cesium.JulianDate.now();
|
const start = JulianDate.now();
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
peoplePositionStartTime.current = start;
|
peoplePositionStartTime.current = start;
|
||||||
viewer.clock.startTime = start.clone();
|
viewer.clock.startTime = start.clone();
|
||||||
viewer.clock.currentTime = start.clone();
|
viewer.clock.currentTime = start.clone();
|
||||||
viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;
|
viewer.clock.clockRange = ClockRange.CLAMPED;
|
||||||
viewer.clock.shouldAnimate = false;
|
viewer.clock.shouldAnimate = false;
|
||||||
return start;
|
return start;
|
||||||
};
|
};
|
||||||
|
|
@ -499,13 +553,13 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
throw new Error("请传入markType(扎点类型)");
|
throw new Error("请传入markType(扎点类型)");
|
||||||
const viewer = getViewer();
|
const viewer = getViewer();
|
||||||
const clonePoint = { ...point };
|
const clonePoint = { ...point };
|
||||||
point.property = new Cesium.SampledPositionProperty();
|
point.property = new SampledPositionProperty();
|
||||||
// 下一条实时定位到达前保持最后有效位置,避免全局时钟前进后点位短暂消失。
|
// 下一条实时定位到达前保持最后有效位置,避免全局时钟前进后点位短暂消失。
|
||||||
point.property.forwardExtrapolationType = Cesium.ExtrapolationType.HOLD;
|
point.property.forwardExtrapolationType = ExtrapolationType.HOLD;
|
||||||
point.property.forwardExtrapolationDuration = 0;
|
point.property.forwardExtrapolationDuration = 0;
|
||||||
// 首批人员必须共用同一采样起点,后续实体创建不会影响已存在人员的播放时间。
|
// 首批人员必须共用同一采样起点,后续实体创建不会影响已存在人员的播放时间。
|
||||||
const start = peoplePositionStartTime.current || initPeoplePositionClock();
|
const start = peoplePositionStartTime.current || initPeoplePositionClock();
|
||||||
const position = Cesium.Cartesian3.fromDegrees(point.x, point.y, 0);
|
const position = getPosition(point.x, point.y);
|
||||||
point.property.addSample(start, position);
|
point.property.addSample(start, position);
|
||||||
point.lastTime = start;
|
point.lastTime = start;
|
||||||
point.lastIconType = point.icon_type;
|
point.lastIconType = point.icon_type;
|
||||||
|
|
@ -542,11 +596,11 @@ export default function useMapMethods(viewerRef, request) {
|
||||||
).image;
|
).image;
|
||||||
point.lastIconType = point.icon_type;
|
point.lastIconType = point.icon_type;
|
||||||
}
|
}
|
||||||
const position = Cesium.Cartesian3.fromDegrees(point.x, point.y, 0);
|
const position = getPosition(point.x, point.y);
|
||||||
const nextTime = Cesium.JulianDate.addSeconds(
|
const nextTime = JulianDate.addSeconds(
|
||||||
point.lastTime,
|
point.lastTime,
|
||||||
10,
|
10,
|
||||||
new Cesium.JulianDate(),
|
new JulianDate(),
|
||||||
);
|
);
|
||||||
point.property.addSample(nextTime, position);
|
point.property.addSample(nextTime, position);
|
||||||
point.lastTime = nextTime;
|
point.lastTime = nextTime;
|
||||||
|
|
|
||||||
|
|
@ -55,8 +55,8 @@ export const closeWindow = () => {
|
||||||
window.close();
|
window.close();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!window.closed && !window.opener) {
|
if (!window.closed && !window.opener) {
|
||||||
window.location.href = "https://gbs-gateway.qhdsafety.com/";
|
// window.location.href = "https://gbs-gateway.qhdsafety.com/";
|
||||||
// window.location.href = "http://192.168.198.8:30140/";
|
window.location.href = "http://192.168.198.8:30140/";
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue