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