Files
sdk4.0/src/Obj/Base/BaseSource/BaseModel/Model2/index.js
2025-07-16 15:02:18 +08:00

1350 lines
48 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { getHost } from "../../../../../on";
import { html, css } from "./_element";
import Dialog from '../../../../Element/Dialog';
import EventBinding from '../../../../Element/Dialog/eventBinding';
import cy_tabs from "../../../../Element/cy_html_tabs";
import Controller from "../../../../../Controller/index";
import LabelObject from "../../../LabelObject";
import { openLeftClick, closeLeftClick, openRightClick, closeRightClick, getLeftClickState, getRightClickState } from "../../../../../Global/ClickCallback"
import BaseModel from "../index";
import { legp } from '../../../../Element/datalist';
import { setActiveViewer, closeRotateAround, closeViewFollow} from '../../../../../Global/global'
class Model2 extends BaseModel {
/**
* @constructor
* @description 加载模型
* @param sdk {object} sdk
* @param options {object} 模型参数
* @param options.id {string} 对象id
* @param options.show=true {boolean} 模型显隐
* @param options.name {string} 名称
* @param options.url {string} 资源地址
* @param options.positions {Array.<object>} 坐标数组 [{lng,lat,alt},...]
* @param options.height {number} 高程,为空时取坐标中最低高程
* @param options.type=0 {number} 类型 0:点1:线2:多边形3:矩形
* @param options.interval=1 {number} 间隔(米)type=0时不生效
* @param options.quantity {object} 数量type=3时生效
* @param options.quantity.x {number} x轴方向数量type=3时生效
* @param options.quantity.y {number} y轴方向数量type=3时生效
* @param options.scale=1 {number} 比例
* @param options.maximumScale=100 {number} 最大比例
* @param options.minimumPixelSize=60 {number} 最小像素
* @param options.scaleByDistance=true {boolean} 随视野缩放
* @param options.rotate {object} 旋转角度
* @param options.rotate.x {number} x轴旋转度数
* @param options.rotate.y {number} y轴旋转度数
* @param options.rotate.z {number} z轴旋转度数
* */
constructor(earth, options = {}, _Dialog = {}) {
super(earth, options, _Dialog = {})
this.picking = true
this.options.name = options.name || '未命名对象'
this.options.color = options.color || '#ffffff'
this.options.scale = (options.scale || options.scale === 0) ? options.scale : 1
this.options.url = options.url
this.options.maximumScale = (options.maximumScale || options.maximumScale === 0) ? options.maximumScale : 100
this.options.minimumPixelSize = (options.minimumPixelSize || options.minimumPixelSize === 0) ? options.minimumPixelSize : 60
this.options.positions = options.positions || []
this.options.type = options.type || 0
this.options.interval = (options.interval || options.interval === 0) ? options.interval : 1
this.options.quantity = options.quantity
this.options.scaleByDistance = (options.scaleByDistance || options.scaleByDistance === false) ? options.scaleByDistance : true
this.options.rotate = options.rotate = (options.rotate || {})
this.options.rotate.x = options.rotate.x || 0
this.options.rotate.y = options.rotate.y || 0
this.options.rotate.z = options.rotate.z || 0
this.options.label = options.label = (options.label || {})
this.options.label.show = (options.label.show || options.label.show === false) ? options.label.show : false
this.options.label.fontSize = options.label.fontSize || 20
this.options.label.color = options.label.color || '#ffffff'
this.options.label.near = (options.label.near || options.label.near === 0) ? options.label.near : 2000
this.options.label.far = (options.label.far || options.label.far === 0) ? options.label.far : 100000
this.options.label.scaleByDistance = options.label.scaleByDistance || false
this.options.label.backgroundColor = options.label.backgroundColor || ['#42c6ef', '#42c6ef']
this.options.line = options.line = (options.line || {})
this.options.line.width = options.line.width || 2
this.options.line.length = options.line.length || 20
this.options.line.color = options.line.color || '#fff000'
this.options.attribute = options.attribute || {}
this.options.attribute.link = this.options.attribute.link || {}
this.options.attribute.link.content = this.options.attribute.link.content || []
this.options.attribute.camera = this.options.attribute.camera || []
this.options.attributeType = options.attributeType || 'richText'
this.ModelPositions = []
this._elms = {};
this.positionCallBack = null
this.rotationCallback = null
this.onClickCallback = null
this._DialogObject = null
this._element_style = null
this.ControllerObject = new Controller(this.sdk)
this.ControllerObject.controllerCallBack = (params) => {
this.lng = params.position.lng
this.lat = params.position.lat
this.alt = params.position.alt
// this.rotateX = params.rotate.x
// this.rotateY = params.rotate.y
// this.rotateZ = params.rotate.z
// this.updateModel(params.position.lng, params.position.lat, params.position.alt, params.rotate.x, params.rotate.y, params.rotate.z, this.options.scale)
}
this.Dialog = _Dialog
this._EventBinding = new EventBinding()
this.on()
}
get type() {
return "glb"
}
async loadModel(url) {
if (!url.startsWith("http")) {
//说明是本地的json在磁盘中存在的
if (!url.includes(":")) {
if (this.options.host) {
let o = new URL(url, this.options.host)
url = o.href
}
}
}
this.originalOptions = this.deepCopyObj(this.options)
const collection = new Cesium.PrimitiveCollection();
let positions = [[]]
let height = this.options.positions[0].alt
for (let i = 0; i < this.options.positions.length; i++) {
positions[0].push([this.options.positions[i].lng, this.options.positions[i].lat])
if (this.options.positions[i].alt > this.options.height) {
height = this.options.positions[i].alt
}
}
if (positions[0].length > 2) {
positions[0].push([this.options.positions[0].lng, this.options.positions[0].lat])
let polygon = turf.polygon(positions);
let centroid = turf.pointOnFeature(polygon);
this.center = { lng: centroid.geometry.coordinates[0], lat: centroid.geometry.coordinates[1] }
}
else if (positions[0].length == 2) {
this.center = { lng: (this.options.positions[0].lng + this.options.positions[1].lng) / 2, lat: (this.options.positions[0].lat + this.options.positions[1].lat) / 2 }
}
else {
this.center = { lng: this.options.positions[0].lng, lat: this.options.positions[0].lat }
}
let ModelPositions = []
if (!this.options.height && this.options.height !== 0) {
this.options.height = height
}
let grid
let scripts = document.scripts;
let turfUrl = ''
for (let i = 0; i < scripts.length; i++) {
if (scripts[i].src && scripts[i].src.includes('turf.min.js')) {
turfUrl = scripts[i].src && scripts[i].src
break
}
}
let params = {
type: this.options.type,
interval: this.options.interval,
positions: positions,
optionsPositions: this.options.positions,
quantity: this.options.quantity,
turfUrl: turfUrl
}
function threadFn({ type, interval, positions, optionsPositions, quantity, turfUrl }) {
importScripts(turfUrl);
let ModelPositions = []
switch (type) {
case 1:
let line = turf.lineString(positions[0]);
let chunk = turf.lineChunk(line, interval / 1000, { units: 'kilometers' });
ModelPositions.push({ lng: chunk.features[0].geometry.coordinates[0][0], lat: chunk.features[0].geometry.coordinates[0][1] })
for (let i = 0; i < chunk.features.length; i++) {
ModelPositions.push({ lng: chunk.features[i].geometry.coordinates[1][0], lat: chunk.features[i].geometry.coordinates[1][1] })
}
break;
case 2:
let polygon = turf.polygon(positions);
let bbox = turf.bbox(polygon);
grid = turf.pointGrid(bbox, interval / 1000, { units: 'kilometers' });
let ptsWithin = turf.pointsWithinPolygon(grid, polygon);
for (let i = 0; i < ptsWithin.features.length; i++) {
ModelPositions.push({ lng: ptsWithin.features[i].geometry.coordinates[0], lat: ptsWithin.features[i].geometry.coordinates[1] })
}
break;
case 3:
if (quantity) {
let minX = optionsPositions[0].lng
let minY = optionsPositions[0].lat
let maxX = optionsPositions[2].lng
let maxY = optionsPositions[2].lat
let fromX = turf.point([minX, maxY]);
let toX = turf.point([maxX, maxY]);
let distanceX = turf.distance(fromX, toX, { units: 'kilometers' });
let x = distanceX / quantity.x
let fromY = turf.point([minX, maxY]);
let toY = turf.point([minX, minY]);
let distanceY = turf.distance(fromY, toY, { units: 'kilometers' });
let y = distanceY / quantity.y
let lineX = turf.lineString([[minX, maxY], [maxX, maxY]]);
let chunkX = turf.lineChunk(lineX, x, { units: 'kilometers' });
let lineY = turf.lineString([[minX, maxY], [minX, minY]]);
let chunkY = turf.lineChunk(lineY, y, { units: 'kilometers' });
for (let i = 0; i < chunkX.features.length; i++) {
let Xcoordinates = chunkX.features[i].geometry.coordinates
for (let m = 0; m < chunkY.features.length; m++) {
let Ycoordinates = chunkY.features[m].geometry.coordinates
ModelPositions.push(
{
lng: (Xcoordinates[0][0] + Xcoordinates[1][0]) / 2,
lat: (Ycoordinates[0][1] + Ycoordinates[1][1]) / 2,
}
)
}
}
}
else {
grid = turf.pointGrid([optionsPositions[0].lng, optionsPositions[0].lat, optionsPositions[2].lng, optionsPositions[2].lat], interval / 1000, { units: 'kilometers' });
for (let i = 0; i < grid.features.length; i++) {
ModelPositions.push({ lng: grid.features[i].geometry.coordinates[0], lat: grid.features[i].geometry.coordinates[1] })
}
}
break;
default:
ModelPositions = [...optionsPositions]
}
self.postMessage(ModelPositions);
}
function createWorker(fn) {
const worker = new Worker(`data:,(${fn.toString()})(${JSON.stringify(params)})`)
return worker
}
const worker = createWorker(threadFn)
worker.onmessage = e => {
this.ModelPositions = ModelPositions = e.data
let instances = []
for (let i = 0; i < ModelPositions.length; i++) {
let heading = 0
let pitch = 0
let roll = 0
let scale = 1
// let cartographic = Cesium.Cartographic.fromDegrees(ModelPositions[i].lng, ModelPositions[i].lat, this.options.height);
let position = Cesium.Cartesian3.fromDegrees(
ModelPositions[i].lng, ModelPositions[i].lat, this.options.height
);
var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
position,
new Cesium.HeadingPitchRoll(heading, pitch, roll)
);
Cesium.Matrix4.multiplyByUniformScale(
modelMatrix,
scale,
modelMatrix
);
instances.push({
modelMatrix: modelMatrix
})
}
this.label = new LabelObject(this.sdk, {
show: this.options.show ? this.options.label.show : false,
position: [this.center.lng, this.center.lat, this.options.height],
text: this.options.name,
fontSize: this.options.label.fontSize,
color: this.options.label.color,
pixelOffset: this.options.line.length,
backgroundColor: this.options.label.backgroundColor,
lineColor: this.options.line.color,
lineWidth: this.options.line.width,
scaleByDistance: this.options.label.scaleByDistance,
near: this.options.label.near,
far: this.options.label.far
})
// this.entity = collection
this.entity = new Cesium2.ModelInstanceCollection({
url: url,
instances: instances
})
this.entity.position = new Cesium.Cartesian3.fromDegrees(this.center.lng, this.center.lat, this.options.height)
this.entity.rotate = { x: this.options.rotate.x, y: this.options.rotate.y, z: this.options.rotate.z };
this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this.sdk.viewer.scene.primitives.add(this.entity);
}
}
remove() {
super.remove()
this.label.remove()
this.positionEditing = false
this.sdk.viewer.scene.primitives.remove(this.entity);
this.entity = null
if (this._DialogObject) {
this._DialogObject.close()
this._DialogObject = null
}
}
async flyTo() {
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
if (this.options.customView && this.options.customView.relativePosition && this.options.customView.orientation) {
let orientation = {
heading: Cesium.Math.toRadians(this.options.customView.orientation.heading || 0.0),
pitch: Cesium.Math.toRadians(this.options.customView.orientation.pitch || -60.0),
roll: Cesium.Math.toRadians(this.options.customView.orientation.roll || 0.0)
}
let lng = this.options.customView.relativePosition.lng
let lat = this.options.customView.relativePosition.lat
let alt = this.options.customView.relativePosition.alt
let destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
let position = { lng: 0, lat: 0 }
if (this.options.position) {
position = { ...this.options.position }
}
else if (this.options.positions) {
position = { ...this.options.positions[0] }
}
else if (this.options.center) {
position = { ...this.options.center }
}
else if (this.options.start) {
position = { ...this.options.start }
}
else {
if (this.options.hasOwnProperty('lng')) {
position.lng = this.options.lng
}
if (this.options.hasOwnProperty('lat')) {
position.lat = this.options.lat
}
if (this.options.hasOwnProperty('alt')) {
position.alt = this.options.alt
}
}
// 如果没有高度值,则获取紧贴高度计算
if (!position.hasOwnProperty('alt')) {
position.alt = await this.getClampToHeight(position)
}
lng = this.options.customView.relativePosition.lng + position.lng
lat = this.options.customView.relativePosition.lat + position.lat
alt = this.options.customView.relativePosition.alt + position.alt
destination = Cesium.Cartesian3.fromDegrees(lng, lat, alt)
this.sdk.viewer.camera.flyTo({
destination: destination,
orientation: orientation
})
}
else {
this.sdk.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.center.lng, this.center.lat, this.options.height + 500)
})
}
// this.sdk.viewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(this.center.lng, this.center.lat, this.options.height)})
}
on() {
return this.add()
}
setDefaultValue() {
super.setDefaultValue()
this.options.host = this.options.host || getHost()
this.options.url = this.options.url || ""
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
this.entity.color = Cesium.Color.fromCssColorString(v)
if (this._elms.color) {
this._elms.color.forEach((item, i) => {
let colorPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: v,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (c) => {
this.color = c
},//点击确认按钮事件回调
clear: () => {
this.color = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.color[i] = colorPicker
})
}
}
get lng() {
return this.center.lng
}
set lng(v) {
this.center.lng = v
this._ControllerChangePosition(50)
this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this.label.position = [this.center.lng, this.center.lat, this.options.height]
this._elms.lng && this._elms.lng.forEach((item) => {
item.value = v
})
}
get lat() {
return this.center.lat
}
set lat(v) {
this.center.lat = v
this._ControllerChangePosition(50)
this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this.label.position = [this.center.lng, this.center.lat, this.options.height]
this._elms.lat && this._elms.lat.forEach((item) => {
item.value = v
})
}
get alt() {
return this.options.height
}
set alt(v) {
this.center.alt = v
this.options.height = v
this._ControllerChangePosition(50)
this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this.label.position = [Number(this.center.lng), Number(this.center.lat), Number(this.options.height)]
this._elms.alt && this._elms.alt.forEach((item) => {
item.value = v
})
}
_ControllerChangePosition(delay) {
let _this = this
clearTimeout(_this._ControllerChangePositionEvent);
_this._ControllerChangePositionEvent = setTimeout(() => {
_this.ControllerObject.position = {
lng: _this.center.lng,
lat: _this.center.lat,
alt: _this.options.height
}
}, delay);
}
get maximumScale() {
return this.options.maximumScale
}
set maximumScale(v) {
this.options.maximumScale = v
this.entity.maximumScale = this.scaleByDistance ? undefined : v
this._elms.maximumScale && this._elms.maximumScale.forEach((item) => {
item.value = v
})
}
get minimumPixelSize() {
return this.options.minimumPixelSize
}
set minimumPixelSize(v) {
this.options.minimumPixelSize = v
this.entity.minimumPixelSize = this.scaleByDistance ? undefined : v
this._elms.minimumPixelSize && this._elms.minimumPixelSize.forEach((item) => {
item.value = v
})
}
get scaleByDistance() {
return this.options.scaleByDistance
}
set scaleByDistance(v) {
this.options.scaleByDistance = v
this.entity.maximumScale = v ? undefined : this.maximumScale
this.entity.minimumPixelSize = v ? undefined : this.minimumPixelSize
this._elms.scaleByDistance && this._elms.scaleByDistance.forEach((item) => {
item.checked = v
})
}
get rotateX() {
return this.options.rotate.x
}
set rotateX(v) {
this.options.rotate.x = v
this.updateModelRotate(this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
// this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this._elms.rotateX && this._elms.rotateX.forEach((item) => {
item.value = v
})
}
get rotateY() {
return this.options.rotate.y
}
set rotateY(v) {
this.options.rotate.y = v
this.updateModelRotate(this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
// this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this._elms.rotateY && this._elms.rotateY.forEach((item) => {
item.value = v
})
}
get rotateZ() {
return this.options.rotate.z
}
set rotateZ(v) {
this.options.rotate.z = v
this.updateModelRotate(this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
// this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this._elms.rotateZ && this._elms.rotateZ.forEach((item) => {
item.value = v
})
}
get scale() {
return this.options.scale
}
set scale(v) {
this.options.scale = v
this.updateModelRotate(this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
// this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this._elms.scale && this._elms.scale.forEach((item) => {
item.value = v
})
}
get labelShow() {
return this.options.label.show
}
set labelShow(v) {
this.options.label.show = v
if (this.show) {
this.label.show = v
}
else {
this.label.show = false
}
this._elms.labelShow && this._elms.labelShow.forEach((item) => {
item.checked = v
})
}
get labelFontSize() {
return this.options.label.fontSize
}
set labelFontSize(v) {
this.options.label.fontSize = v
this.label.fontSize = v
this._elms.labelFontSize && this._elms.labelFontSize.forEach((item) => {
item.value = v
})
}
get labelColor() {
return this.options.label.color
}
set labelColor(v) {
this.options.label.color = v
this.label.color = v
if (this._elms.labelColor) {
this._elms.labelColor.forEach((item, i) => {
let labelColorPicker = new YJColorPicker({
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 labelScaleByDistance() {
return this.options.label.scaleByDistance
}
set labelScaleByDistance(v) {
this.options.label.scaleByDistance = v
this.label.scaleByDistance = v
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.near = near
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.far = far
this._elms.labelFar && this._elms.labelFar.forEach((item) => {
item.value = far
})
}
get lineWidth() {
return this.options.line.width
}
set lineWidth(v) {
this.options.line.width = v
this.label.lineWidth = v
this._elms.lineWidth && this._elms.lineWidth.forEach((item) => {
item.value = v
})
}
get lineLength() {
return this.options.line.length
}
set lineLength(v) {
this.options.line.length = v
this.label.pixelOffset = v
this._elms.lineLength && this._elms.lineLength.forEach((item) => {
item.value = v
})
}
get lineColor() {
return this.options.line.color
}
set lineColor(v) {
this.options.line.color = v
this.label.lineColor = v
if (this._elms.lineColor) {
this._elms.lineColor.forEach((item, i) => {
let lineColorPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.lineColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.lineColor = color
},//点击确认按钮事件回调
clear: () => {
this.lineColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.lineColor[i] = lineColorPicker
})
}
}
get labelBackgroundColorStart() {
return this.options.label.backgroundColor[0]
}
set labelBackgroundColorStart(v) {
this.options.label.backgroundColor[0] = v
this.label.backgroundColor = [v, this.labelBackgroundColorEnd]
if (this._elms.labelBackgroundColorStart) {
this._elms.labelBackgroundColorStart.forEach((item, i) => {
let labelBackgroundColorStartPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.labelBackgroundColorStart,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.labelBackgroundColorStart = color
},//点击确认按钮事件回调
clear: () => {
this.labelBackgroundColorStart = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.labelBackgroundColorStart[i] = labelBackgroundColorStartPicker
})
}
}
get labelBackgroundColorEnd() {
return this.options.label.backgroundColor[1]
}
set labelBackgroundColorEnd(v) {
this.options.label.backgroundColor[1] = v
this.label.backgroundColor = [this.labelBackgroundColorStart, v]
if (this._elms.labelBackgroundColorEnd) {
this._elms.labelBackgroundColorEnd.forEach((item, i) => {
let labelBackgroundColorEndPicker = new YJColorPicker({
el: item.el,
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.labelBackgroundColorEnd,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.labelBackgroundColorEnd = color
},//点击确认按钮事件回调
clear: () => {
this.labelBackgroundColorEnd = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
this._elms.labelBackgroundColorEnd[i] = labelBackgroundColorEndPicker
})
}
}
get attributeType() {
return this.options.attributeType
}
set attributeType(v) {
this.options.attributeType = v
this._elms.attributeType && this._elms.attributeType.forEach((item) => {
item.value = v
})
let attributeContent = this._DialogObject._element.content.getElementsByClassName('attribute-content')
for (let i = 0; i < attributeContent.length; i++) {
if (attributeContent[i].className.indexOf('attribute-content-' + v) > -1) {
attributeContent[i].style.display = 'block';
}
else {
attributeContent[i].style.display = 'none';
}
}
}
get attributeLink() {
return this.options.attribute.link.content
}
set attributeLink(v) {
this.options.attribute.link.content = v
if (!this._DialogObject || !this._DialogObject._element || !this._DialogObject._element.content || this._DialogObject._element.content.getElementsByClassName('attribute-content-link').length == 0) {
return
}
let table = this._DialogObject._element.content.getElementsByClassName('attribute-content-link')[1].getElementsByClassName('table')[0]
let tableContent = table.getElementsByClassName('table-body')[0]
tableContent.innerHTML = ''
if (this.options.attribute.link.content.length > 0) {
table.getElementsByClassName('table-empty')[0].style.display = 'none'
}
else {
table.getElementsByClassName('table-empty')[0].style.display = 'flex'
}
for (let i = 0; i < this.options.attribute.link.content.length; i++) {
let tr = `
<div class="tr">
<div class="td">` + this.options.attribute.link.content[i].name + `</div>
<div class="td">` + this.options.attribute.link.content[i].url + `</div>
<div class="td">
<button @click="linkEdit">编辑</button>
<button @click="linkDelete">删除</button>
</div>
</div>`
let trElm = document.createRange().createContextualFragment(tr)
tableContent.appendChild(trElm)
}
let item = tableContent.getElementsByClassName('tr')
let fun = {
linkEdit: async (index) => {
this.attributeLink = await this.options.attribute.link.content
let table = this._DialogObject._element.content.getElementsByClassName('attribute-content-link')[1].getElementsByClassName('table')[0]
let tableContent = table.getElementsByClassName('table-body')[0]
let item = tableContent.getElementsByClassName('tr')
for (let i = 0; i < item.length; i++) {
if (index === i) {
let height = item[i].offsetHeight
let html = `
<div class="td">
<input class="input" type="text">
</div>
<div class="td">
<textarea class="input link-edit" type="text"></textarea>
</div>
<div class="td">
<button @click="confirmEdit">确认</button>
<button @click="cancelEdit">取消</button>
</div>`
item[i].innerHTML = html
let textareaElm = item[i].getElementsByClassName('link-edit')[0]
textareaElm.style.height = (height - 10) + 'px'
let td = item[i].getElementsByClassName('td')
td[0].getElementsByClassName('input')[0].value = this.options.attribute.link.content[index].name
td[1].getElementsByClassName('input')[0].value = this.options.attribute.link.content[index].url
let btn = item[i].getElementsByTagName('button')
for (let n = 0; n < btn.length; n++) {
if (!btn[n] || !btn[n].attributes) {
continue
}
for (let m of btn[n].attributes) {
if (m.name === '@click') {
btn[n].addEventListener('click', (e) => {
if (typeof (fun[m.value]) === 'function') {
fun[m.value]({ name: td[0].getElementsByClassName('input')[0].value, url: td[1].getElementsByClassName('input')[0].value }, i)
}
});
btn[n].attributes.removeNamedItem(m.name)
break
}
}
}
break
}
}
},
linkDelete: (i) => {
this.options.attribute.link.content.splice(i, 1)
this.attributeLink = this.options.attribute.link.content
},
confirmEdit: (value, i) => {
let name = value.name && value.name.replace(/\s/g, "")
let url = value.url && value.url.replace(/\s/g, "")
if(name && url) {
this.options.attribute.link.content[i] = value
}
else {
window.ELEMENT && window.ELEMENT.Message({
message: '名称或链接不能为空!',
type: 'warning',
duration: 1500
});
}
this.attributeLink = this.options.attribute.link.content
},
cancelEdit: () => {
this.attributeLink = this.options.attribute.link.content
},
fileSelect: (value, i) => {
let fileElm = item[i].getElementsByClassName('file-select')[0]
fileElm.click()
fileElm.removeEventListener('change', fileSelect)
fileElm.addEventListener('change', fileSelect)
}
}
let fileSelect = (event) => {
if (event.target.value) {
let td = item[event.target.getAttribute('index')].getElementsByClassName('td')
td[1].getElementsByClassName('input')[0].value = event.target.value
event.target.value = null
}
}
for (let i = 0; i < item.length; i++) {
let btn = item[i].getElementsByTagName('button')
for (let n = 0; n < btn.length; n++) {
if (!btn[n] ||!btn[n].attributes) {
continue
}
for (let m of btn[n].attributes) {
if (m.name === '@click') {
btn[n].addEventListener('click', (e) => {
if (typeof (fun[m.value]) === 'function') {
fun[m.value](i)
}
});
btn[n].attributes.removeNamedItem(m.name)
break
}
}
}
}
}
get attributeCamera() {
return this.options.attribute.camera
}
set attributeCamera(v) {
this.options.attribute.camera = v
}
// get position() {
// let cartographic = Cesium.Cartographic.fromCartesian(this.entity.position);
// let lng = Cesium.Math.toDegrees(cartographic.longitude + 0.00000000663814);
// let lat = Cesium.Math.toDegrees(cartographic.latitude + 0.00000025137835);
// return { lng: lng, lat: lat, alt: cartographic.height - 2.19104611043234 }
// }
// set position(p) {
// }
/**
* @desc 打开模型旋转功能
* @param status {boolean}
* @methodOf Source
* */
set rotationEditing(status) {
if (status) {
this.ControllerObject.editRtation()
}
else {
this.ControllerObject.destroy()
}
}
/**
* @desc 获取模型旋转状态
* @method rotationEditing
* @return boolean
* @methodOf Source
* */
get rotationEditing() {
if (this.ControllerObject.getActiveState() === 'rtation') {
return true
}
return false
}
/**@desc 打开平移模型功能
*
* @memberOf Source
*@param status {boolean}
*
* */
set positionEditing(status) {
if (YJ.Measure.GetMeasureStatus() || !this.sdk || !this.sdk.viewer) {
return
}
if (status) {
this.leftClickState = getLeftClickState()
this.ControllerObject.position = {
lng: this.center.lng,
lat: this.center.lat,
alt: this.options.height
}
this.ControllerObject.editTranslational()
new closeLeftClick(this.sdk)
}
else {
if (this.leftClickState && !getLeftClickState()) {
new openLeftClick(this.sdk)
}
this.ControllerObject.destroy()
}
}
get positionEditing() {
if (this.ControllerObject.getActiveState() === 'translational') {
return true
}
return false
}
//平移时,坐标信息变化的回调
set positionEditingCallBack(callback) {
return
}
get positionEditingCallBack() {
}
//旋转时,坐标信息变化的回调
set rotationEditingCallBack(callback) {
this._rotationEditingCallBack = callback
}
get rotationEditingCallBack() {
return (params) => {
// let params = this.ControllerObject._params
// this.center = {
// lng: params.tx,
// lat: params.ty,
// alt: params.tz,
// }
this.lng = params.tx
this.lat = params.ty
this.alt = params.tz
this.rotateX = params.rx
this.rotateY = params.ry
this.rotateZ = params.rz
this._rotationEditingCallBack && this._rotationEditingCallBack(this.ControllerObject._params)
}
}
/**
* @description 编辑框
* @param state=false {boolean} 状态: true打开, false关闭
*/
async edit(state = false) {
let _this = this
this.originalOptions = this.deepCopyObj(this.options)
this._element_style = null
// let elms = this.sdk.viewer._container.getElementsByClassName('YJ-custom-base-dialog')
// for (let i = elms.length - 1; i >= 0; i--) {
// this.sdk.viewer._container.removeChild(elms[i])
// }
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
if (state) {
this._element_style = document.createElement('style');
this._element_style.type = 'text/css';
this._element_style.setAttribute('data-name', 'YJ_style_dialog');
this._element_style.innerHTML = css();
this._DialogObject = await new Dialog(this.sdk, this.originalOptions, {
title: '编辑属性', left: '180px', top: '100px',
confirmCallBack: (options) => {
this.name = this.options.name || '未命名对象'
this.originalOptions = this.deepCopyObj(this.options)
this._DialogObject.close()
this.Dialog.confirmCallBack && this.Dialog.confirmCallBack(this.originalOptions)
},
resetCallBack: () => {
this.reset()
this.Dialog.resetCallBack && this.Dialog.resetCallBack()
},
removeCallBack: () => {
this.Dialog.removeCallBack && this.Dialog.removeCallBack()
},
closeCallBack: () => {
this.reset()
// this.entity.style = new Cesium.Cesium3DTileStyle({
// color: "color('rgba(255,255,255," + this.newData.transparency + ")')",
// show: true,
// });
this.positionEditing = false
this.ControllerObject && this.ControllerObject.destroy()
this.Dialog.closeCallBack && this.Dialog.closeCallBack()
},
showCallBack: (show) => {
this.show = show
this.Dialog.showCallBack && this.Dialog.showCallBack()
},
translationalCallBack: () => {
if (this.positionEditing) {
this.positionEditing = false
}
else {
this.positionEditing = true
}
}
}, true)
document.getElementsByTagName('head')[0].appendChild(this._element_style);
let contentElm = document.createElement('div');
contentElm.innerHTML = html(this)
this._DialogObject.contentAppChild(contentElm)
this.attributeType = this.options.attributeType
this.attributeCamera = this.options.attribute.camera
// 创建标签页
let tabsElm = new cy_tabs('model-edit-tabs', undefined, this.sdk)
// 颜色组件
let colorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.color,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.color = color
},//点击确认按钮事件回调
clear: () => {
this.color = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let labelColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("label_color")[0],
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)'
},//点击清空按钮事件回调
})
let lineColorPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("line_color")[0],
size: 'mini',//颜色box类型
alpha: true,//是否开启透明度
defaultColor: this.lineColor,
disabled: false,//是否禁止打开颜色选择器
openPickerAni: 'opacity',//打开颜色选择器动画
sure: (color) => {
this.lineColor = color
},//点击确认按钮事件回调
clear: () => {
this.lineColor = 'rgba(255,255,255,1)'
},//点击清空按钮事件回调
})
let labelBackgroundColorStartPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("labelBackgroundColorStart")[0],
size: 'mini',
alpha: true,
defaultColor: this.labelBackgroundColorStart,
disabled: false,
openPickerAni: 'opacity',
sure: (color) => {
this.labelBackgroundColorStart = color
},
clear: () => {
this.labelBackgroundColorStart = 'rgba(255,255,255,1)'
},
})
let labelBackgroundColorEndPicker = new YJColorPicker({
el: contentElm.getElementsByClassName("labelBackgroundColorEnd")[0],
size: 'mini',
alpha: true,
defaultColor: this.labelBackgroundColorEnd,
disabled: false,
openPickerAni: 'opacity',
sure: (color) => {
this.labelBackgroundColorEnd = color
},
clear: () => {
this.labelBackgroundColorEnd = 'rgba(255,255,255,1)'
},
})
let all_elm = contentElm.getElementsByTagName("*")
this._EventBinding.on(this, all_elm)
this._elms = this._EventBinding.element
this._elms.color = [colorPicker]
this._elms.labelColor = [labelColorPicker]
this._elms.lineColor = [lineColorPicker]
this._elms.labelBackgroundColorStart = [labelBackgroundColorStartPicker]
this._elms.labelBackgroundColorEnd = [labelBackgroundColorEndPicker]
setTimeout(() => {
this.attributeLink = this.options.attribute.link.content
this.cameraSelect && this.cameraSelect()
let tagData = this.attributeSelect
let attributeElm = this._DialogObject._element.content.getElementsByClassName('attribute-select-box')[0]
if (attributeElm) {
let legpObject = legp(attributeElm, ".attribute-select")
legpObject.legp_search(tagData)
let attributeSelectElm = this._DialogObject._element.content.getElementsByClassName('attribute-select')[0].getElementsByTagName('input')[0]
for (let i = 0; i < tagData.length; i++) {
if (tagData[i].key === this.options.attributeType) {
attributeSelectElm.value = tagData[i].value
legpObject.legp_searchActive(tagData[i].value)
break
}
}
attributeSelectElm.addEventListener('input', () => {
for (let i = 0; i < tagData.length; i++) {
if (tagData[i].value === attributeSelectElm.value) {
this.attributeType = tagData[i].key
break
}
}
})
}
}, 0);
} else {
// if (this._element_style) {
// document.getElementsByTagName('head')[0].removeChild(this._element_style)
// this._element_style = null
// }
// if (this._DialogObject && this._DialogObject.close) {
// this._DialogObject.close()
// this._DialogObject = null
// }
}
}
//更新模型位置
updateModel(_tx, _ty, _tz, _rx = 0, _ry = 0, _rz = 0, _scale) {
_tx = parseFloat(_tx)
_ty = parseFloat(_ty)
_tz = parseFloat(_tz)
_rx = parseFloat(_rx)
_ry = parseFloat(_ry)
_rz = parseFloat(_rz)
_scale = parseFloat(_scale)
this.entity.rotate = { x: _rx, y: _ry, z: _rz };
let mx = Cesium.Matrix3.fromRotationX(
Cesium.Math.toRadians(_rx)
)
let my = Cesium.Matrix3.fromRotationY(
Cesium.Math.toRadians(_ry)
)
let mz = Cesium.Matrix3.fromRotationZ(
Cesium.Math.toRadians(_rz)
)
// 平移
let position = new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz)
let m = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3(position.x - this.entity._center.x, position.y - this.entity._center.y, position.z - this.entity._center.z))
// 旋转
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.fromTranslation(new Cesium.Cartesian3(position.x - this.entity._center.x, position.y - this.entity._center.y, position.z - this.entity._center.z), this.entity.modelMatrix)
// console.log(position.z, this.entity._center.z)
// Cesium.Matrix4.multiply(this.entity.modelMatrix, rotationX, originalMatrix)
// Cesium.Matrix4.multiply(originalMatrix, rotationY, originalMatrix)
// Cesium.Matrix4.multiply(originalMatrix, rotationZ, this.entity.modelMatrix)
// 缩放
// Cesium.Matrix4.multiplyByScale(this.entity.modelMatrix, new Cesium.Cartesian3(_scale, _scale, _scale), this.entity.modelMatrix)
this.ControllerObject.update()
this.entity.position = new Cesium.Cartesian3.fromDegrees(_tx, _ty, _tz)
}
updateModelRotate(_rx = 0, _ry = 0, _rz = 0, _scale) {
_rx = parseFloat(_rx)
_ry = parseFloat(_ry)
_rz = parseFloat(_rz)
_scale = parseFloat(_scale)
this.sdk.viewer.scene.primitives.remove(this.entity);
let url = this.options.url
if (!url.startsWith("http")) {
//说明是本地的json在磁盘中存在的
if (!url.includes(":")) {
if (this.options.host) {
let o = new URL(url, this.options.host)
url = o.href
}
}
}
let instances = []
for (let i = 0; i < this.ModelPositions.length; i++) {
let scale = _scale
// let cartographic = Cesium.Cartographic.fromDegrees(ModelPositions[i].lng, ModelPositions[i].lat, this.options.height);
let position = Cesium.Cartesian3.fromDegrees(
this.ModelPositions[i].lng, this.ModelPositions[i].lat, this.options.height
);
var modelMatrix = Cesium.Transforms.headingPitchRollToFixedFrame(
position,
new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(_rz), Cesium.Math.toRadians(_ry), Cesium.Math.toRadians(_rx))
);
Cesium.Matrix4.multiplyByUniformScale(
modelMatrix,
scale,
modelMatrix
);
instances.push({
modelMatrix: modelMatrix
})
}
this.entity = new Cesium.ModelInstanceCollection({
url: url,
instances: instances
})
this.entity.position = new Cesium.Cartesian3.fromDegrees(this.center.lng, this.center.lat, this.options.height)
this.entity.rotate = { x: this.options.rotate.x, y: this.options.rotate.y, z: this.options.rotate.z };
this.updateModel(this.center.lng, this.center.lat, this.options.height, this.options.rotate.x, this.options.rotate.y, this.options.rotate.z, this.options.scale)
this.sdk.viewer.scene.primitives.add(this.entity);
}
reset() {
if (!this.entity) {
return
}
this.options = this.deepCopyObj(this.originalOptions)
this.name = this.originalOptions.name
this.color = this.originalOptions.color
this.lng = this.originalOptions.position.lng
this.lat = this.originalOptions.position.lat
this.alt = this.originalOptions.position.alt
this.maximumScale = this.originalOptions.maximumScale
this.minimumPixelSize = this.originalOptions.minimumPixelSize
this.scaleByDistance = this.originalOptions.scaleByDistance
this.rotateX = this.originalOptions.rotate.x
this.rotateY = this.originalOptions.rotate.y
this.rotateZ = this.originalOptions.rotate.z
this.scale = this.originalOptions.scale
this.labelShow = this.originalOptions.label.show
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.attributeLink = this.options.attribute.link.content
this.attributeCamera = this.options.attribute.camera
this.cameraSelect && this.cameraSelect()
}
}
export default Model2