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

1709 lines
57 KiB
JavaScript
Raw Normal View History

2025-07-03 13:54:01 +08:00
import { getHost, getToken } from '../../../on'
import Base from '../index'
import { generatePagination } from '../../Element/Pagination'
import {
regLeftClickCallback,
regRightClickCallback
} from '../../../Global/ClickCallback'
import richText from '../../Element/richText'
import Dialog from '../../Element/Dialog'
import { openAllNodeList as OpenAllNodeList } from './openAllNodeList'
import { openNodeListById as OpenNodeListById } from './openNodeListById'
import { syncData } from '../../../Global/MultiViewportMode'
import { syncSplitData } from "../../../Global/SplitScreen";
import { attributeElm } from '../../Element/elm_html'
import { Proj } from '../../../Tools/proj'
import { legp } from '../../Element/datalist'
import { setActiveViewer, getGroundCover, closeRotateAround, closeViewFollow } from '../../../Global/global'
import {
addCluster,
remove_entity_from_cluster
} from '../../../Global/cluster/cluster'
let colors = require('./color.json')
class Vector extends Base {
#loadEvent = void 0
#loaded = false
#textEntity = []
constructor(sdk, options = {}, _Dialog = {}) {
super(sdk, options)
this.viewer = sdk.viewer
if (!this.options.path) {
this.error = '未提供路径!'
if (window.ELEMENT) {
window.ELEMENT.Message.closeAll()
window.ELEMENT.Message({
message: this.error,
type: 'warning',
duration: 1500
})
}
console.warn(this.error)
return
}
this.colors = colors
this.options.head_tables = options.head_tables || []
this.options.fileName = options.fileName || '未命名对象'
if (!this.options.path.endsWith('.kml')) {
; (this.options.color = options.color || 'rgba(0,255,184,0.5)'),
(this.options.opacity =
options.opacity || options.opacity === 0 ? options.opacity : 1)
}
this.options.show =
options.show || options.show === false ? options.show : true
this.total = 0
this.page = 1
this.pageSize = 20
this.currentData = []
this.data = []
this.list = []
this.imgEntity = []
this.Dialog = _Dialog
this._elms = {}
this.sdk.addIncetance(this.options.id, this)
this.disaster_type_colors = colors[this.options.disaster_type]
? { ...colors[this.options.disaster_type] }
: void 0
for (const key in this.disaster_type_colors) {
this.disaster_type_colors[key] = this.cmykToRgb(
this.disaster_type_colors[key]
)
}
}
get type() {
return 'vector'
}
get show() {
return this.options.show
}
set show(v) {
this.setShow(v)
}
get opacity() {
return this.options.opacity
}
set opacity(v) {
this.options.opacity = v
if (this.entity) {
this.entity.entities.values.forEach(enetity => {
if (enetity.point) {
enetity.point.color = enetity.point.color._value.withAlpha(v)
}
if (enetity.polygon) {
enetity.polygon.material = enetity.polygon.material.color._value.withAlpha(
v
)
}
if (enetity.polyline) {
enetity.polyline.material = enetity.polyline.material.color._value.withAlpha(
v
)
}
})
}
}
on() {
if (!this.sdk || !this.viewer || !this.options.path) {
return
}
return this.init()
}
async init() {
let url = ''
this.options.host = this.options.host || getHost()
if (this.options.host.endsWith('yjearth4.0')) {
url = this.options.host + '/api/v1/vector/load2'
} else {
url = this.options.host + '/yjearth4.0/api/v1/vector/load2'
}
url += '?path=' + this.options.path
// url = 'json/shp.json'
let response = await fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
token: getToken(),
Authorization: 'Bearer ' + getToken()
}
})
if (response.status === 200) {
let arrayBuffer = await response.arrayBuffer()
let uint8Array = new Uint8Array(arrayBuffer)
let string = this.decompressGzip(uint8Array)
if(this.data.length===0)
{
this.data = JSON.parse(string)
}
await this.formatData()
return Vector.create(this)
}
}
// 格式化数据
async formatData() {
let features = []
let _this = this
const posConvert = (data, src, dst) => {
if (data) {
if (Array.isArray(data)) {
let flag = false
for (let i = 0; i < data.length; i++) {
if (typeof data[i] === 'object') {
posConvert(data[i], src, dst)
} else {
flag = true
break
}
}
if (flag) {
let x = Number(data[0])
let y = Number(data[1])
let res = proj4(src, dst, [x, y])
data[0] = Number(res[0].toFixed(10))
data[1] = Number(res[1].toFixed(10))
}
} else {
if (data instanceof Object) {
posConvert(data.coordinates, src, dst)
posConvert(data.geometries, src, dst)
}
}
}
}
for (let i = 0; i < this.data.list.length; i++) {
let crs_src = ''
let crs_dst = ''
for (let [key, item] of this.name_map) {
if (item.def === this.data.list[i].crs_src) {
crs_src = item.epsg
}
if (item.def === this.data.list[i].crs_dst) {
crs_dst = item.epsg
}
}
for (let m = 0; m < this.data.list[i].features.length; m++) {
this.data.list[i].features[m].properties.id
if(!this.data.list[i].features[m].properties) {
this.data.list[i].features[m].properties = {}
}
if(!this.data.list[i].features[m].properties.id) {
this.data.list[i].features[m].properties.id = Cesium.createGuid()
}
this.data.list[i].features[m].id = this.data.list[i].features[m].properties.id
posConvert(
this.data.list[i].features[m].geometry,
this.data.list[i].crs_src,
this.data.list[i].crs_dst || '+proj=longlat +datum=WGS84 +no_defs'
)
this.data.list[i].features[m].geometry.geometries ||
(this.data.list[i].features[m].geometry.geometries = [])
let range = turf.bbox(this.data.list[i].features[m].geometry)
if (range && range[0] && range[0] != Infinity) {
this.data.list[i].features[m].geometry.range = turf.bbox(
this.data.list[i].features[m]
)
}
features.push(this.data.list[i].features[m])
}
}
this.geojson = {
type: 'FeatureCollection',
features: features
}
// console.log(this.geojson)
// for (let i = 0; i < this.geojson.features.length; i++) {
// this.geojson.features[i].id = this.geojson.features[i].properties.id
// this.geojson.features[i].geometry.range = turf.bbox(this.geojson.features[i]);
// }
}
get fileName() {
return this.options.fileName
}
set fileName(v) {
this.options.fileName = v
this._elms.fileName && (this._elms.fileName.value = v)
}
get field() {
return this.options.field
}
set field(v) {
this.options.field = v
// for (let i = 0; i < this.#textEntity.length; i++) {
// const img = new Image();
// img.src = Vector.getcanvas(this.#textEntity[i].properties[this.options.field] && this.#textEntity[i].properties[this.options.field]._value + '')
// img.onload = async () => {
// this.#textEntity[i].billboard.image = Vector.getcanvas(this.#textEntity[i].properties[this.options.field] && this.#textEntity[i].properties[this.options.field]._value + '')
// }
// }
let label = v
for (let index = 0; index < this.options.head_tables.length; index++) {
if (this.options.head_tables[index].key === v) {
label = this.options.head_tables[index].label
break
}
}
this._elms.field && (this._elms.field.value = label)
}
get img() {
return this.options.img
}
set img(v) {
if (!Array.isArray(v)) {
v = [v]
}
this.options.img = v
Vector.createImage(this)
}
get color() {
return this.options.color
}
set color(v) {
this.options.color = v
if (!this.entity) {
return
}
this.entity.entities.values.forEach(enetity => {
if (enetity.point) {
enetity.point.color = Cesium.Color.fromCssColorString(v).withAlpha(
this.opacity
)
}
if (enetity.polygon) {
enetity.polygon.material = Cesium.Color.fromCssColorString(v).withAlpha(
this.opacity
)
}
if (enetity.polyline) {
enetity.polyline.material = Cesium.Color.fromCssColorString(
v
).withAlpha(this.opacity)
}
})
}
set onRightClick(val) {
if (val && typeof val !== 'function') {
console.error('val:', val, '不是一个function')
} else {
if (this.rightClickCallBack == null && this.options && this.options.id) {
regRightClickCallback(this.options.id, this.rightClickCB, this)
}
this.rightClickCallBack = val
}
}
leftClickCB(mo, id, p, that) {
if (that.clickCallBack && typeof that.clickCallBack === 'function') {
that.clickCallBack(mo, id, p)
}
}
static create(that) {
// that.entity = new Cesium.PrimitiveCollection();
// that.viewer.scene.primitives.add(that.entity)
// Vector.calculationScope(that, that.data)
// Vector.createPoints(that, that.data.points)
// Vector.createPolylines(that, that.data.polylines)
// Vector.createPolygons(that, that.data.polygons)
let bbox = turf.bbox(that.geojson)
if (bbox && bbox[0] && bbox[0] != Infinity) {
that.range = bbox
}
that.options.img && Vector.createImage(that)
const getColor = level => {
// level = Number(level)
let color = that.options.color
if (
that.disaster_type_colors &&
that.disaster_type_colors.hasOwnProperty(level)
) {
color = that.disaster_type_colors[level]
}
return color
}
if (
that.options.path.endsWith('.kml') ||
that.options.path.endsWith('.kmz')
) {
let url = ''
that.options.host = that.options.host || getHost()
if (that.options.host.endsWith('yjearth4.0')) {
url = that.options.host + '/api/v1/vector/getKml'
} else {
url = that.options.host + '/yjearth4.0/api/v1/vector/getKml'
}
url += '?path=' + that.options.path
// url = 'json/shp.json'
fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
token: getToken(),
Authorization: 'Bearer ' + getToken()
}
}).then(response => {
if (response.status === 200) {
response.blob().then(data => {
data.text().then(kml => {
if (that.options.path.endsWith('.kmz')) {
kml = url
}
else {
let parser = new DOMParser() // new Parser
kml = parser.parseFromString(kml, 'text/xml') // Parse string
let placemark = kml.getElementsByTagName('Placemark')
for (let i = 0; i < placemark.length; i++) {
placemark[i].id = that.geojson.features[i].id
}
}
Cesium.KmlDataSource.load(kml, {
camera: that.viewer.scene.camera,
canvas: that.viewer.scene.canvas,
clampToGround: true
}).then(datasource => {
createEntity(datasource)
})
})
})
}
})
} else {
const geoJsonDataSource = new Cesium.GeoJsonDataSource()
let promise = geoJsonDataSource.load(that.geojson, {
clampToGround: true
})
let Instances = []
return promise.then(datasource => {
createEntity(datasource)
})
}
function createEntity(datasource) {
that.entity = datasource
// that.viewer.dataSources.add(datasource);
datasource.entities.values.forEach((entity, index) => {
// if(!that.geojson.features[index]) {
// return
// }
// that.data.list[i].features[index].id = that.data.list[i].features[index].properties.id = entity.id
// that.geojson.features[index].id = that.geojson.features[index].properties.id = entity.id
entity.show = that.options.show
entity.type = 'vector'
entity.parentId = that.options.id
if (!entity.properties) {
entity.properties = {}
}
// that.sdk.viewer.entities.add(entity)
addCluster(that.sdk, entity)
let color = getColor(
entity.properties &&
entity.properties[that.options.fxdj] &&
entity.properties[that.options.fxdj]._value
)
if (entity.billboard) {
// entity.billboard.show = false
entity.billboard.heightReference =
Cesium.HeightReference.CLAMP_TO_GROUND
entity.point = new Cesium.PointGraphics({
show: true,
// position: new Cesium.Cartesian3(entity.position._value.x, entity.position._value.y, entity.position._value.z), // 点的位置
color: Cesium.Color.fromCssColorString(
color || 'rgba(0,255,184,0.5)'
).withAlpha(that.opacity), // 点的颜色
pixelSize: 10, // 点的大小
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
}, false)
})
}
if (entity.polyline) {
let material = entity.polyline.material
if (color) {
material = Cesium.Color.fromCssColorString(color).withAlpha(
that.opacity
)
}
entity.polyline = new Cesium.PolylineGraphics({
positions: entity.polyline.positions._value,
width: entity.polyline.width && entity.polyline.width.getValue(),
clampToGround: true,
material: material,
zIndex: that.sdk._entityZIndex
})
// let polyline = new Cesium.GroundPolylineGeometry({
// positions: entity.polyline.positions._value,
// width: 2
// });
// Instances.push(new Cesium.GeometryInstance({
// geometry: polyline,
// attributes: {
// color: Cesium.ColorGeometryInstanceAttribute.fromColor(
// Cesium.Color.fromCssColorString('rgba(0,255,184,0.5)')
// )
// }
// }))
// console.log(entity.polyline)
}
if (entity.polygon && entity.polygon.material) {
entity.polygon.perPositionHeight = false
entity.polygon.extrudedHeight = undefined
let material = entity.polygon.material.color._value
if (color) {
material = Cesium.Color.fromCssColorString(color)
}
if (that.opacity || that.opacity === 0) {
material = material.withAlpha(that.opacity)
}
let data = entity.kml || entity.kmz
if (data) {
let img =
data.extendedData &&
data.extendedData.BaseTexturePath &&
data.extendedData.BaseTexturePath.value
? data.extendedData.BaseTexturePath.value
: undefined
if (img) {
entity.polygon.material.image = img
entity.polygon.material.repeat = new Cesium.Cartesian2(1, 1)
}
entity.polygon.material = new Cesium.ImageMaterialProperty({
image: img, // 贴图的URL
repeat: new Cesium.Cartesian2(1, 1),
color: material
})
}
entity.polygon.zIndex = that.sdk._entityZIndex
if (
that.options.path.endsWith('.kml') ||
that.options.path.endsWith('.kmz')
) {
let material = color
? Cesium.Color.fromCssColorString('#000000')
: entity.polygon.outlineColor.getValue()
if (that.opacity || that.opacity === 0) {
material = material.withAlpha(that.opacity)
}
if (entity.polygon.outlineWidth) {
entity.polyline = new Cesium.PolylineGraphics({
positions: entity.polygon.hierarchy._value.positions,
width: entity.polygon.outlineWidth.getValue(),
clampToGround: true,
material: material,
zIndex: that.sdk._entityZIndex
})
}
} else {
entity.polyline = new Cesium.PolylineGraphics({
positions: entity.polygon.hierarchy._value.positions,
width: 1,
clampToGround: true,
material: Cesium.Color.fromCssColorString('#000000').withAlpha(
that.opacity
),
zIndex: that.sdk._entityZIndex
})
// 通过生成canvas创建billboard增加贴地高度的加载速度
// if (entity.billboard && entity.position && entity.position.getValue()) {
// const img = new Image();
// img.src = Vector.getcanvas(entity.properties[that.options.field] && entity.properties[that.options.field]._value + '')
// img.onload = async function () {
// let position = entity.position.getValue()
// let entity2 = new Cesium.Entity({
// show: that.options.show,
// id: entity.id + '_text',
// parentId: that.options.id,
// position: new Cesium.Cartesian3(position.x, position.y, position.z), // 点的位置
// billboard: {
// image: img,
// pixelOffset: new Cesium.Cartesian2(0, -15),
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// disableDepthTestDistance: new Cesium.CallbackProperty(function () {
// return getGroundCover() ? undefined : 100000000
// }, false)
// }
// })
// entity2.properties = entity.properties
// that.#textEntity.push(entity2)
// that.sdk.viewer.entities.add(entity2)
// }
// }
if (entity.point) {
entity.label = new Cesium.LabelGraphics({
text: new Cesium.CallbackProperty(function () {
return (
entity.properties[that.options.field] &&
entity.properties[that.options.field]._value + ''
)
}, false),
outlineColor: Cesium.Color.BLACK,
outlineWidth: 10,
font: '16px Microsoft YaHei',
fillColor: Cesium.Color.fromCssColorString('#ffeb3b'),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15),
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
}, false)
})
}
}
that.sdk._entityZIndex++
}
if (
that.options.path.endsWith('.kml') ||
that.options.path.endsWith('.kmz')
) {
if (entity.label) {
entity.label.font = '16px Microsoft YaHei'
let feature = that.geojson.features[index]
entity.billboard.heightReference = Cesium.HeightReference.CLAMP_TO_GROUND
entity.properties = feature ? feature.properties : {}
if (!entity.properties.id && !entity.properties.Id && !entity.properties.ID) {
entity.properties.addProperty('id', entity.id)
}
entity.label.text = new Cesium.CallbackProperty(function () {
return entity.properties[that.options.field] && entity.properties[that.options.field]._value + ''
}, false)
}
}
else {
if (entity.point) {
entity.label = new Cesium.LabelGraphics({
text: new Cesium.CallbackProperty(function () {
return (
entity.properties[that.options.field] &&
entity.properties[that.options.field]._value + ''
)
}, false),
outlineColor: Cesium.Color.BLACK,
outlineWidth: 10,
font: '16px Microsoft YaHei',
fillColor: Cesium.Color.fromCssColorString('#ffeb3b'),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -15),
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
}, false)
})
}
}
})
if (!that.options.field) {
const properties = ['id', 'Id', 'ID', 'name', 'Name', 'NAME', 'address', 'Address', 'ADDRESS', 'text', 'Text', 'TEXT', 'label', 'Label', 'LABEL'];
const field = properties.find(prop => that.geojson.features[0].properties[prop] !== undefined);
if (field) {
that.options.field = field;
}
else {
for (let key in that.geojson.features[0].properties) {
that.options.field = key;
break;
}
}
}
// for (let i = 0; i < that.#textEntity.length; i++) {
// that.entity.entities.add(that.#textEntity[i])
// }
that.#loaded = true
if (that.#loadEvent) {
that.#loadEvent()
}
// let primitive = new Cesium.GroundPolylinePrimitive({
// geometryInstances: Instances,
// appearance: new Cesium.PolylineColorAppearance()
// });
// that.viewer.scene.primitives.add(primitive);
// that.viewer.zoomTo(datasource)
}
}
static createImage(that) {
//(primitive无法贴地?)
that.removeImage()
if (!that.range) {
return
}
for (let i = 0; i < that.options.img.length; i++) {
let entity = that.sdk.viewer.entities.add({
show: that.options.show,
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(...that.range),
material: new Cesium.ImageMaterialProperty({
image: that.options.img[i],
transparent: true
})
}
})
that.imgEntity.push(entity)
}
}
static getcanvas(text) {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.font = '16px YaHei'
let texts = text.split('\n')
let canvasWidth = 0
let canvasHeight = 0
for (let i = 0; i < texts.length; i++) {
const t = texts[i]
const width = ctx.measureText(t).width
if (width > canvasWidth) {
canvasWidth = width
}
canvasHeight += 16
}
canvasHeight = canvasHeight + 10 + (texts.length - 1) * 5
canvasWidth = canvasWidth + 30
canvas.width = canvasWidth
canvas.height = canvasHeight
const linearGradient = ctx.createLinearGradient(
0,
0,
canvasWidth,
canvasHeight
)
ctx.fillStyle = linearGradient
ctx.fillRect(0, 0, canvasWidth, canvasHeight)
ctx.fillStyle = '#ffffff'
ctx.font = '16px YaHei'
ctx.strokeStyle = '#000000'
ctx.strokeText(
texts,
15,
16 * texts.length + (10 * 10) / 16 + texts.length * 5
)
ctx.fillText(
texts,
15,
16 * texts.length + (10 * 10) / 16 + texts.length - 1 * 5
)
ctx.moveTo(canvasWidth / 2, canvasHeight)
ctx.stroke()
ctx.closePath()
return canvas.toDataURL()
}
async edit(status = false, DialogEvent = {}) {
this.originalOptions = this.deepCopyObj(this.options)
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
if (status) {
this._DialogObject = await new Dialog(this.sdk, this.options, {
title: '编辑属性',
left: '180px',
top: '100px',
confirmCallBack: options => {
this.fileName = this.fileName.trim()
if (!this.fileName) {
this.fileName = '未命名对象'
}
this.originalOptions.fileName = this.fileName
this.originalOptions.field = this.field
this._DialogObject.close()
DialogEvent.confirmCallBack &&
DialogEvent.confirmCallBack({
id: this.options.id,
fileName: this.originalOptions.fileName,
field: this.originalOptions.field
})
},
closeCallBack: () => {
this.reset()
DialogEvent.closeCallBack && DialogEvent.closeCallBack()
}
})
let html = `
<div class="row">
<div class="col">
<span class="label">文件名称</span>
<input class="input flie-name" type="text">
</div>
</div>
<div class="row">
<div class="col key-box">
<span class="label">名称字段选择</span>
<div class="key"></div>
</div>
</div>
`
let contentElm = document.createElement('div')
contentElm.innerHTML = html
this._DialogObject.contentAppChild(contentElm)
let nameElm = contentElm.getElementsByClassName('flie-name')[0]
nameElm.value = this.options.fileName
nameElm.addEventListener('input', () => {
this.options.fileName = nameElm.value
})
let keyData = []
for (let key in this.geojson.features[0].properties) {
let label = key
for (let index = 0; index < this.options.head_tables.length; index++) {
if (this.options.head_tables[index].key === key) {
label = this.options.head_tables[index].label
break
}
}
keyData.push({
name: label,
value: label,
key: key
})
}
let keyObject = legp(
contentElm.getElementsByClassName('key-box')[0],
'.key'
)
if (keyObject) {
keyObject.legp_search(keyData)
let keyDataLegpElm = contentElm
.getElementsByClassName('key')[0]
.getElementsByTagName('input')[0]
keyDataLegpElm.value = this.field
for (let i = 0; i < keyData.length; i++) {
if (keyData[i].key == this.field) {
keyDataLegpElm.value = keyData[i].value
keyObject.legp_searchActive(keyData[i].value)
break
}
}
keyDataLegpElm.addEventListener('input', () => {
for (let i = 0; i < keyData.length; i++) {
if (keyData[i].value === keyDataLegpElm.value) {
this.options.field = keyData[i].key
break
}
}
})
this._elms.field = keyDataLegpElm
}
this._elms.fileName = nameElm
return
let selectElm = contentElm.getElementsByClassName('input-select')[0]
let option = ''
// for (let key in this.geojson.features[0].properties) {
// let o = `<option value="${key}">${key}</option>`
// option = option + o
// }
for (let key in this.geojson.features[0].properties) {
let label = key
for (let index = 0; index < this.options.head_tables.length; index++) {
if (this.options.head_tables[index].key === key) {
label = this.options.head_tables[index].label
break
}
}
let o = `<option value="${key}">${label}</option>`
option = option + o
}
selectElm.innerHTML = option
selectElm.value = this.options.field
selectElm.addEventListener('input', () => {
this.options.field = selectElm.value
})
this._elms.fileName = nameElm
this._elms.field = selectElm
} else {
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
}
}
async editById(status = false, nodeId, DialogEvent = {}) {
// nodeId = this.dataArray[0].attr.id
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
let cameraName = ''
let index
if (status) {
let options = {}
for (let i = 0; i < this.geojson.features.length; i++) {
if (this.geojson.features[i].id === nodeId) {
if (this.geojson.features[i].content) {
options = this.deepCopyObj(this.geojson.features[i].content)
}
index = i
break
}
}
options.id = options.id || nodeId
options.link || (options.link = {})
options.link.content || (options.link.content = [])
options.camera || (options.camera = [])
options.richTextContent || (options.richTextContent = '')
options.attributeType = options.attributeType || 'richText'
this._DialogObject = await new Dialog(this.sdk, options, {
title: '编辑属性',
left: '180px',
top: '100px',
confirmCallBack: () => {
this._DialogObject.close()
this.geojson.features[index].content = this.deepCopyObj(
this._DialogObject.attribute
)
DialogEvent.confirmCallBack &&
DialogEvent.confirmCallBack(this._DialogObject.attribute)
},
closeCallBack: () => {
// this.reset()
DialogEvent.closeCallBack && DialogEvent.closeCallBack()
}
})
this._DialogObject.event = DialogEvent
this._DialogObject.attribute = this.deepCopyObj(options)
let html = `
<div class="row">
<div class="col">
<span class="label">内容类型</span>
<select class="input input-select attribute-select" style="width: 120px;">
<option value="richText">富文本</option>
<!--<option value="link">链接</option>
<option value="camera">摄像头</option>
<option value="sensor">传感器</option>
<option value="vr">全景图</option>-->
</select>
</div>
<div class="col attribute-content attribute-content-link">
<div class="input-group">
<input class="input link_add" type="text">
<button class="link_add_btn">+</button>
</div>
</div>
</div>
<div class="attribute-content attribute-content-richText">
<span>编辑内容<button class="open-richText-btn">打开文本编辑器</button></span>
</div>
<div class="attribute-content attribute-content-link">
<div class="table">
<div class="table-head">
<div class="tr">
<div class="th">名称</div>
<div class="th">链接</div>
<div class="th">操作</div>
</div>
</div>
<div class="table-body">
</div>
<div class="table-empty">
<div class="empty-img"></div>
<p>暂无数据</p>
</div>
</div>
</div>
<div class="attribute-content attribute-content-camera">
<div class="row">
<div class="col">
<span class="label">编辑内容</span>
<input class="input camera-name" type="text" style="width: 100px;">
<button class="select btn camera-select">搜索</button>
</div>
</div>
<div>
<div class="table camera-table">
<div class="table-head">
<div class="tr">
<div class="th">操作</div>
<div class="th">设备名称</div>
<div class="th" style="width: 80px; flex: 0 80px;min-width: 80px;">设备类型</div>
<div class="th" style="width: 126px; flex: 0 126px;min-width: 126px;">设备IP</div>
<div class="th" style="width: 80px; flex: 0 80px;min-width: 80px;">设备端口</div>
<div class="th" style="width: 80px; flex: 0 80px;min-width: 80px;">用户名</div>
<div class="th">密码</div>
</div>
</div>
<div class="table-body" style="display:none;">
<div class="tr">
<div class="td">
<input type="checkbox" value="2">
<span>绑定</span>
</div>
<div class="td">设备名称</div>
<div class="td">设备类型</div>
<div class="td">设备IP</div>
<div class="td">设备端口</div>
<div class="td">用户名</div>
<div class="td">密码</div>
</div>
</div>
<div class="table-empty">
<div class="empty-img"></div>
<p>暂无数据</p>
</div>
</div>
</div>
<div class=""row>
<ul class="pagination"></ul>
</div>
</div>
`
let contentElm = document.createElement('div')
contentElm.innerHTML = html
this._DialogObject.contentAppChild(contentElm)
let all_elm = contentElm.getElementsByTagName('*')
this._DialogObject._element.body.style.width = '600px'
let attributeSelectElm = contentElm.getElementsByClassName(
'attribute-select'
)[0]
let linkAddBtnElm = contentElm.getElementsByClassName('link_add_btn')[0]
let openRichTextBtnElm = contentElm.getElementsByClassName(
'open-richText-btn'
)[0]
let attributeContent = this._DialogObject._element.content.getElementsByClassName(
'attribute-content'
)
for (let i = 0; i < attributeContent.length; i++) {
if (
attributeContent[i].className.indexOf(
'attribute-content-' + this._DialogObject.attribute.attributeType
) > -1
) {
attributeContent[i].style.display = 'block'
} else {
attributeContent[i].style.display = 'none'
}
}
attributeSelectElm.addEventListener('change', () => {
this._DialogObject.attribute.attributeType = attributeSelectElm.value
for (let i = 0; i < attributeContent.length; i++) {
if (
attributeContent[i].className.indexOf(
'attribute-content-' + this._DialogObject.attribute.attributeType
) > -1
) {
attributeContent[i].style.display = 'block'
} else {
attributeContent[i].style.display = 'none'
}
}
})
linkAddBtnElm.addEventListener('click', async () => {
if (
this._DialogObject._element.content.getElementsByClassName(
'link_add'
)[0].value
) {
this._DialogObject.attribute.link.content.push({
2025-07-03 15:54:39 +08:00
name: '链接',
2025-07-03 13:54:01 +08:00
url: this._DialogObject._element.content.getElementsByClassName(
'link_add'
)[0].value
})
this._DialogObject._element.content.getElementsByClassName(
'link_add'
)[0].value = ''
this.setAttributeLinkById(
nodeId,
this._DialogObject.attribute.link.content
)
} else {
DialogEvent.clickAddLink && DialogEvent.clickAddLink(nodeId)
}
})
openRichTextBtnElm.addEventListener('click', () => {
richText.open(
nodeId,
nodeId,
this._DialogObject.attribute.richTextContent
)
richText.primaryCallBack = content => {
this._DialogObject.attribute.richTextContent = content
}
})
let cameraNameElm = contentElm.getElementsByClassName('camera-name')[0]
let cameraSelectElm = contentElm.getElementsByClassName(
'camera-select'
)[0]
cameraNameElm.addEventListener('input', () => {
cameraName = cameraNameElm.value
})
this.cameraSelect && this.cameraSelect(cameraName)
cameraSelectElm.addEventListener('click', () => {
this.cameraSelect && this.cameraSelect(cameraName)
})
// let nameElm = contentElm.getElementsByClassName('flie-name')[0]
// nameElm.value = this.options.fileName
// nameElm.addEventListener('input', ()=>{
// this.options.fileName = nameElm.value
// })
// let selectElm = contentElm.getElementsByClassName('input-select')[0]
// let option = ''
// for(let key in this.dataArray[0].attr) {
// let o = `<option value="${key}">${key}</option>`
// option = option + o
// }
// selectElm.innerHTML = option
// selectElm.value = this.options.field
// selectElm.addEventListener('input', ()=>{
// this.options.field = selectElm.value
// })
// this._elms.fileName = nameElm
// this._elms.field = selectElm
} else {
if (this._DialogObject && this._DialogObject.close) {
this._DialogObject.close()
this._DialogObject = null
}
}
}
editContentById(nodeId, content) {
for (let i = 0; i < this.geojson.features.length; i++) {
if (this.geojson.features[i].id === nodeId) {
this.geojson.features[i].content = content
break
}
}
}
reset() {
this.fileName = this.originalOptions.fileName
this.field = this.originalOptions.field
}
addAttributeLinkById(nodeId, link, i) {
if (
this._DialogObject &&
this._DialogObject.attribute &&
this._DialogObject.attribute.id == nodeId
) {
if (i || i === 0) {
this._DialogObject._element.body
.getElementsByClassName('attribute-content-link')[1]
.getElementsByClassName('tr')
[i + 1].getElementsByClassName('file-select')[0].value = link
} else {
this._DialogObject.attribute.link.content.push({
2025-07-03 15:54:39 +08:00
name: '链接',
2025-07-03 13:54:01 +08:00
url: link
})
this.setAttributeLinkById(
nodeId,
this._DialogObject.attribute.link.content
)
}
}
}
setAttributeLinkById(nodeId, data) {
if (
this._DialogObject &&
this._DialogObject.attribute &&
this._DialogObject.attribute.id == nodeId
) {
this._DialogObject.attribute.link.content = data
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._DialogObject.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._DialogObject.attribute.link.content.length;
i++
) {
let tr =
`
<div class="tr">
<div class="td">` +
this._DialogObject.attribute.link.content[i].name +
`</div>
<div class="td">` +
this._DialogObject.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 => {
await this.setAttributeLinkById(
nodeId,
this._DialogObject.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 html = `
<div class="td">
<input class="input" type="text">
</div>
<div class="td">
<div class="input-group">
<input class="input file-select" type="text" style="width: 200px;">
<button @click="fileSelect">...</button>
</div>
</div>
<div class="td">
<button @click="confirmEdit">确认</button>
<button @click="cancelEdit">取消</button>
</div>`
item[i].innerHTML = html
let td = item[i].getElementsByClassName('td')
td[0].getElementsByClassName(
'input'
)[0].value = this._DialogObject.attribute.link.content[index].name
td[1].getElementsByClassName(
'input'
)[0].value = this._DialogObject.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._DialogObject.attribute.link.content.splice(i, 1)
this.setAttributeLinkById(
nodeId,
this._DialogObject.attribute.link.content
)
},
confirmEdit: (value, i) => {
this._DialogObject.attribute.link.content[i] = value
this.setAttributeLinkById(
nodeId,
this._DialogObject.attribute.link.content
)
},
cancelEdit: () => {
this.setAttributeLinkById(
nodeId,
this._DialogObject.attribute.link.content
)
},
fileSelect: (value, i) => {
this._DialogObject.event &&
this._DialogObject.event.clickAddLink &&
this._DialogObject.event.clickAddLink(nodeId, i)
}
}
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
}
}
}
}
}
for (let i = 0; i < this.dataArray.length; i++) {
if (this.dataArray[i].attr.id === nodeId) {
if (this.dataArray[i].content) {
this.opt_DialogObject.attribute.link.content = v
}
break
}
}
}
getAllNode() {
return this.data
}
openAllNodeList() {
OpenAllNodeList(this)
}
openNodeListById(id) {
OpenNodeListById(this, id)
}
static createTableContent(that) {
let trsElm = ''
for (let i = 0; i < that.currentData.length; i++) {
let trElm = '<tr class="el-table__row">'
let tdElm = ''
for (let key in that.currentData[i].attr) {
tdElm =
tdElm +
`<td rowspan="1" colspan="1" class="el-table_1_column_${i} el-table__cell"><div class="cell">${that.currentData[i].attr[key]}</div></td>`
}
trElm = trElm + tdElm + '</tr>'
trsElm = trsElm + trElm
}
return trsElm
}
flyTo(id, options = {}) {
setActiveViewer(0)
closeRotateAround(this.sdk)
closeViewFollow(this.sdk)
if (id) {
for (let i = 0; i < this.geojson.features.length; i++) {
if (this.geojson.features[i].id === id) {
if (this.geojson.features[i].geometry.type === 'Point') {
this.getClampToHeight({
lng: this.geojson.features[i].geometry.coordinates[0],
lat: this.geojson.features[i].geometry.coordinates[1]
}).then(height => {
this.sdk.viewer.camera.flyTo({
orientation: options.orientation,
destination: Cesium.Cartesian3.fromDegrees(
this.geojson.features[i].geometry.coordinates[0],
this.geojson.features[i].geometry.coordinates[1],
height + (options.height || 500)
)
})
})
} else {
let range = this.geojson.features[i].geometry.range
if (range) {
let array = []
this.getClampToHeight({ lng: range[0], lat: range[1] }).then(
h => {
let a = Cesium.Cartesian3.fromDegrees(range[0], range[1], h)
array.push(a.x, a.y, a.z)
this.getClampToHeight({ lng: range[2], lat: range[3] }).then(
h2 => {
let a = Cesium.Cartesian3.fromDegrees(
range[2],
range[3],
h2
)
array.push(a.x, a.y, a.z)
let BoundingSphere = Cesium.BoundingSphere.fromVertices(
array
)
this.sdk.viewer.camera.flyToBoundingSphere(
BoundingSphere,
{
offset: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
}
)
}
)
}
)
}
}
}
}
} else {
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)
this.sdk.viewer.camera.flyTo({
destination: destination,
orientation: orientation
})
} else {
if (this.range) {
let array = []
this.getClampToHeight({
lng: this.range[0],
lat: this.range[1]
}).then(h => {
let a = Cesium.Cartesian3.fromDegrees(
this.range[0],
this.range[1],
h
)
array.push(a.x, a.y, a.z)
this.getClampToHeight({
lng: this.range[2],
lat: this.range[3]
}).then(h2 => {
let a = Cesium.Cartesian3.fromDegrees(
this.range[2],
this.range[3],
h2
)
array.push(a.x, a.y, a.z)
let BoundingSphere = Cesium.BoundingSphere.fromVertices(array)
this.sdk.viewer.camera.flyToBoundingSphere(BoundingSphere, {
offset: options.orientation || {
heading: Cesium.Math.toRadians(0.0),
pitch: Cesium.Math.toRadians(-90.0),
roll: Cesium.Math.toRadians(0.0)
}
})
})
})
}
}
}
}
setShow(status, id) {
// let enetity = this.entity.entities.getById(id)
// if(enetity) {
// enetity.show = status
// }
// else {
// }
if (id) {
if (!this.entity) {
return
}
for (let i = 0; i < this.entity.entities.values.length; i++) {
if (
this.entity.entities.values[i].id &&
this.entity.entities.values[i].id.startsWith(id)
) {
this.entity.entities.values[i].show = status
this.entity.entities.values[i]._customShow = status
syncSplitData(this.sdk, this.options.id, this.entity.entities.values[i].id)
// this.entity.entities.remove(this.entity.entities.values[i])
break
}
}
syncData(this.sdk, this.options.id)
} else {
this.options.show = status
if (!this.entity) {
return
}
// this.entity.show = status
for (let i = 0; i < this.entity.entities.values.length; i++) {
this.entity.entities.values[i].show = status
this.entity.entities.values[i]._customShow = status
syncSplitData(this.sdk, this.options.id, this.entity.entities.values[i].id)
}
syncData(this.sdk, this.options.id)
}
}
setShowImg(status, index) {
if (index || index === 0) {
for (let i = 0; i < this.imgEntity.length; i++) {
if (i == index) {
this.imgEntity[i].show = status
break
}
}
} else {
for (let i = 0; i < this.imgEntity.length; i++) {
this.imgEntity[i].show = status
}
}
}
async remove() {
if (this.entity) {
this.entity.entities.values.forEach(enetity => {
remove_entity_from_cluster(this.sdk.viewer, enetity)
})
}
this.#textEntity = []
// this.#textEntity = []
// this.viewer.dataSources.remove(this.entity, true)
this.removeImage()
this.entity = null
this.geojson = {}
this.data = {}
await this.sdk.removeIncetance(this.options.id)
await syncSplitData(this.sdk, this.options.id)
await syncData(this.sdk, this.options.id)
}
removeImage() {
for (let i = 0; i < this.imgEntity.length; i++) {
this.sdk.viewer.entities.remove(this.imgEntity[i])
}
this.imgEntity = []
}
cameraSelect(cameraName, page) {
const type = {
'1': '海康',
'2': '大华'
}
let host = this.options.host
if (
this._DialogObject &&
this._DialogObject._element &&
this._DialogObject._element.content
) {
let paginationElm = that._DialogObject._element.content.getElementsByClassName(
'pagination'
)[0]
let attributeCameraElm = that._DialogObject._element.content.getElementsByClassName(
'attribute-content-camera'
)[0]
if (!paginationElm) {
return
}
if (!attributeCameraElm) {
return
}
generatePagination(paginationElm, 1, 10, 1)
} else {
return
}
let url = ''
const params = {
cameraName: cameraName,
page: !page || typeof page === 'object' ? 1 : page,
pageSize: 5
}
const queryString = new URLSearchParams(params).toString()
if (host.endsWith('yjearth4.0'))
url = `${host}/api/v1/cameraData/list?${queryString}`
else url = `${host}/yjearth4.0/api/v1/cameraData/list?${queryString}`
// url = this.options.path
fetch(url, {
method: 'get',
headers: {
'Content-Type': 'application/json',
token: getToken(),
Authorization: 'Bearer ' + getToken()
}
}).then(response => {
if (response.status === 200) {
response.json().then(data => {
if (data.code === 200 || data.code === 0) {
if (
!this._DialogObject ||
!this._DialogObject._element ||
!this._DialogObject._element.content
) {
return
}
let paginationElm = this._DialogObject._element.content.getElementsByClassName(
'pagination'
)[0]
let table = this._DialogObject._element.content.getElementsByClassName(
'camera-table'
)[0]
let tableContent = table.getElementsByClassName('table-body')[0]
tableContent.innerHTML = ''
if (data.data) {
if (data.data.list && data.data.list.length > 0) {
generatePagination(
paginationElm,
data.data.total,
10,
1,
pageIndex => {
this.cameraSelect &&
this.cameraSelect(cameraName, pageIndex)
}
)
table.getElementsByClassName('table-empty')[0].style.display =
'none'
tableContent.style.display = 'inline-flex'
for (let i = 0; i < data.data.list.length; i++) {
let tr = `
<div class="tr">
<div class="td">
<input type="checkbox" value="${data.data.list[i].ID}">
<span>绑定</span>
</div>
<div class="td">${data.data.list[i].cameraName}</div>
<div class="td" style="width: 80px; flex: 0 80px; min-width: 80px;">${type[data.data.list[i].type]
}</div>
<div class="td" style="width: 126px; flex: 0 126px;min-width: 126px;">${data.data.list[i].ip
}</div>
<div class="td" style="width: 80px; flex: 0 80px;min-width: 80px;">${data.data.list[i].port
}</div>
<div class="td" style="width: 80px; flex: 0 80px;min-width: 80px;">${data.data.list[i].userName
}</div>
<div class="td">${data.data.list[i].passWord}</div>
</div>`
let trElm = document
.createRange()
.createContextualFragment(tr)
let checkbox = trElm.querySelector('input[type="checkbox"]')
checkbox.addEventListener('change', () => {
if (checkbox.checked) {
this._DialogObject.attribute.camera.push(
data.data.list[i]
)
} else {
let newArray = this._DialogObject.attribute.camera.filter(
item => {
return item.ID !== data.data.list[i].ID
}
)
this._DialogObject.attribute.camera = newArray
}
})
tableContent.appendChild(trElm)
for (
let m = 0;
m < this._DialogObject.attribute.camera.length;
m++
) {
if (
this._DialogObject.attribute.camera[m].ID ===
data.data.list[i].ID
) {
checkbox.checked = true
break
}
}
}
}
if (data.data && data.data.total) {
generatePagination(
paginationElm,
data.data.total,
10,
1,
pageIndex => {
this.cameraSelect &&
this.cameraSelect(cameraName, pageIndex)
}
)
}
} else {
generatePagination(paginationElm, 1, 10, 1)
table.getElementsByClassName('table-empty')[0].style.display =
'flex'
tableContent.style.display = 'none'
}
} else {
console.error(data.message)
}
})
}
})
}
load(callback) {
if (this.#loaded) {
callback()
} else {
this.#loadEvent = callback
}
}
flicker() { }
}
export default Vector