Files
sdk4.0/src/Obj/Base/TrajectoryMotion/index.js

2573 lines
94 KiB
JavaScript
Raw Normal View History

2025-07-03 13:54:01 +08:00
import Dialog from '../../Element/Dialog';
import EventBinding from '../../Element/Dialog/eventBinding';
import { html } from "./_element";
import Base from "../index";
import MouseEvent from '../../../Event/index'
import EditGltf from "../../ModelController/EditGltf";
import Controller from "../../../Controller/index";
import MouseTip from '../../../MouseTip'
import LabelObject from '../LabelObject'
import { setActiveViewer, CameraController, closeRotateAround } from '../../../Global/global'
import { syncData, get2DView, get3DView } from '../../../Global/MultiViewportMode'
import { legp } from '../../../Obj/Element/datalist';
import { getFontList, getFontFamilyName } from '../../Element/fontSelect'
import { setSplitDirection, syncSplitData, setActiveId, getSdk } from '../../../Global/SplitScreen'
class TrajectoryMotion extends Base {
#timeoutEventObject = null
#lineEdit = false
#_requestAnimationFrameEventId
#_requestAnimationFrameEventId2
#mouseRightevent
#firstPersonViewEvent
/**
* @constructor
* @description 轨迹运动
* @param options {object}
* @param options.name {string} 名称
* @param options.speed=1 {number} 运行速度
* @param options.delay=0 {number} 运动延迟时间(毫秒)
* @param options.loop=true {boolean} 循环
* @param options.height {number} 起始点高度
* @param options.ground=false {boolean} 贴地
* @param options.state=true {boolean} 模型运动
* @param options.routeDirection=true {boolean} 路径方向
* @param options.viewFollow=false {boolean} 视角跟随
* @param options.model {object} 模型参数
* @param options.model.show=true {boolean} 模型显隐
* @param options.model.url {url} 模型地址
* @param options.model.pixelSize=70 {number} 模型像素大小
* @param options.model.heading=0 {number}
* @param options.model.pitch=0 {number}
* @param options.model.roll=0 {number}
* @param options.model.scale=1 {number} 模型比例
* @param options.model.animate {string} 模型动画
* @param options.line {object} 路径参数
* @param options.line.show=true {boolean} 路径显隐
* @param options.line.smooth=false {boolean} 路径圆滑
* @param options.line.noseToTail=false {boolean} 路径收尾相联
* @param {Array.<object>} options.line.positions 经纬度和高度的列表值交替 [{lon,lat,alt},...]
* @param _Dialog {object} 弹框事件
* @param _Dialog.confirmCallBack {function} 弹框确认时的回调
* */
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options);
this.options.name = options.name || ''
this.options.show = (options.show || options.show === false) ? options.show : true
this.options.speed = (options.speed || options.speed === 0) ? options.speed : 1
if (this.options.speed <= 0) {
this.options.speed = 0.01
}
this.options.delay = options.delay || 0
this.options.loop = options.loop || options.loop === false ? options.loop : true
this.options.model = options.model = options.model || {}
this.options.line = options.line = options.line || {}
this.options.line.positions = options.line.positions || []
// this.options.height = (options.height || options.height === 0) ? options.height : (this.options.line.positions[0] ? this.options.line.positions[0].alt : 0)
this.options.height = this.options.line.positions[0] ? this.options.line.positions[0].alt : 0
this.options.height = Number(this.options.height.toFixed(2))
this.options.line.show = options.line.show || options.line.show === false ? options.line.show : true
this.options.model.show = options.model.show || options.model.show === false ? options.model.show : true
this.options.model.url = options.model.url || ''
this.options.model.pixelSize = options.model.pixelSize || 70
this.options.model.heading = options.model.heading || 0
this.options.model.pitch = options.model.pitch || 0
this.options.model.roll = options.model.roll || 0
this.options.model.scale = (options.model.scale || options.model.scale === 0) ? options.model.scale : 1
this.options.model.animate = options.model.animate || '无'
this.options.line.smooth = options.line.smooth ? options.line.smooth : false
this.options.line.noseToTail = options.line.noseToTail ? options.line.noseToTail : false
this.positions_smooth = []
2025-08-21 16:37:49 +08:00
this.options.unitFuelConsumption = options.unitFuelConsumption || 0
2025-07-03 13:54:01 +08:00
this.options.ground = options.ground || false
this.options.state = (options.state || options.state === false) ? options.state : true
this.options.routeDirection = (options.routeDirection || options.routeDirection === false) ? options.routeDirection : true
this.keyPoints = []
this.realTimePositions = []
this._elms = {};
this.Dialog = _Dialog
this.realTimeRouteArray = []
// this.options.firstPerson = false
this.distance
// this.addModel()
options.label = options.label || {}
this.options.label = {
text: this.options.name,
show: options.label.show || false,
fontSize: (options.label.fontSize || options.label.fontSize === 0) ? options.label.fontSize : 20,
fontFamily: options.label.fontFamily ? options.label.fontFamily : 0,
color: options.label.color || '#ffffff',
lineWidth: (options.label.lineWidth || options.label.lineWidth === 0) ? options.label.lineWidth : 4,
pixelOffset: (options.label.pixelOffset || options.label.pixelOffset === 0) ? options.label.pixelOffset : 20,
backgroundColor: options.label.backgroundColor || ['#00ffff80', '#00ffff80'],
2025-07-09 11:15:53 +08:00
lineColor: options.label.lineColor || '#00ffff80',
2025-07-03 13:54:01 +08:00
scaleByDistance: options.label.scaleByDistance || false,
near: (options.label.near || options.label.near === 0) ? options.label.near : 2000,
far: (options.label.far || options.label.far === 0) ? options.label.far : 100000,
}
if (this.options.line.positions.length < 2) {
this._error = '最少需要两个坐标!'
console.warn(this._error)
window.ELEMENT && window.ELEMENT.Message({
message: this._error,
type: 'warning',
duration: 1500
});
}
else {
this.sdk.addIncetance(this.options.id, this)
this.ControllerObject = new Controller(this.sdk)
this._EventBinding = new EventBinding()
this.options.viewFollow = false
this.options.firstPersonView = false
TrajectoryMotion.addLine(this)
this.firstPersonView = false
// this.options.viewFollowOrientation = options.viewFollowOrientation
}
// animateUpdate()
// function animateUpdate() {
// requestAnimationFrame(animateUpdate);
// TWEEN.update();
// }
}
get type() {
return 'TrajectoryMotion'
}
get show() {
return this.options.show
}
set show(v) {
if (typeof v === "boolean") {
2025-08-13 11:51:39 +08:00
let sdkD = get2DView()
if (!this.isShowView || !sdkD) {
this.options.show = v
if (this.originalOptions) {
this.originalOptions.show = v
}
2025-07-03 13:54:01 +08:00
}
if (this.options.show) {
2025-07-03 13:54:01 +08:00
if (this.firstPersonView) {
this.model.show = false
}
else {
2025-08-13 11:51:39 +08:00
this.model.show = (!this.showView || this.showView == 3 || !sdkD) ? this.modelShow : false
2025-07-03 13:54:01 +08:00
}
2025-08-13 11:51:39 +08:00
if ((!this.showView || this.showView == 3 || !sdkD)) {
this.line.polyline.material = this.lineShow ? new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff'),
dashLength: 20,
}) : new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff00'),
dashLength: 20,
})
}
else {
this.line.polyline.material = new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff00'),
dashLength: 20,
})
}
2025-07-03 13:54:01 +08:00
for (let i = 0; i < this.keyPoints.length; i++) {
2025-08-13 11:51:39 +08:00
this.keyPoints[i].show = (!this.showView || this.showView == 3 || !sdkD) ? this.keyPointShow : false
2025-07-03 13:54:01 +08:00
}
if (this.realTimeRoute) {
2025-08-13 11:51:39 +08:00
this.realTimeLine && (this.realTimeLine.show = (!this.showView || this.showView == 3 || !sdkD) ? true : false)
2025-07-03 13:54:01 +08:00
}
this.label && (this.label.show = (!this.showView || this.showView == 3) ? this.options.label.show : false)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.show = (!this.showView || this.showView == 3) ? this.options.fuelShow : false)
2025-07-03 13:54:01 +08:00
}
else {
2025-08-13 11:51:39 +08:00
this.model.show = (!this.showView || this.showView == 3 || !sdkD) ? this.options.show : false
let show = this.options.show
2025-08-13 11:51:39 +08:00
if ((!this.showView || this.showView == 3 || !sdkD)) {
show = this.options.show
}
else {
show = false
}
2025-07-03 13:54:01 +08:00
this.realTimeLine && (this.realTimeLine.show = false)
this.line.polyline.material = show ? new Cesium.PolylineDashMaterialProperty({
2025-07-03 13:54:01 +08:00
color: new Cesium.Color.fromCssColorString('#00ffff'),
dashLength: 20,
}) : new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff00'),
dashLength: 20,
})
for (let i = 0; i < this.keyPoints.length; i++) {
this.keyPoints[i].show = (!this.showView || this.showView == 3) ? show : false
2025-07-03 13:54:01 +08:00
}
this.label && (this.label.show = false)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.show = false)
2025-07-03 13:54:01 +08:00
this.viewFollow = false
}
if (this._DialogObject && this._DialogObject.showBtn) {
this._DialogObject.showBtn.checked = v
}
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
this.isShowView = false
2025-07-03 13:54:01 +08:00
} else {
console.error("参数必须为boolean")
}
}
get height() {
return this.options.height
}
set height(v) {
if (this.ground) {
return
}
let difference = this.options.height - Number(v.toFixed(2))
this.options.height = Number(v.toFixed(2))
if (this.line) {
if (this.ground) {
}
else {
let dvalue = this.options.height - this.options.line.positions[0].alt
this.line.polyline.clampToGround = false
for (let i = 0; i < this.keyPoints.length; i++) {
this.options.line.positions[i].alt += dvalue
this.keyPoints[i].position = Cesium.Cartesian3.fromDegrees(this.options.line.positions[i].lng, this.options.line.positions[i].lat, this.options.line.positions[i].alt)
}
}
}
if (this.model && this.model.position) {
let heading = this.model.heading
let pitch = this.model.pitch
let roll = this.model.roll
if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
return
}
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.model.position)
Cesium.Matrix4.multiplyByTranslation(matrix, new Cesium.Cartesian3(0, 0, -difference), matrix)
Cesium.Matrix4.getTranslation(matrix, this.model.position)
Cesium.Matrix4.multiplyByMatrix3(matrix, Cesium.Matrix3.fromHeadingPitchRoll(Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll)), this.entity.modelMatrix)
// Cesium.Matrix4.multiplyByTranslation(this.model.modelMatrix, new Cesium.Cartesian3(0, 0, -difference), this.model.modelMatrix)
// Cesium.Matrix4.getTranslation(this.model.modelMatrix, this.model.position)
this.label && (this.label.show = this.label.show)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.show = this.fuelLabel.show)
2025-07-03 13:54:01 +08:00
if (this.options.label.position) {
setTimeout(() => {
if (this.options.label.position.alt) {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
2025-07-03 13:54:01 +08:00
}
else {
this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, height])
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, height])
2025-07-03 13:54:01 +08:00
})
}
}, 0)
}
}
let positions_smooth = this.renewLinePositions(this.options.line.positions)
this.line.polyline.positions = positions_smooth
this._elms.height && this._elms.height.forEach((item) => {
item.value = Number(v.toFixed(2))
})
}
get ground() {
return this.options.ground
}
set ground(v) {
this.lineEdit = false
this.options.ground = v
this.realTimeLine.polyline.clampToGround = v
this.height = this.options.height
if (this.line) {
if (v) {
this.line.polyline.clampToGround = true
for (let i = 0; i < this.keyPoints.length; i++) {
this.sdk.viewer.scene.clampToHeightMostDetailed([new Cesium.Cartesian3.fromDegrees(this.options.line.positions[i].lng, this.options.line.positions[i].lat)]).then((result) => {
this.keyPoints[i].position = result[0]
})
}
}
}
setTimeout(() => {
if (this.TweenAnimate && this.TweenAnimate._isPlaying) {
this.setMovePositionByDistance(this.TweenAnimate._object.distance)
}
else {
this.setMovePositionByDistance(0)
}
}, 200);
// let _this = this
// let positions = this.renewLinePositions(this.options.line.positions)
// let startDistance = this.TweenAnimate._object.distance
// let lineString = []
// for (let i = 0; i < positions.length; i++) {
// let position = this.cartesian3Towgs84(positions[i], _this.sdk.viewer)
// lineString.push([position.lng, position.lat, position.alt])
// }
// let line = turf.lineString(lineString);
// this.distance = turf.length(line, { units: 'kilometers' });
// setPosition(startDistance)
// async function setPosition(distance) {
// let start = 0;
// let stop = distance;
// let coordinates
// let sliced = line
// if (stop) {
// sliced = await turf.lineSliceAlong(line, start, stop, { units: 'kilometers' });
// // _this.realTimeRouteArray = sliced+
// coordinates = [...sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1]]
// }
// else {
// coordinates = [...line.geometry.coordinates[0]]
// }
// let position
// let positionCamera
// if (_this.ground) {
// // if (viewer.terrainProvider.availability) {
// // let result = await new Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [Cesium.Cartographic.fromDegrees(coordinates[0], coordinates[1])]);
// // position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height)
// // positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height + 1)
// // }
// // else {
// // position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
// // positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], 1)
// // }
// let filterEntitys = []
// // for (let [key, value] of _this.sdk.entityMap) {
// // if (!value.type || (value.type !== 'glb' && value.type!== 'bim' && value.type!== 'tileset' && value.type!== 'TrajectoryMotion' && value.entity)) {
// // console.log(value.entity)
// // filterEntitys.push(value.entity.id)
// // }
// // }
// // console.log('8888888888',_this.model, ...filterEntitys)
// let result
// let sdk2D = get2DView()
// if (sdk2D && _this.sdk == sdk2D) {
// result = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
// position = result
// }
// else {
// result = await _this.sdk.viewer.scene.clampToHeight(new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1]), [_this.model, ...filterEntitys])
// position = result
// }
// if (!result) {
// position = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
// }
// let pos3 = _this.cartesian3Towgs84(position, _this.sdk.viewer);
// let height2 = 0
// try {
// let position2 = await Cesium.sampleTerrainMostDetailed(
// _this.sdk.viewer.scene.terrainProvider,
// [Cesium.Cartographic.fromDegrees(pos3.lng, pos3.lat)]
// )
// height2 = position2[0].height
// } catch (error) {
// height2 = 0
// }
// if (pos3.alt < height2) {
// pos3.alt = height2
// }
// pos3.alt = Number(pos3.alt.toFixed(1))
// position = Cesium.Cartesian3.fromDegrees(pos3.lng, pos3.lat, pos3.alt)
// positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], _this.cartesian3Towgs84(position, _this.sdk.viewer).alt + 1.8)
// let fromDegreesArray = []
// for (let i = 0; i < sliced.geometry.coordinates.length; i++) {
// fromDegreesArray.push(sliced.geometry.coordinates[i][0], sliced.geometry.coordinates[i][1])
// }
// _this.realTimePositions = Cesium.Cartesian3.fromDegreesArray(fromDegreesArray)
// // _this.realTimeLine.polyline.positions =
// }
// else {
// let cartesian3 = _this.spline.evaluate(distance / _this.distance)
// if (!cartesian3) {
// return
// }
// coordinates = _this.cartesian3Towgs84(cartesian3, _this.sdk.viewer);
// position = cartesian3
// positionCamera = Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, coordinates.alt + 1.8)
// let positions_smooth = []
// for (let i = 0; i <= 1000; i++) {
// if ((i / 1000) > (distance / _this.distance)) {
// break
// }
// let cartesian3 = _this.spline.evaluate(i / 1000);
// positions_smooth.push(cartesian3);
// }
// positions_smooth.push(cartesian3)
// _this.realTimePositions = positions_smooth
// }
// HeadingPitchRoll = getHeadingPitchRoll(_this.model.position, position)
// if (previous && previous.position) {
// HeadingPitchRoll2 = getHeadingPitchRoll(previous.position, position)
// HeadingPitchRoll.pitch = HeadingPitchRoll2.pitch
// }
// previous.position = _this.model.position
// let modeHeadingPitchRoll = Cesium.HeadingPitchRoll.fromDegrees(_this.options.model.heading, _this.options.model.pitch, _this.options.model.roll)
// let heading = 0
// let pitch = 0
// let roll = 0
// let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
// if (_this.options.routeDirection && !_this.lineEdit) {
// heading = (HeadingPitchRoll.heading) * (180 / Math.PI) - 90 - _this.options.model.heading
// pitch = (HeadingPitchRoll.pitch) * (180 / Math.PI) - _this.options.model.pitch
// roll = _this.options.model.roll
// if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
// return
// }
// _this.model.modelMatrix = Cesium.Matrix4.multiplyByMatrix3(matrix, Cesium.Matrix3.fromHeadingPitchRoll(Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll)), _this.model.modelMatrix)
// }
// else {
// if (_this.entity) {
// heading = _this.options.model.heading
// pitch = _this.options.model.pitch
// roll = _this.options.model.roll
// if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
// return
// }
// // 旋转
// let mx = Cesium.Matrix3.fromRotationX(
// Cesium.Math.toRadians(roll)
// )
// let my = Cesium.Matrix3.fromRotationY(
// Cesium.Math.toRadians(pitch)
// )
// let mz = Cesium.Matrix3.fromRotationZ(
// Cesium.Math.toRadians(heading)
// )
// let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
// let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
// let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
// let originalMatrix = new Cesium.Matrix4()
// Cesium.Matrix4.multiply(matrix, rotationX, originalMatrix)
// Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
// Cesium.Matrix4.multiply(originalMatrix, rotationZ, _this.entity.modelMatrix)
// }
// }
// // console.log((HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI))
// _this.model.position = position
// if (!position) {
// return
// }
// let labelPosition = _this.cartesian3Towgs84(position, _this.sdk.viewer)
// _this.label.position = [labelPosition.lng, labelPosition.lat, labelPosition.alt]
// lastDistance = distance
// // console.log(position)
// _this.realTimeRouteArray.push(position)
// if (_this.viewFollow) {
// // console.log(Cesium.Math.toDegrees(_this.sdk.viewer.camera.pitch))
// if (_this.options.firstPersonView) {
// _this.sdk.viewer.camera.setView({
// destination: positionCamera,
// orientation: {
// heading: Cesium.Math.toRadians(heading + 90 + _this.firstPersonHeadingPitch.heading),
// pitch: Cesium.Math.toRadians(_this.firstPersonHeadingPitch.pitch),
// roll: 0
// }
// })
// }
// else {
// if (_this.sdk.viewer.scene.mode === 3) {
// if (_this.sdk.viewer.trackedEntity) {
// _this.sdk.viewer.trackedEntity.position = position
// // _this.sdk.viewer.camera.position = position
// }
// }
// else {
// if (_this.sdk.viewer.trackedEntity) {
// _this.sdk.viewer.camera.setView({
// destination: Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, _this.sdk.viewer.camera.positionCartographic.height),
// orientation: {
// heading: Cesium.Math.toRadians(-90),
// pitch: 0,
// roll: 0
// }
// })
// }
// }
// }
// }
// }
if (v) {
this._elms.heightBox && (this._elms.heightBox.className = 'input-number input-number-unit-1 height-box disabled');
}
else {
this._elms.heightBox && (this._elms.heightBox.className = 'input-number input-number-unit-1 height-box');
}
this._elms.ground && this._elms.ground.forEach((item) => {
item.checked = v
})
}
get modelPixelSize() {
return this.options.model.pixelSize
}
set modelPixelSize(v) {
this.options.model.pixelSize = v
if (this.model) {
this.model.minimumPixelSize = v
}
this._elms.modelPixelSize && this._elms.modelPixelSize.forEach((item) => {
item.value = v
})
}
get scale() {
return this.options.model.scale
}
set scale(v) {
this.options.model.scale = Number(v)
if (this.model) {
this.model.scale = v
this.model.customScale = { x: this.options.model.scale, y: this.options.model.scale, z: this.options.model.scale };
}
this._elms.scale && this._elms.scale.forEach((item) => {
item.value = v
})
}
get speed() {
return this.options.speed
}
set speed(v) {
if (v <= 0) {
v = 0.01
}
this.options.speed = v
if (this.state && this.TweenAnimate && this.TweenAnimate._isPlaying) {
this.setMovePositionByDistance(this.TweenAnimate._object.distance)
}
// let totalTime = (this.distance * 1000) / this.options.speed * 1000
// // this.TweenAnimate._object.distance/this.TweenAnimate._valuesEnd.distance
// this.TweenAnimate._duration = totalTime
this._elms.speed && this._elms.speed.forEach((item) => {
item.value = v
})
}
get smooth() {
return this.options.line.smooth
}
set smooth(v) {
this.lineEdit = false
this.options.line.smooth = v
let positions = this.renewLinePositions(this.options.line.positions)
this.line.polyline.positions = positions
this.model.position = positions[0]
this.modelMove(positions)
this._elms.smooth && this._elms.smooth.forEach((item) => {
item.checked = v
})
}
get delay() {
return this.options.delay
}
set delay(v) {
this.options.delay = v
if (this.TweenAnimate && this.TweenAnimate._isPlaying) {
this.TweenAnimate.delay(this.delay)
}
this._elms.delay && this._elms.delay.forEach((item) => {
item.value = v
})
}
get state() {
return this.options.state
}
set state(v) {
this.options.state = v
cancelAnimationFrame(this.#_requestAnimationFrameEventId)
if (this.editObj) {
this.editObj.destroy()
this.editObj = null
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '开始调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn'
}
}
if (this.TweenAnimate && this.TweenAnimate._isPlaying) {
clearTimeout(this.TweenAnimate.timeout)
if (v) {
this.lineEdit = false
if (this.TweenAnimate.isPlaying()) {
this.TweenAnimate.timeout = setTimeout(() => {
this.TweenAnimate.resume()
}, this.options.delay);
}
else {
this.TweenAnimate.delay(this.delay).start()
}
this.speed = this.speed
}
else {
let positionCamera = { ...this.sdk.viewer.camera._position }
let _this = this
this.#_requestAnimationFrameEventId = requestAnimationFrame(function fn() {
if (_this.firstPersonView) {
_this.sdk.viewer.camera.setView({
destination: { ...positionCamera },
orientation: {
heading: _this.sdk.viewer.camera.heading,
pitch: _this.sdk.viewer.camera.pitch,
roll: _this.sdk.viewer.camera.roll
}
})
}
_this.#_requestAnimationFrameEventId = requestAnimationFrame(fn)
})
this.TweenAnimate.pause()
setTimeout(() => {
_this.model && (_this.model.isMove = false)
2025-07-03 13:54:01 +08:00
}, 200);
}
}
else {
if (v) {
let positions = this.renewLinePositions(this.options.line.positions)
this.modelMove(positions)
}
}
this._elms.state && this._elms.state.forEach((item) => {
item.checked = v
})
}
get modelShow() {
return this.options.model.show
}
set modelShow(v) {
2025-08-13 11:51:39 +08:00
let sdkD = get2DView()
2025-07-03 13:54:01 +08:00
this.options.model.show = v
let show = v
2025-08-13 11:51:39 +08:00
if (this.show && (!this.showView || this.showView == 3 || !sdkD)) {
show = v
}
else {
show = false
}
2025-07-03 13:54:01 +08:00
if (this.model && this.show) {
this.model.show = show
2025-07-03 13:54:01 +08:00
}
this._elms.modelShow && this._elms.modelShow.forEach((item) => {
item.checked = v
})
}
get modelAnimate() {
return this.options.model.animate
}
set modelAnimate(v) {
this.options.model.animate = v
if (!this.model || !this.model.loader.components) {
return
}
let animations = this.model.loader.components.animations
this.model.activeAnimations.removeAll()
if (animations && animations.length > 0) {
for (let i = 0; i < animations.length; i++) {
if (animations[i].name == v) {
this.model.activeAnimations.add({
index: i,
loop: Cesium.ModelAnimationLoop.REPEAT,
speedup: 1,
reverse: false
})
break
}
}
}
this._elms.modelAnimate && this._elms.modelAnimate.forEach((item) => {
item.value = v
})
}
get noseToTail() {
return this.options.line.noseToTail
}
set noseToTail(v) {
this.lineEdit = false
this.options.line.noseToTail = v
let fromDegreesArrayHeights = []
for (let i = 0; i < this.options.line.positions.length; i++) {
fromDegreesArrayHeights.push(this.options.line.positions[i].lng, this.options.line.positions[i].lat, this.options.line.positions[i].alt)
}
let nosmooth = Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights)
if (this.line) {
let positions_smooth = this.renewLinePositions(this.options.line.positions)
this.line.polyline.positions = positions_smooth
this.model.position = positions_smooth[0]
this.modelMove(positions_smooth)
}
this._elms.noseToTail && this._elms.noseToTail.forEach((item) => {
item.checked = v
})
}
get lineShow() {
return this.options.line.show
}
set lineShow(v) {
if (v) {
this.realTimeRoute = false
}
this.options.line.show = v
let show = v
2025-08-13 11:51:39 +08:00
let sdkD = get2DView()
if ((!this.showView || this.showView == 3 || !sdkD)) {
show = v
}
else {
show = false
}
2025-07-03 13:54:01 +08:00
if (this.line && this.show) {
this.line.polyline.material = show ? new Cesium.PolylineDashMaterialProperty({
2025-07-03 13:54:01 +08:00
color: new Cesium.Color.fromCssColorString('#00ffff'),
dashLength: 20, //短划线长度
}) : new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff00'),
dashLength: 20, //短划线长度
})
}
this._elms.lineShow && this._elms.lineShow.forEach((item) => {
item.checked = v
})
}
get realTimeRoute() {
return this.options.realTimeRoute
}
set realTimeRoute(v) {
if (v) {
this.lineShow = false
this.keyPointShow = false
}
this.options.realTimeRoute = v
if (this.realTimeLine && this.show) {
this.realTimeLine.show = v
}
this._elms.realTimeRoute && this._elms.realTimeRoute.forEach((item) => {
item.checked = v
})
}
get keyPointShow() {
return this.options.line.keyPoint
}
set keyPointShow(v) {
this.options.line.keyPoint = v
for (let i = 0; i < this.keyPoints.length; i++) {
if (this.show) {
this.keyPoints[i].show = v
}
}
this._elms.keyPointShow && this._elms.keyPointShow.forEach((item) => {
item.checked = v
})
if (!v && this.lineEdit) {
// 关闭线编辑
this.#lineEdit = v
YJ.Measure.SetMeasureStatus(false)
this.event && this.event.destroy()
this.ControllerObject && this.ControllerObject.destroy()
this.tip && this.tip.destroy()
this.tip = null
this._elms.lineEdit && this._elms.lineEdit.forEach((item) => {
item.checked = v
})
}
}
get lineEdit() {
return this.#lineEdit
}
set lineEdit(v) {
let linePositions = []
let computePositionsSmooth = (positions) => {
linePositions = this.renewLinePositions(positions)
this.model.position = linePositions[0]
this.modelMove(linePositions)
}
if (v) {
this.viewFollow = false
if (YJ.Measure.GetMeasureStatus()) {
console.warn('上一次测量未结束')
this.lineEdit = false
return
}
else {
this.ground = false
this.smooth = false
this.state = false
YJ.Measure.SetMeasureStatus(true)
this.event && this.event.destroy()
this.tip && this.tip.destroy()
this.tip = new MouseTip('请选择一个顶点,右键取消', this.sdk)
this.event = new MouseEvent(this.sdk)
let selectPoint
computePositionsSmooth([...this.options.line.positions])
let leftEvent = (movement, cartesian) => {
let pick = this.sdk.viewer.scene.pick(movement.position);
if (pick && pick.id && pick.id.name && pick.id.name === 'node-secondary-edit-point') {
for (let i = 0; i < this.keyPoints.length; i++) {
if (this.keyPoints[i].id === pick.id.id) {
// this.keyPoints[i].show = false
selectPoint = pick.id
this.ControllerObject.position = this.options.line.positions[selectPoint.index]
this.ControllerObject.editTranslational()
this.tip && this.tip.destroy()
this.tip = null
this.ControllerObject.controllerCallBack = (params) => {
// console.log('params', params)
this.options.line.positions[selectPoint.index] = params.position
if (selectPoint.index === 0) {
this.options.height = this.options.line.positions[selectPoint.index].alt
this._elms.height && this._elms.height.forEach((item) => {
item.value = Number(this.options.height.toFixed(2))
})
}
selectPoint.position = Cesium.Cartesian3.fromDegrees(params.position.lng, params.position.lat, params.position.alt)
computePositionsSmooth([...this.options.line.positions])
}
break
}
}
// originalPosition = this.cartesian3Towgs84(cartesian, this.sdk.viewer)
}
}
this.event.mouse_left(leftEvent)
this.event.mouse_right((movement, cartesian) => {
this.keyPointShow = false
YJ.Measure.SetMeasureStatus(false)
this.event.destroy()
this.tip && this.tip.destroy()
this.tip = null
this.ControllerObject.destroy()
})
this.event.mouse_move((movement, cartesian) => {
this.tip && this.tip.setPosition(
cartesian,
movement.endPosition.x,
movement.endPosition.y
)
})
this.event.gesture_pinck_start((movement, cartesian) => {
let startTime = new Date()
let pos = {
position: {
x: (movement.position1.x + movement.position2.x) / 2,
y: (movement.position1.y + movement.position2.y) / 2
}
}
this.event.gesture_pinck_end(() => {
let endTime = new Date()
if (endTime - startTime >= 500) {
// 长按取消
this.keyPointShow = false
YJ.Measure.SetMeasureStatus(false)
this.event.destroy()
this.tip && this.tip.destroy()
this.tip = null
this.ControllerObject.destroy()
}
else {
leftEvent(pos, cartesian)
}
})
})
this.line.polyline.positions = new Cesium.CallbackProperty(function () {
return linePositions
}, false)
}
// 显示关键点
this.keyPointShow = v
}
else {
if (this.lineEdit) {
YJ.Measure.SetMeasureStatus(false)
this.event.destroy()
this.tip && this.tip.destroy()
this.tip = null
}
// 隐藏关键点
this.keyPointShow = v
this.ControllerObject.destroy()
}
this.#lineEdit = v
this._elms.lineEdit && this._elms.lineEdit.forEach((item) => {
item.checked = v
})
}
get routeDirection() {
return this.options.routeDirection
}
set routeDirection(v) {
this.options.routeDirection = v
this._elms.routeDirection && this._elms.routeDirection.forEach((item) => {
item.checked = v
})
}
get loop() {
return this.options.loop
}
set loop(v) {
this.options.loop = v
if (this.TweenAnimate && this.TweenAnimate._isPlaying) {
if (v) {
this.TweenAnimate.repeat(Infinity)
}
else {
this.TweenAnimate.repeat()
}
}
this._elms.loop && this._elms.loop.forEach((item) => {
item.checked = v
})
}
get firstPersonView() {
return this.options.firstPersonView
}
set firstPersonView(v) {
// this.state = true
2025-08-13 11:51:39 +08:00
let sdkD = get2DView()
2025-07-03 13:54:01 +08:00
let splitSdk = getSdk()
if (get2DView() || splitSdk.sdkD || !this.show) {
v = false
}
cancelAnimationFrame(this.#_requestAnimationFrameEventId)
this.#firstPersonViewEvent && this.#firstPersonViewEvent.destroy()
this.sdk.viewer._firstPersonView = v
this.options.firstPersonView = v
if (this.options.firstPersonView) {
this.viewFollow = true
this.firstPersonHeadingPitch = {
heading: 0,
pitch: -10
}
this.state = true
this.model && (this.model.show = false)
if (this._DialogObject && this._DialogObject._element.content) {
let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']")
e_firstPerson[0].className = 'btn is-active'
e_firstPerson[1].className = 'btn'
}
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
this.sdk.viewer.trackedEntity = null
}
CameraController(this.sdk, false)
let splitSdk = getSdk()
let targetSdk
if (this.sdk === splitSdk.sdkP) {
targetSdk = splitSdk.sdkD
}
else {
targetSdk = splitSdk.sdkP
}
let targetEntity = targetSdk ? targetSdk.entityMap.get(this.options.id) : undefined
if (this.sdk)
this.#firstPersonViewEvent = new MouseEvent(this.sdk)
this.#firstPersonViewEvent.mouse_right_down((movement, cartesian) => {
let startPosition = { ...movement.position }
this.#firstPersonViewEvent.mouse_move((movement2, cartesian2) => {
this.firstPersonHeadingPitch.heading = this.firstPersonHeadingPitch.heading + ((movement2.endPosition.x - startPosition.x) / 20)
this.firstPersonHeadingPitch.pitch = this.firstPersonHeadingPitch.pitch + ((startPosition.y - movement2.endPosition.y) / 10)
targetEntity && (targetEntity.firstPersonHeadingPitch = { ...this.firstPersonHeadingPitch })
startPosition = { ...movement2.endPosition }
}, true)
}, true)
this.#firstPersonViewEvent.mouse_right_up((movement, cartesian) => {
this.#firstPersonViewEvent.mouse_move(() => { })
}, true)
}
else {
CameraController(this.sdk, true)
if (this.model && this.modelShow && this.show) {
let show = true
2025-08-13 11:51:39 +08:00
if (this.show && (!this.showView || this.showView == 3 || !sdkD)) {
show = true
}
else {
show = false
}
this.model.show = show
2025-07-03 13:54:01 +08:00
}
if (this._DialogObject && this._DialogObject._element.content) {
let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']")
if (e_firstPerson[0] && e_firstPerson[1]) {
e_firstPerson[0].className = 'btn'
e_firstPerson[1].className = 'btn is-active'
}
}
if (this.viewFollow && this.show) {
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
}
if (this.sdk.viewer.scene.mode === 3) {
let pointEntity = this.sdk.viewer.entities.add({
// show: false,
position: this.positions_smooth[0], // position of the point
point: {
color: Cesium.Color.RED.withAlpha(0), // color of the point
pixelSize: 0
}
});
this.sdk.viewer.trackedEntity = pointEntity;
}
this.viewFollow = this.viewFollow
}
}
syncSplitData(this.sdk, this.options.id)
}
get viewFollow() {
return this.options.viewFollow
}
set viewFollow(v) {
let splitSdk = getSdk()
let sdk2D = get2DView()
// if (sdk2D || splitSdk.sdkD) {
// v = false
// }
if (!this.show) {
v = false
}
this.options.viewFollow = v
if (!this.options.viewFollow) {
this.firstPersonView = false
}
else {
if (this.editObj) {
this.editObj.destroy()
this.editObj = null
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '开始调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn'
}
}
closeRotateAround(this.sdk)
this.lineEdit = false
}
if (this.options.firstPersonView) {
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
this.sdk.viewer.trackedEntity = null
}
if (this._DialogObject && this._DialogObject._element.content) {
let e_firstPerson = this._DialogObject._element.content.querySelectorAll("button[name='firstPerson']")
if (e_firstPerson[0] && e_firstPerson[1]) {
e_firstPerson[0].className = 'btn'
e_firstPerson[1].className = 'btn is-active'
}
}
}
else {
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
this.sdk.viewer.trackedEntity = null
}
if (v && this.show && this.model) {
let pointEntity = this.sdk.viewer.entities.add({
// show: false,
position: this.model.position, // position of the point
point: {
color: Cesium.Color.RED.withAlpha(0), // color of the point
pixelSize: 0
}
});
this.sdk.viewer.trackedEntity = pointEntity;
}
}
let sdk3D = get3DView()
if (sdk3D) {
if (this.sdk != sdk3D) {
let that3D = sdk3D.entityMap.get(this.options.id)
if (that3D && that3D.viewFollow != v) {
that3D.viewFollow = v
}
}
else {
if (sdk2D) {
let that2D = sdk2D.entityMap.get(this.options.id)
if (that2D && that2D.viewFollow != v) {
that2D.viewFollow = v
if (this.TweenAnimate && this.TweenAnimate._isPlaying) {
that2D.setMovePositionByDistance(this.TweenAnimate._object.distance)
}
}
}
}
}
syncSplitData(this.sdk, this.options.id)
this._elms.viewFollow && this._elms.viewFollow.forEach((item) => {
item.checked = v
})
}
get labelShow() {
return this.options.label.show
}
set labelShow(v) {
this.options.label.show = v
2025-08-13 11:51:39 +08:00
let sdkD = get2DView()
let show = v
2025-08-13 11:51:39 +08:00
if (this.show && (!this.showView || this.showView == 3 || !sdkD)) {
show = v
}
else {
show = false
}
2025-07-03 13:54:01 +08:00
if (this.show) {
2025-08-21 16:37:49 +08:00
if (this.label) {
this.label.show = show
this.label.pixelOffset = this.options.label.pixelOffset + (this.fuelShow ? this.labelFontSize + 20 : 0)
if (this.options.label.position) {
setTimeout(() => {
if (this.options.label.position.alt) {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
}
else {
this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
this.label && (this.label.position = [this.options.label.position.lng, this.options.label.position.lat, height])
})
}
}, 0);
}
2025-07-03 13:54:01 +08:00
}
}
else {
this.label && (this.label.show = false)
}
this._elms.labelShow && this._elms.labelShow.forEach((item) => {
item.checked = v
})
}
get labelFontFamily() {
return this.options.label.fontFamily
}
set labelFontFamily(v) {
this.options.label.fontFamily = v || 0
this.label && (this.label.fontFamily = this.options.label.fontFamily)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.fontFamily = this.options.label.fontFamily)
2025-07-03 13:54:01 +08:00
let name = getFontFamilyName(this.labelFontFamily) || ''
this._elms.labelFontFamily &&
this._elms.labelFontFamily.forEach(item => {
item.value = name
})
}
get labelColor() {
return this.options.label.color
}
set labelColor(v) {
this.options.label.color = v
this.label && (this.label.color = v)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.color = v)
2025-07-03 13:54:01 +08:00
if (this._elms.labelColor) {
this._elms.labelColor.forEach((item, i) => {
2025-07-16 15:02:18 +08:00
let labelColorPicker = new YJColorPicker({
2025-07-03 13:54:01 +08:00
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.labelColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.labelColor = color
},//点击确认按钮事件回调
clear: () => {
this.labelColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.labelColor[i] = labelColorPicker
})
}
}
get labelFontSize() {
return this.options.label.fontSize
}
set labelFontSize(v) {
this.options.label.fontSize = v
this.label && (this.label.fontSize = v)
2025-08-21 16:37:49 +08:00
if (this.fuelLabel) {
this.fuelLabel.fontSize = v
this.label.pixelOffset = this.options.label.pixelOffset + v + 20
}
else {
this.label.pixelOffset = this.options.label.pixelOffset
}
2025-07-03 13:54:01 +08:00
this._elms.labelFontSize && this._elms.labelFontSize.forEach((item) => {
item.value = v
})
}
get labelScaleByDistance() {
return this.options.label.scaleByDistance
}
set labelScaleByDistance(v) {
this.options.label.scaleByDistance = v
this.label && (this.label.scaleByDistance = v)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.scaleByDistance = v)
2025-07-03 13:54:01 +08:00
this._elms.labelScaleByDistance && this._elms.labelScaleByDistance.forEach((item) => {
item.checked = v
})
}
get labelNear() {
return this.options.label.near
}
set labelNear(v) {
let near = v
if (near > this.labelFar) {
near = this.labelFar
}
this.options.label.near = near
this.label && (this.label.near = near)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.near = near)
2025-07-03 13:54:01 +08:00
this._elms.labelNear && this._elms.labelNear.forEach((item) => {
item.value = near
})
}
get labelFar() {
return this.options.label.far
}
set labelFar(v) {
let far = v
if (far < this.labelNear) {
far = this.labelNear
}
this.options.label.far = far
this.label && (this.label.far = far)
2025-08-21 16:37:49 +08:00
this.fuelLabel && (this.fuelLabel.far = far)
2025-07-03 13:54:01 +08:00
this._elms.labelFar && this._elms.labelFar.forEach((item) => {
item.value = far
})
}
2025-08-21 16:37:49 +08:00
get unitFuelConsumption() {
return this.options.unitFuelConsumption
}
set unitFuelConsumption(v) {
this.options.unitFuelConsumption = v
this._elms.unitFuelConsumption && this._elms.unitFuelConsumption.forEach((item) => {
item.value = v
})
}
get fuelShow() {
return this.options.fuelShow
}
set fuelShow(v) {
this.options.fuelShow = v
let show = v
if (this.show && (!this.showView || this.showView == 3)) {
show = v
}
else {
show = false
}
if (this.show) {
if (this.fuelLabel) {
this.fuelLabel.show = show
this.label.pixelOffset = this.options.label.pixelOffset + (show ? this.labelFontSize + 20 : 0)
}
else {
this.label.pixelOffset = this.options.label.pixelOffset
}
if (this.options.label.position) {
setTimeout(() => {
if (this.options.label.position.alt) {
this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, this.options.label.position.alt])
}
else {
this.getClampToHeight({ lng: this.options.label.position.lng, lat: this.options.label.position.lat }).then((height) => {
this.fuelLabel && (this.fuelLabel.position = [this.options.label.position.lng, this.options.label.position.lat, height])
})
}
}, 0);
}
}
else {
this.fuelLabel && (this.fuelLabel.show = false)
this.label.pixelOffset = this.options.label.pixelOffset
}
this._elms.fuelShow && this._elms.fuelShow.forEach((item) => {
item.checked = v
})
}
2025-07-03 13:54:01 +08:00
// 创建路径
static addLine(that) {
let positions_smooth = that.renewLinePositions(that.options.line.positions)
let show
if (that.options.show) {
show = that.options.line.show
}
else {
show = false
}
that.sdk.viewer.entities.removeById(that.options.id + '-2')
that.sdk.viewer.entities.removeById(that.options.id + '-3')
that.line = that.sdk.viewer.entities.add({
id: that.options.id + '-2',
polyline: {
positions: positions_smooth,
width: 2,
clampToGround: that.ground,
material: show ? new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff'),
dashLength: 20, //短划线长度
}) : new Cesium.PolylineDashMaterialProperty({
color: new Cesium.Color.fromCssColorString('#00ffff00'),
dashLength: 20, //短划线长度
}),
zIndex: that.sdk._entityZIndex
},
})
that.realTimeLine = that.sdk.viewer.entities.add({
id: that.options.id + '-3',
show: that.options.realTimeRoute ? that.options.realTimeRoute : false,
polyline: {
positions: new Cesium.CallbackProperty(function () {
return that.realTimePositions
}, false),
width: 2,
clampToGround: that.ground,
material: Cesium.Color.fromCssColorString('#ff0000'),
zIndex: that.sdk._entityZIndex
},
})
that.sdk._entityZIndex++
if (that.#mouseRightevent) {
that.#mouseRightevent.destroy()
}
that.#mouseRightevent = new MouseEvent(that.sdk)
that.#mouseRightevent.mouse_right((movement, cartesian) => {
let splitSdk = getSdk()
let targetSdk
if (that.sdk === splitSdk.sdkP) {
targetSdk = splitSdk.sdkD
}
else {
targetSdk = splitSdk.sdkP
}
let targetEntity = targetSdk ? targetSdk.entityMap.get(that.options.id) : undefined
targetEntity && (targetEntity.viewFollow = false)
that.viewFollow = false
}, true)
TrajectoryMotion.addModel(that)
TrajectoryMotion.addKeyPoint(that)
that.noseToTail = that.options.line.noseToTail
that.smooth = that.options.line.smooth
syncData(that.sdk, that.options.id)
if (that.options.show) {
setSplitDirection(0, that.options.id)
}
}
// 创建模型
static async addModel(that) {
let url = that.replaceHost(that.options.model.url, that.options.host)
2025-07-03 13:54:01 +08:00
let options = {
id: that.options.id,
url: url,
2025-07-03 13:54:01 +08:00
show: that.options.show ? that.options.model.show : false,
scale: that.options.model.scale,
// minimumPixelSize: that.options.model.pixelSize,
// maximumScale: 100000,
// allowPicking: false
}
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
that.model = await Cesium.Model.fromGltfAsync(options)
that.model.originalBoundingSphereRadius = 0
that.sdk.viewer.scene.primitives.add(that.model)
that.model.readyEvent.addEventListener(() => {
that.model.originalBoundingSphereRadius = that.model.boundingSphere.radius
that.modelAnimate = that.options.model.animate
})
}
else {
that.model = that.sdk.viewer.scene.primitives.add(
Cesium.Model.fromGltf(options)
);
that.model.originalBoundingSphereRadius = 0
that.model.readyPromise.then(() => {
that.model.originalBoundingSphereRadius = that.model.boundingSphere.radius
that.modelAnimate = that.options.model.animate
})
}
that.model.imageBasedLighting.luminanceAtZenith = 0.6
// 设置模型的旋转角度,使其水平放置于地面
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(that.positions_smooth[0])
that.model.modelMatrix = matrix
that.model.position = that.positions_smooth[0]
that.model.customScale = { x: that.options.model.scale, y: that.options.model.scale, z: that.options.model.scale };
// 模型大小比例
// Cesium.Matrix4.multiplyByScale(matrix, new Cesium.Cartesian3(0.1, 0.1, 0.1), this.entity.modelMatrix)
let positions = that.options.line.positions
let fromDegreesArrayHeights = []
for (let i = 0; i < positions.length; i++) {
fromDegreesArrayHeights.push(positions[i].lng, positions[i].lat, positions[i].alt)
}
let pos = that.smooth ? that.positions_smooth : Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights)
TrajectoryMotion.createLabel(that)
2025-08-21 16:37:49 +08:00
TrajectoryMotion.createFuelLabel(that)
2025-07-03 13:54:01 +08:00
that.modelMove(pos)
that.entity = that.model
}
static async createLabel(that) {
let labelPosition = that.cartesian3Towgs84(that.model.position, that.sdk.viewer)
that.label = new LabelObject(that.sdk, {
2025-08-21 16:37:49 +08:00
show: that.options.show ? (that.options.label.show ? true : false) : false,
2025-07-03 13:54:01 +08:00
position: [labelPosition.lng, labelPosition.lat, labelPosition.alt],
text: that.options.name,
fontSize: that.options.label.fontSize,
fontFamily: that.options.label.fontFamily,
color: that.options.label.color,
2025-08-21 16:37:49 +08:00
pixelOffset: that.options.label.pixelOffset + (that.options.fuelShow ? that.options.label.fontSize + 20 : 0),
2025-07-03 13:54:01 +08:00
backgroundColor: that.options.label.backgroundColor,
lineColor: that.options.label.lineColor,
lineWidth: that.options.label.lineWidth,
scaleByDistance: that.options.label.scaleByDistance,
near: that.options.label.near,
far: that.options.label.far
}, that.model)
}
2025-08-21 16:37:49 +08:00
static async createFuelLabel(that) {
let labelPosition = that.cartesian3Towgs84(that.model.position, that.sdk.viewer)
that.fuelLabel = new LabelObject(that.sdk, {
show: that.options.show ? (that.options.fuelShow ? true : false) : false,
// show: true,
position: [labelPosition.lng, labelPosition.lat, labelPosition.alt],
text: '总油耗:',
fontSize: that.options.label.fontSize,
fontFamily: that.options.label.fontFamily,
color: that.options.label.color,
pixelOffset: 0,
backgroundColor: ['#6e6e6e', '#6e6e6e'],
lineColor: '#00ffff00',
lineWidth: 0,
scaleByDistance: that.options.label.scaleByDistance,
near: that.options.label.near,
far: that.options.label.far
}, that.model)
}
2025-07-03 13:54:01 +08:00
// 创建关键点
static async addKeyPoint(that) {
for (let i = 0; i < that.options.line.positions.length; i++) {
let height = await that.getClampToHeight(that.options.line.positions[i])
let result = await Cesium.Cartesian3.fromDegrees(that.options.line.positions[i].lng, that.options.line.positions[i].lat, height)
let entity = that.sdk.viewer.entities.add({
name: 'node-secondary-edit-point',
index: i,
show: that.options.line.keyPoint || false,
position: that.ground ? result : Cesium.Cartesian3.fromDegrees(that.options.line.positions[i].lng, that.options.line.positions[i].lat, that.options.line.positions[i].alt),
billboard: {
image: that.getSourceRootPath() + '/img/point.png',
width: 15,
height: 15,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
color: Cesium.Color.WHITE.withAlpha(0.99)
},
})
that.keyPoints.push(entity)
}
}
// 模型移动
async modelMove(positions, option = { time: 0 }) {
cancelAnimationFrame(this.#_requestAnimationFrameEventId)
let _this = this
let time = option.time || 0
let startDistance = option.distance
let viewer = this.sdk.viewer
if (!this.model || !this.sdk || !this.sdk.viewer) {
return
}
this.removeModelAnimate()
let lineString = []
for (let i = 0; i < positions.length; i++) {
let position = this.cartesian3Towgs84(positions[i], viewer)
lineString.push([position.lng, position.lat, position.alt])
}
// console.log(lineString)
let line = turf.lineString(lineString);
this.distance = turf.length(line, { units: 'kilometers' });
let totalTime = (this.distance * 1000) / this.options.speed // 总耗时(秒)
if (!startDistance && startDistance !== 0) {
startDistance = 0.000001
if (time) {
if (time > totalTime) {
time = totalTime
}
startDistance = (time / totalTime) * this.distance
}
}
else {
if (startDistance > this.distance) {
startDistance = this.distance
}
time = (startDistance / this.distance) * totalTime
}
// console.log(totalTime)
let lastDistance = 0
let motionArray = []
let HeadingPitchRoll
let HeadingPitchRoll2
let previous = {}
let m = 0
this.TweenAnimate = new TWEEN.Tween({ distance: startDistance }).to({ distance: this.distance }, (totalTime - time) * 1000).delay(this.delay).easing(TWEEN.Easing.Linear.None).repeat(this.options.loop ? Infinity : 0).onRepeat(() => {
if (time || startDistance) {
this.modelMove(positions)
}
}).onUpdate(async (r, a) => {
if (this.TweenAnimate._duration == Infinity) {
return
}
m++
if (!this.sdk.viewer) {
this.removeModelAnimate()
return
}
if (!isNaN(r.distance)) {
setPosition(r.distance)
}
}).onEveryStart(() => {
this.realTimeRouteArray = []
}).onComplete((d) => {
this.state = false
// this.removeModelAnimate()
// let runtimeAnimation = this.model._activeAnimations._runtimeAnimations
// // let animations = await this.model.readyPromise
// for (let i = runtimeAnimation.length - 1; i >= 0; i--) {
// switch (runtimeAnimation[i].name) {
// case '跑':
// this.model.activeAnimations.remove(runtimeAnimation[i])
// break;
// default:
// }
// }
});
if (this.state) {
this.TweenAnimate.start()
}
else {
setPosition(startDistance)
setTimeout(() => {
_this.model.isMove = false
2025-08-21 16:37:49 +08:00
}, 1000);
2025-07-03 13:54:01 +08:00
animateUpdate()
function animateUpdate() {
_this.#_requestAnimationFrameEventId2 = requestAnimationFrame(
animateUpdate
)
if (_this.options.firstPersonView) {
let positionCamera = { ..._this.sdk.viewer.camera._position }
_this.sdk.viewer.camera.setView({
destination: positionCamera,
orientation: {
heading: Cesium.Math.toRadians(_this.model.heading + 90 + _this.firstPersonHeadingPitch.heading),
pitch: Cesium.Math.toRadians(_this.firstPersonHeadingPitch.pitch),
roll: 0
}
})
}
}
}
async function setPosition(distance) {
2025-08-21 16:37:49 +08:00
_this.totalFuelConsumption = Number((distance / 100 * _this.unitFuelConsumption).toFixed(2))
_this.fuelLabel.text = '总油耗:' + _this.totalFuelConsumption + ' L'
2025-07-03 13:54:01 +08:00
_this.model.isMove = true
let sdk2D = get2DView()
let splitSdk = getSdk()
if (!_this.sdk.viewer || !_this.sdk.viewer.scene) {
_this.removeModelAnimate()
return
}
let start = 0;
let stop = distance;
let coordinates
let sliced = line
if (stop) {
sliced = await turf.lineSliceAlong(line, start, stop, { units: 'kilometers' });
// _this.realTimeRouteArray = sliced+
coordinates = [...sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1]]
}
else {
coordinates = [...line.geometry.coordinates[0]]
}
let position
let positionCamera
if (_this.ground) {
// if (viewer.terrainProvider.availability) {
// let result = await new Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, [Cesium.Cartographic.fromDegrees(coordinates[0], coordinates[1])]);
// position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height)
// positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], result[0].height + 1)
// }
// else {
// position = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
// positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], 1)
// }
let filterEntitys = []
for (let [key, value] of _this.sdk.entityMap) {
if (!value.type || (value.type !== 'glb' && value.type !== 'bim' && value.type !== 'tileset' && value.type !== 'TrajectoryMotion' && value.type !== 'ParticleEffects' && value.entity)) {
// if(value.type === 'ParticleEffects') {
// for (let i = 0; i < value.entity._particles.length; i++) {
// filterEntitys.push(value.entity._particles[i]._billboard)
// }
// }
filterEntitys.push(value.entity)
if (value.label && value.label.entity) {
filterEntitys.push(value.label.entity)
}
}
}
if (_this.label && _this.label.entity) {
filterEntitys.push(_this.label.entity)
}
// let point1 = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], -10000);
// let point2 = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], 10000000000);
// let direction = Cesium.Cartesian3.subtract(point2, point1, new Cesium.Cartesian3());
// let c = Cesium.Cartesian3.normalize(direction, direction);
// console.log('射线方向:', c);
// let ray = new Cesium.Ray(point1, c);
// let pickedObjects = this.sdk.viewer.scene.pickFromRay(ray);
// console.log('pickedObjects', pickedObjects)
// console.log('height', Cesium.Cartographic.fromCartesian(pickedObjects.position).height)
let result
let sdk2D = get2DView()
if (sdk2D && _this.sdk == sdk2D) {
result = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
position = result
}
else {
result = await _this.sdk.viewer.scene.clampToHeight(new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1]), [_this.model, ...filterEntitys])
position = result
}
if (!result) {
position = new Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1])
}
let pos3 = _this.cartesian3Towgs84(position, viewer);
let height2 = 0
try {
let position2 = await Cesium.sampleTerrainMostDetailed(
_this.sdk.viewer.scene.terrainProvider,
[Cesium.Cartographic.fromDegrees(pos3.lng, pos3.lat)]
)
height2 = position2[0].height
} catch (error) {
height2 = 0
}
if (pos3.alt < height2) {
pos3.alt = height2
}
pos3.alt = Number(pos3.alt.toFixed(1))
position = Cesium.Cartesian3.fromDegrees(pos3.lng, pos3.lat, pos3.alt)
if (!_this.sdk.viewer || !_this.sdk.viewer.scene) {
_this.removeModelAnimate()
return
}
positionCamera = Cesium.Cartesian3.fromDegrees(coordinates[0], coordinates[1], _this.cartesian3Towgs84(position, _this.sdk.viewer).alt + 1.8)
let fromDegreesArray = []
for (let i = 0; i < sliced.geometry.coordinates.length; i++) {
fromDegreesArray.push(sliced.geometry.coordinates[i][0], sliced.geometry.coordinates[i][1])
}
_this.realTimePositions = Cesium.Cartesian3.fromDegreesArray(fromDegreesArray)
// _this.realTimeLine.polyline.positions =
}
else {
let cartesian3 = _this.spline.evaluate(distance / _this.distance)
if (!cartesian3) {
return
}
coordinates = _this.cartesian3Towgs84(cartesian3, viewer);
position = cartesian3
positionCamera = Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, coordinates.alt + 1.8)
let positions_smooth = []
for (let i = 0; i <= 1000; i++) {
if ((i / 1000) > (distance / _this.distance)) {
break
}
let cartesian3 = _this.spline.evaluate(i / 1000);
positions_smooth.push(cartesian3);
}
positions_smooth.push(cartesian3)
_this.realTimePositions = positions_smooth
}
HeadingPitchRoll = getHeadingPitchRoll(_this.model.position, position)
if (previous && previous.position) {
HeadingPitchRoll2 = getHeadingPitchRoll(previous.position, position)
HeadingPitchRoll.pitch = HeadingPitchRoll2.pitch
}
previous.position = _this.model.position
let modeHeadingPitchRoll = Cesium.HeadingPitchRoll.fromDegrees(_this.options.model.heading, _this.options.model.pitch, _this.options.model.roll)
let heading = 0
let pitch = 0
let roll = 0
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
if (_this.options.routeDirection && !_this.lineEdit) {
heading = (HeadingPitchRoll.heading) * (180 / Math.PI) - 90 - _this.options.model.heading
pitch = (HeadingPitchRoll.pitch) * (180 / Math.PI) - _this.options.model.pitch
roll = _this.options.model.roll
let that3D
if (get3DView()) {
that3D = get3DView().entityMap.get(_this.options.id)
}
else {
that3D = (splitSdk.sdkP && splitSdk.sdkP.entityMap.get(_this.options.id))
}
if (!_this.state) {
if (that3D && ((sdk2D && sdk2D === _this.sdk) || (splitSdk.sdkD && splitSdk.sdkD === _this.sdk))) {
heading = that3D.model.heading
pitch = that3D.model.pitch
roll = that3D.model.roll
}
}
if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
return
}
if (!_this.state) {
if (that3D && ((sdk2D && sdk2D === _this.sdk) || (splitSdk.sdkD && splitSdk.sdkD === _this.sdk))) {
heading = that3D.model.heading
pitch = that3D.model.pitch
roll = that3D.model.roll
}
else {
heading = (_this.model.heading || _this.model.heading === 0) ? _this.model.heading : _this.options.model.heading
pitch = (_this.model.pitch || _this.model.pitch === 0) ? _this.model.pitch : _this.options.model.pitch
roll = (_this.model.roll || _this.model.roll === 0) ? _this.model.roll : _this.options.model.roll
}
}
_this.model.modelMatrix = Cesium.Matrix4.multiplyByMatrix3(matrix, Cesium.Matrix3.fromHeadingPitchRoll(Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll)), _this.model.modelMatrix)
}
else {
if (_this.entity) {
heading = _this.options.model.heading
pitch = _this.options.model.pitch
roll = _this.options.model.roll
if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
return
}
// 旋转
let mx = Cesium.Matrix3.fromRotationX(
Cesium.Math.toRadians(roll)
)
let my = Cesium.Matrix3.fromRotationY(
Cesium.Math.toRadians(pitch)
)
let mz = Cesium.Matrix3.fromRotationZ(
Cesium.Math.toRadians(heading)
)
let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
let originalMatrix = new Cesium.Matrix4()
Cesium.Matrix4.multiply(matrix, rotationX, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationZ, _this.entity.modelMatrix)
}
}
// console.log((HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI))
_this.model.position = position
_this.model.roll = roll
_this.model.pitch = pitch
_this.model.heading = heading
if (!position) {
return
}
let labelPosition = _this.cartesian3Towgs84(position, _this.sdk.viewer)
_this.label.position = [labelPosition.lng, labelPosition.lat, labelPosition.alt]
2025-08-21 16:37:49 +08:00
_this.fuelLabel.position = [labelPosition.lng, labelPosition.lat, labelPosition.alt]
2025-07-03 13:54:01 +08:00
lastDistance = distance
// console.log(position)
_this.realTimeRouteArray.push(position)
if (_this.viewFollow) {
// console.log(Cesium.Math.toDegrees(_this.sdk.viewer.camera.pitch))
if (_this.options.firstPersonView) {
_this.sdk.viewer.camera.setView({
destination: positionCamera,
orientation: {
heading: Cesium.Math.toRadians(heading + 90 + _this.firstPersonHeadingPitch.heading),
pitch: Cesium.Math.toRadians(_this.firstPersonHeadingPitch.pitch),
roll: 0
}
})
}
else {
if (_this.sdk.viewer.scene.mode === 3) {
if (_this.sdk.viewer.trackedEntity) {
_this.sdk.viewer.trackedEntity.position = position
// _this.sdk.viewer.camera.position = position
}
}
else {
if (_this.sdk.viewer.trackedEntity) {
_this.sdk.viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees(coordinates.lng, coordinates.lat, _this.sdk.viewer.camera.positionCartographic.height),
orientation: {
heading: Cesium.Math.toRadians(-90),
pitch: 0,
roll: 0
}
})
}
}
}
}
}
// function executeAnimate() {
// }
// setTimeout(() => {
// let i = 0
// function animate() {
// if (i < motionArray.length) {
// let result = motionArray[i].result;
// console.log(result)
// result.then((res) => {
// let position = Cesium.Cartesian3.fromDegrees(motionArray[i].lng, motionArray[i].lat, res[0].height)
// let HeadingPitchRoll = getHeadingPitchRoll(_this.model.position, position)
// let modeHeadingPitchRoll = Cesium.HeadingPitchRoll.fromDegrees(_this.options.model.heading, _this.options.model.pitch, _this.options.model.roll)
// let heading = 0
// let pitch = 0
// let roll = 0
// if (_this.options.routeDirection) {
// heading = (HeadingPitchRoll.heading - modeHeadingPitchRoll.heading) * (180 / Math.PI) - 90
// pitch = (HeadingPitchRoll.pitch - modeHeadingPitchRoll.pitch) * (180 / Math.PI)
// }
// else {
// heading = - _this.options.model.heading
// pitch = - _this.options.model.pitch
// }
// roll = - _this.options.model.roll
// // console.log(heading)
// let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(position)
// _this.model.modelMatrix = Cesium.Matrix4.multiplyByMatrix3(matrix, Cesium.Matrix3.fromHeadingPitchRoll(Cesium.HeadingPitchRoll.fromDegrees(heading, pitch, roll)), _this.model.modelMatrix)
// _this.model.position = position
// if (_this.sdk.viewer.trackedEntity) {
// _this.sdk.viewer.trackedEntity.position = position
// }
// i++
// requestAnimationFrame(animate);
// })
// }
// }
// animate();
// }, 2000);
// 根据两个坐标点,获取Heading(朝向)
function getHeadingPitchRoll(pointA, pointB) {
// console.log(distance, _this.cartesian3Towgs84(pointA, viewer), _this.cartesian3Towgs84(pointB, viewer))
//建立以点A为原点X轴为east,Y轴为north,Z轴朝上的坐标系
const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
//向量AB
if (!pointB) {
return
}
const positionvector = Cesium.Cartesian3.subtract(pointB, pointA, new Cesium.Cartesian3());
//因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵
//AB为世界坐标中的向量
//因此将AB向量转换为A原点坐标系中的向量需乘以transform的逆矩阵。
const vector = Cesium.Matrix4.multiplyByPointAsVector(
Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()),
positionvector,
new Cesium.Cartesian3()
);
//归一化
const direction = Cesium.Cartesian3.normalize(vector, new Cesium.Cartesian3());
// console.log(direction)
//heading
const heading = Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO;
const pitch = Cesium.Math.PI_OVER_TWO - Cesium.Math.acosClamped(direction.z);
// console.log(pitch * (180 / Math.PI))
const roll = Cesium.Math.fastApproximateAtan2(direction.x, direction.z);
// console.log({heading: heading * (180 / Math.PI), pitch: pitch * (180 / Math.PI), roll: roll * (180 / Math.PI)})
return { heading: Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading), pitch: pitch, roll: roll };
}
}
setMovePositionByDistance(distance) {
let positions_smooth = this.renewLinePositions(this.options.line.positions)
this.modelMove(positions_smooth, { distance: distance })
}
setMovePositionByTime(time) {
let positions_smooth = this.renewLinePositions(this.options.line.positions)
this.modelMove(positions_smooth, { time: time })
}
// 编辑框
async edit(state) {
if (this._error) {
return
}
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
if (state) {
this._DialogObject = await new Dialog(this.sdk, this.options, {
title: '轨迹运动属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.name.trim()
if (!this.name) {
this.name = '未命名对象'
}
this.originalOptions = this.deepCopyObj(this.options)
// this.options.viewFollowOrientation = {}
// this.options.viewFollowOrientation.heading = Cesium.Math.toDegrees(this.sdk.viewer.camera.heading)
// this.options.viewFollowOrientation.pitch = Cesium.Math.toDegrees(this.sdk.viewer.camera.pitch)
// this.options.viewFollowOrientation.roll = Cesium.Math.toDegrees(this.sdk.viewer.camera.roll)
// this.options.viewFollowOrientation.direction = this.sdk.viewer.camera.direction
this._DialogObject.close()
let cdoptions = this.deepCopyObj(this.options)
cdoptions.host = ''
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(cdoptions)
2025-07-03 13:54:01 +08:00
syncData(this.sdk, this.options.id)
syncSplitData(this.sdk, this.options.id)
},
removeCallBack: () => {
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
this.sdk.viewer.trackedEntity = null
}
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this._DialogObject = null
this.reset()
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
if (this.editObj) {
this.editObj.destroy()
this.editObj = null
}
this.keyPointShow = false
this.event && this.event.destroy()
this.tip && this.tip.destroy()
this.tip = null
this.ControllerObject.destroy()
if (this.firstPersonView !== this.originalOptions.firstPersonView) {
2025-07-03 13:54:01 +08:00
this.firstPersonView = this.originalOptions.firstPersonView;
}
if (this.firstPersonView && this.modelShow) {
2025-07-03 13:54:01 +08:00
this.model && (this.model.show = false)
}
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
// this.options.show = show
// this.model && (this.model.show = show)
// this.line && (this.line.show = show)
}
})
this._DialogObject._element.body.className = this._DialogObject._element.body.className + ' trajectory-motion'
let contentElm = document.createElement('div');
contentElm.innerHTML = html()
this._DialogObject.contentAppChild(contentElm)
if (this.editObj) {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '结束调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn is-active'
}
else {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '开始调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn'
}
2025-07-16 15:02:18 +08:00
let labelColorPicker = new YJColorPicker({
2025-07-03 13:54:01 +08:00
el: contentElm.getElementsByClassName("labelColor")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.labelColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.labelColor = color
},//点击确认按钮事件回调
clear: () => {
this.labelColor = ''
},//点击清空按钮事件回调
})
let heightBoxElm = this._DialogObject._element.content.getElementsByClassName('height-box')[0]
let all_elm = contentElm.getElementsByTagName("*")
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
this._elms.heightBox = heightBoxElm
this._elms.labelColor = [labelColorPicker]
if (this.model) {
const getAnimationsList = () => {
let animations = this.model.loader.components.animations
if (this._DialogObject) {
if (animations) {
let tagData = [
{
name: '无',
value: '无',
}
]
for (let i = 0; i < animations.length; i++) {
tagData.push(
{
name: animations[i].name,
value: animations[i].name
}
)
}
legp(this._DialogObject._element.content, ".model-animate-select").legp_search(tagData)
}
let selectElm = contentElm.getElementsByClassName('model-animate-select')[0].getElementsByTagName('input')[0]
selectElm.value = this.modelAnimate
selectElm.addEventListener('input', (e, c) => {
this.modelAnimate = selectElm.value
})
}
}
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
if (this.model.ready) {
getAnimationsList()
}
else {
this.model.readyEvent.addEventListener(() => {
getAnimationsList()
})
}
}
else {
this.model.readyPromise.then((entity) => {
getAnimationsList()
})
}
}
if (this.ground) {
this._elms.heightBox && (this._elms.heightBox.className = 'input-number input-number-unit-1 height-box disabled');
}
else {
this._elms.heightBox && (this._elms.heightBox.className = 'input-number input-number-unit-1 height-box');
}
let e_firstPerson = contentElm.querySelectorAll("button[name='firstPerson']")
e_firstPerson[0].addEventListener('click', (e) => {
let splitSdk = getSdk()
if (!get2DView() && !splitSdk.sdkD) {
if (!this.firstPersonView) {
this.viewFollow = true
}
this.firstPersonView = true
}
})
e_firstPerson[1].addEventListener('click', (e) => {
if (this.firstPersonView) {
this.viewFollow = true
}
this.firstPersonView = false
})
if (this.options.firstPersonView) {
e_firstPerson[0].className = 'btn is-active'
e_firstPerson[1].className = 'btn'
if (this.sdk.viewer.trackedEntity) {
this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
this.sdk.viewer.trackedEntity = null
}
}
else {
e_firstPerson[0].className = 'btn'
e_firstPerson[1].className = 'btn is-active'
}
let rubricElm = document.createElement('div')
rubricElm.className = 'custom-rubric-box'
rubricElm.style.transformOrigin = 'center bottom'
rubricElm.style.position = 'absolute';
rubricElm.style.top = '180px';
rubricElm.style.right = '3px';
rubricElm.style.padding = '5px 10px';
rubricElm.style.backgroundColor = '#3e4249';
rubricElm.style.borderRadius = '5px';
rubricElm.style.fontSize = '12px';
rubricElm.style.color = '#ff5733';
rubricElm.style.display = 'none'
2025-08-22 16:05:40 +08:00
rubricElm.innerHTML = `场景正东方向为轨迹前进正方向<div x-arrow="" class="custom__popper__arrow" style="left: 59px;"></div>`
2025-07-03 13:54:01 +08:00
let iconRubric = contentElm.getElementsByClassName('icon-rubric')[0]
iconRubric.addEventListener('mouseenter', (e) => {
rubricElm.style.display = 'block'
})
document.addEventListener('mousemove', (event) => {
// 检查点击的元素是否在模态框内容区域之外
if (!iconRubric.contains(event.target)) {
rubricElm.style.display = 'none';
}
});
this._DialogObject._element.content.appendChild(rubricElm)
setTimeout(() => {
let fontData = getFontList()
let fontObject = legp(
this._DialogObject._element.content.getElementsByClassName(
'font-select-box'
)[0],
'.font-select'
)
if (fontObject) {
fontObject.legp_search(fontData)
let fontDataLegpElm = this._DialogObject._element.content
.getElementsByClassName('font-select')[0]
.getElementsByTagName('input')[0]
fontDataLegpElm.value = fontData[this.labelFontFamily].value
for (let i = 0; i < fontData.length; i++) {
if (fontData[i].value == fontDataLegpElm.value) {
fontObject.legp_searchActive(fontData[i].value)
break
}
}
fontDataLegpElm.addEventListener('input', () => {
for (let i = 0; i < fontData.length; i++) {
if (fontData[i].value === fontDataLegpElm.value) {
this.labelFontFamily = fontData[i].key
break
}
}
})
this._elms.labelFontFamily = [fontDataLegpElm]
}
}, 0)
}
}
flyTo(options = {}) {
setActiveViewer(0)
closeRotateAround(this.sdk)
if (this.options.customView) {
this.sdk.viewer.camera.flyTo({
destination: this.options.customView.position,
orientation: this.options.customView.orientation
})
}
else {
this.line && this.sdk.viewer.flyTo(this.line, {
offset: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-60.0),
roll: Cesium.Math.toRadians(0.0)
}
})
}
}
async remove() {
this.event && this.event.destroy()
this.tip && this.tip.destroy()
this.sdk.viewer.scene.primitives.remove(this.model)
this.sdk.viewer.entities.remove(this.line)
this.sdk.viewer.entities.remove(this.realTimeLine)
this.label && this.label.remove()
2025-08-21 16:37:49 +08:00
this.fuelLabel && this.fuelLabel.remove()
2025-07-03 13:54:01 +08:00
for (let i = 0; i < this.keyPointShow.length; i++) {
this.sdk.viewer.entities.remove(this.keyPointShow[i])
}
this.line = null
this.realTimeLine = null
this.model = null
this.label = null
2025-08-21 16:37:49 +08:00
this.fuelLabel = null
2025-07-03 13:54:01 +08:00
if (this._DialogObject && !this._DialogObject.isDestroy) {
this._DialogObject.close()
this._DialogObject = null
}
if (this.#mouseRightevent) {
this.#mouseRightevent.destroy()
}
this.removeModelAnimate()
let sdk2D = get2DView()
if (!sdk2D || sdk2D !== this.sdk) {
this.viewFollow = false
}
cancelAnimationFrame(this.#_requestAnimationFrameEventId)
await this.sdk.removeIncetance(this.options.id)
await syncData(this.sdk, this.options.id)
}
async reset() {
(this.options.model.url !== this.originalOptions.model.url) && this.changeModelUrl(this.originalOptions.model.url);
this.name = this.originalOptions.name;
if (JSON.stringify(this.options.line.positions) !== JSON.stringify(this.originalOptions.line.positions)) {
this.options.line.positions = this.deepCopyObj(this.originalOptions.line.positions);
let positions = this.renewLinePositions(this.options.line.positions)
this.line.polyline.positions = positions
setTimeout(() => {
this.model.position = positions[0];
this.modelMove(positions)
}, 0);
}
this.modelShow = this.originalOptions.model.show;
(this.noseToTail !== this.originalOptions.line.noseToTail) && (this.noseToTail = this.originalOptions.line.noseToTail);
(this.height !== this.originalOptions.height) && (this.height = this.originalOptions.height);
(this.lineShow !== this.originalOptions.line.show) && (this.lineShow = this.originalOptions.line.show);
this.keyPointShow = this.originalOptions.line.keyPoint;
this.routeDirection = this.originalOptions.routeDirection;
this.scale = this.originalOptions.model.scale;
(this.loop !== this.originalOptions.loop) && (this.loop = this.originalOptions.loop);
this.viewFollow = this.originalOptions.viewFollow;
this.state = this.originalOptions.state;
this.speed = this.originalOptions.speed;
(this.smooth !== this.originalOptions.line.smooth) && (this.smooth = this.originalOptions.line.smooth);
this.realTimeRoute = this.originalOptions.realTimeRoute;
this.modelAnimate = this.originalOptions.model.animate;
this.delay = this.originalOptions.delay;
(this.ground !== this.originalOptions.ground) && (this.ground = this.originalOptions.ground);
if (this.firstPersonView !== this.originalOptions.firstPersonView) {
2025-07-03 13:54:01 +08:00
this.firstPersonView = this.originalOptions.firstPersonView;
}
if (this.firstPersonView && this.modelShow) {
2025-07-03 13:54:01 +08:00
this.model && (this.model.show = false)
}
this.labelShow = this.originalOptions.label.show
2025-08-21 16:37:49 +08:00
this.fuelLabelShow = this.originalOptions.fuelShow
2025-07-03 13:54:01 +08:00
this.labelColor = this.originalOptions.label.color
this.labelFontSize = this.originalOptions.label.fontSize
this.labelFontFamily = this.originalOptions.label.fontFamily
this.labelScaleByDistance = this.originalOptions.label.scaleByDistance
this.labelNear = this.originalOptions.label.near
this.labelFar = this.originalOptions.label.far
this.labelLineWidth = this.originalOptions.label.lineWidth
this.labelPixelOffset = this.originalOptions.label.pixelOffset
this.labelLineColor = this.originalOptions.label.lineColor
this.labelBackgroundColorStart = this.originalOptions.label.backgroundColor[0]
this.labelBackgroundColorEnd = this.originalOptions.label.backgroundColor[1]
this.options = this.deepCopyObj(this.originalOptions);
}
// viewFollow(e) {
// if (e.target.checked) {
// var pointEntity = this.sdk.viewer.entities.add({
// // show: false,
// position: this.positions_smooth[0], // position of the point
// point: {
// color: Cesium.Color.RED.withAlpha(0), // color of the point
// pixelSize: 0
// }
// });
// this.sdk.viewer.trackedEntity = pointEntity;
// }
// else {
// this.sdk.viewer.entities.remove(this.sdk.viewer.trackedEntity)
// this.sdk.viewer.trackedEntity = null
// }
// }
modelRotate() {
if (this.editObj) {
this.editObj.destroy()
this.editObj = null
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '开始调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn'
}
}
else {
if (this.viewFollow) {
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll();
window.ELEMENT.Message({
message: '关闭视角跟随后可调整模型方向!',
type: 'warning',
duration: 1500
});
console.warn('关闭视角跟随后可调整模型方向!')
}
}
else {
if (this._DialogObject && this._DialogObject._element && this._DialogObject._element.content) {
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].innerHTML = '结束调整'
this._DialogObject._element.content.getElementsByClassName('model-rotate-btn')[0].className = 'btn model-rotate-btn is-active'
}
this.state = false
this.editObj = new EditGltf(this.sdk, this.model)
this.editObj.editRtation()
this.editObj.transformCallBack = this.rotationEditingCallBack
this.routeDirection = false
let heading = this.options.model.heading
let pitch = this.options.model.pitch
let roll = this.options.model.roll
if (isNaN(heading) || isNaN(pitch) || isNaN(roll)) {
return
}
let matrix = Cesium.Transforms.eastNorthUpToFixedFrame(this.model.position)
// 旋转
let mx = Cesium.Matrix3.fromRotationX(
Cesium.Math.toRadians(roll)
)
let my = Cesium.Matrix3.fromRotationY(
Cesium.Math.toRadians(pitch)
)
let mz = Cesium.Matrix3.fromRotationZ(
Cesium.Math.toRadians(heading)
)
let rotationX = Cesium.Matrix4.fromRotationTranslation(mx)
let rotationY = Cesium.Matrix4.fromRotationTranslation(my)
let rotationZ = Cesium.Matrix4.fromRotationTranslation(mz)
let originalMatrix = new Cesium.Matrix4()
Cesium.Matrix4.multiply(matrix, rotationX, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
Cesium.Matrix4.multiply(originalMatrix, rotationZ, this.entity.modelMatrix)
}
}
}
clickChangeModel() {
this.Dialog.changeModelCallBack && this.Dialog.changeModelCallBack()
}
//旋转时,坐标信息变化的回调
set rotationEditingCallBack(callback) {
this._rotationEditingCallBack = callback
}
get rotationEditingCallBack() {
return (params) => {
this.options.model.heading = params.rz
this.options.model.pitch = params.ry
this.options.model.roll = params.rx
this._rotationEditingCallBack && this._rotationEditingCallBack(this.editObj._params)
this.entity && (this.entity.isMove = true)
clearTimeout(this.#timeoutEventObject)
this.#timeoutEventObject = setTimeout(() => {
this.entity && (this.entity.isMove = false)
}, 500);
}
}
async changeModelUrl(url) {
this.sdk.viewer.scene.primitives.remove(this.model)
this.options.model.url = this.replaceHost(url, this.options.host)
2025-07-03 13:54:01 +08:00
let matrix = this.model.modelMatrix
let position = this.model.position
let options = {
id: this.options.id,
url: this.options.model.url,
show: this.options.model.show,
scale: this.options.model.scale,
// minimumPixelSize: this.options.model.pixelSize,
// maximumScale: 100000,
}
const getAnimationsList = () => {
if (this.options.model.url === this.originalOptions.model.url) {
this.modelAnimate = this.originalOptions.model.animate
}
else {
this.options.model.animate = '无'
}
let animations = this.model.loader.components.animations
if (this._DialogObject) {
if (animations) {
let tagData = [
{
name: '无',
value: '无',
}
]
for (let i = 0; i < animations.length; i++) {
tagData.push(
{
name: animations[i].name,
value: animations[i].name
}
)
}
legp(this._DialogObject._element.content, ".model-animate-select").legp_search(tagData)
}
let selectElm = this._DialogObject._element.content.getElementsByClassName('model-animate-select')[0].getElementsByTagName('input')[0]
selectElm.value = this.modelAnimate
selectElm.addEventListener('input', (e, c) => {
this.modelAnimate = selectElm.value
})
}
}
if (Number(Cesium.VERSION.split('.')[1]) >= 107) {
this.model = await Cesium.Model.fromGltfAsync(options)
this.model.position = position
this.sdk.viewer.scene.primitives.add(this.model)
this.model.readyEvent.addEventListener(() => {
getAnimationsList()
this.model.modelMatrix = matrix
})
}
else {
this.model = this.sdk.viewer.scene.primitives.add(
Cesium.Model.fromGltf(options)
);
this.model.position = position
this.model.readyPromise.then((entity) => {
getAnimationsList()
this.model.modelMatrix = matrix
})
}
this.model.imageBasedLighting.luminanceAtZenith = 0.6
}
// 移除动画
removeModelAnimate() {
if (this.TweenAnimate) {
clearTimeout(this.TweenAnimate.timeout)
TWEEN.remove(this.TweenAnimate)
this.TweenAnimate = null
}
// if (modelPrimitive && modelPrimitive._activeAnimations && modelPrimitive._activeAnimations._runtimeAnimations) {
// let runtimeAnimation = modelPrimitive._activeAnimations._runtimeAnimations
// for (let i = runtimeAnimation.length - 1; i >= 0; i--) {
// switch (runtimeAnimation[i].name) {
// case '跑':
// modelPrimitive.activeAnimations.remove(runtimeAnimation[i])
// break;
// default:
// }
// }
// }
}
set controllerCallBack(callback) {
this._controllerCallBack = callback
}
get controllerCallBack() {
return (params) => {
}
}
// 更新坐标
renewLinePositions(pos) {
let positions = pos
if (this.noseToTail) {
positions = [...pos, pos[0]]
}
let fromDegreesArrayHeights = []
let time = []
let positions_smooth = []
for (let i = 0; i < positions.length; i++) {
fromDegreesArrayHeights.push(positions[i].lng, positions[i].lat, positions[i].alt)
time.push(i / (positions.length - 1))
}
if (this.smooth) {
this.spline = new Cesium.CatmullRomSpline({
times: time,
points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights)
});
}
else {
this.spline = new Cesium.LinearSpline({
times: time,
points: Cesium.Cartesian3.fromDegreesArrayHeights(fromDegreesArrayHeights)
});
}
for (let i = 0; i <= 1000; i++) {
let cartesian3 = this.spline.evaluate(i / 1000);
positions_smooth.push(cartesian3);
}
this.positions_smooth = positions_smooth
return positions_smooth
}
flicker() { }
}
export default TrajectoryMotion