可拖拽标牌 2.0
Cesium > label
的效果不太好看,改为用 dom 做标牌
0、效果

1、使用方式
import DragDiv from './DragDiv.js'
const dataSource = new Cesium.CustomDataSource('label-datasource')
function addDragLabelEntity() {
const entity = new Cesium.Entity({
id: `entity-id`,
position: Cesium.Cartesian3.fromDegrees(123.0, 30.0, 1000),
model: {
show: true,
uri: './assets/model/warrior.glb',
scale: 1,
minimumPixelSize: 128,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 4e8)
}
})
dataSource.entities.add(entity)
let table = new DragDiv(viewer, dataSource)
table.addEntity(entity, {
details: [
{ label: '名称:', value: '测试设备' },
{ label: '状态:', value: '完好' },
{ label: '经度:', value: '109.25560682' },
{ label: '纬度:', value: '34.63496935' },
{ label: '成功率:', value: '99%' }
]
})
}
2、可拖拽标牌类DragDiv.js
export default class DragDiv {
constructor(viewer, dataSource, options) {
this._viewer = viewer
this._options = {
labelPixelOffset: new Cesium.Cartesian2(100, -100),
dragLineColor: Cesium.Color.GOLD,
dragLineLength: 100 * 1.414,
dragLinePixelOffset: new Cesium.Cartesian2(50 - (100 * 1.414) / 2, -50),
...options
}
this._dataSource = dataSource
this._isDragging = false
this._cacheList = new Cesium.AssociativeArray()
this._viewer.clock.onTick.addEventListener(this.calcLablePositions, this)
const style = document.createElement('style')
style.textContent = `
.LabelPlotBeautiful-container {
position: absolute;
color: white;
border-radius: 8px 8px 8px 0;
padding: 10px;
width: 200px;
background: rgba(3, 170, 170, 0.6);
user-select: none;
}
.LabelPlotBeautiful-content {
left: 0;
bottom: 0;
cursor: default;
}
.LabelPlotBeautiful-info-item {
letter-spacing: 2px;
font-family: serif;
}
`
document.head.appendChild(style)
}
addEntity(targetEntity, info) {
const canvas = document.createElement('canvas')
canvas.width = 200
canvas.height = 5
const cxt = canvas.getContext('2d')
cxt.lineWidth = 5
cxt.strokeStyle = 'red'
cxt.moveTo(0, 0)
cxt.lineTo(200, 0)
cxt.stroke()
targetEntity.billboard = {
image: canvas,
width: this._options.dragLineLength,
color: this._options.dragLineColor,
pixelOffset: this._options.dragLinePixelOffset,
rotation: Cesium.Math.toRadians(45),
height: 2,
scale: 1,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.BASELINE
}
const { details } = info
const newDiv = document.createElement('div')
newDiv.classList.add('LabelPlotBeautiful-container')
newDiv.id = `${targetEntity.id}`
newDiv.innerHTML = createHtml()
this._viewer.container.append(newDiv)
function createHtml() {
let html = `<div class="LabelPlotBeautiful-content">`
details.forEach((item) => {
html += `<div class="LabelPlotBeautiful-info-item">${item.label}${item.value}</div>`
})
html += `</div>`
return html
}
this._cacheList.set(targetEntity.id, this._options.labelPixelOffset)
this.calcLablePositions()
const that = this
newDiv.onmousedown = function (ev) {
that._isDragging = true
const { clientX: x1, clientY: y1 } = ev
const { offsetLeft: l, offsetTop: t } = newDiv
let distanceX = 0
let distanceY = 0
const { x: oldX, y: oldY } = that._cacheList.get(targetEntity.id)
document.onmousemove = function (e) {
const { clientX: x2, clientY: y2 } = e
distanceX = x2 - x1
distanceY = y2 - y1
newDiv.style.left = `${distanceX + l}px`
newDiv.style.top = `${distanceY + t}px`
that.updateBillboard(targetEntity, { x: distanceX + oldX, y: distanceY + oldY })
that._cacheList.set(targetEntity.id, { x: distanceX + oldX, y: distanceY + oldY })
}
document.onmouseup = function (ev) {
that._isDragging = false
document.onmousemove = null
document.onmouseup = null
}
}
}
updateBillboard(clickEntity, delta) {
let billboard = clickEntity.billboard
billboard.width = Math.sqrt(Math.pow(delta.x, 2) + Math.pow(delta.y, 2))
billboard.rotation = Cesium.Math.toRadians(-Math.atan(delta.y / delta.x) * (180 / Math.PI))
if (delta.x >= 0 && delta.y >= 0) {
billboard.horizontalOrigin = Cesium.HorizontalOrigin.LEFT
billboard.verticalOrigin = Cesium.VerticalOrigin.BASELINE
billboard.pixelOffset = new Cesium.Cartesian2(delta.x / 2 - billboard.width / 2, delta.y / 2)
} else if (delta.x > 0 && delta.y < 0) {
billboard.horizontalOrigin = Cesium.HorizontalOrigin.LEFT
billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
billboard.pixelOffset = new Cesium.Cartesian2(delta.x / 2 - billboard.width / 2, delta.y / 2)
} else if (delta.x < 0 && delta.y < 0) {
billboard.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT
billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM
billboard.pixelOffset = new Cesium.Cartesian2(delta.x / 2 + billboard.width / 2, delta.y / 2)
} else if (delta.x < 0 && delta.y > 0) {
billboard.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT
billboard.verticalOrigin = Cesium.VerticalOrigin.BASELINE
billboard.pixelOffset = new Cesium.Cartesian2(delta.x / 2 + billboard.width / 2, delta.y / 2)
}
}
calcLablePositions() {
if (this._isDragging) return
const allKeys = Object.keys(this._cacheList._hash)
allKeys.forEach((key) => {
const delta = this._cacheList.get(key)
const entity = this._dataSource.entities.getById(key)
const div = document.getElementById(key)
if (entity) {
const C3 = entity.position.x ? entity.position : entity.position.getValue()
const windowPos = this._viewer.scene.cartesianToCanvasCoordinates(C3)
if (windowPos && div) {
div.style.left = `${windowPos.x + delta.x}px`
div.style.top = `${windowPos.y - div.offsetHeight + delta.y}px`
}
} else {
this._cacheList.remove(key)
}
})
}
destroy() {
this._viewer.clock.onTick.removeEventListener(this.calcLablePositions, this)
}
}