代码迁移
This commit is contained in:
589
src/Obj/Base/LabelObject/index.js
Normal file
589
src/Obj/Base/LabelObject/index.js
Normal file
@ -0,0 +1,589 @@
|
||||
/**
|
||||
* 标注
|
||||
*/
|
||||
import Base from '../index'
|
||||
import MouseEvent from '../../../Event/index'
|
||||
import {
|
||||
getGroundCover
|
||||
} from '../../../Global/global'
|
||||
import { getFontFamily } from '../../Element/fontSelect'
|
||||
import {
|
||||
addCluster,
|
||||
remove_entity_from_cluster
|
||||
} from '../../../Global/cluster/cluster'
|
||||
|
||||
class LabelObject extends Base {
|
||||
#updateBillboardImageTimeout
|
||||
constructor(sdk, options = {}, model) {
|
||||
super(sdk, options)
|
||||
this.model = model
|
||||
this.options.near = options.near || options.near === 0 ? options.near : 2000
|
||||
this.options.far = options.far || options.far === 0 ? options.far : 100000
|
||||
this.options.scaleByDistance = options.scaleByDistance || false
|
||||
this.options.show =
|
||||
options.show || options.show === false ? options.show : true
|
||||
this.options.text = options.text
|
||||
let textArray = this.options.text.split('\n')
|
||||
for (let i = 0; i < textArray.length; i++) {
|
||||
if (textArray[i].length > 40) {
|
||||
textArray[i] = textArray[i].slice(0, 40 - textArray[i].length)
|
||||
}
|
||||
}
|
||||
if (textArray.length > 10) {
|
||||
textArray.splice(10 - textArray.length)
|
||||
}
|
||||
this.options.text = textArray.join('\n')
|
||||
this.options.fontFamily = options.fontFamily || 0
|
||||
this.font = getFontFamily(this.options.fontFamily) || 'Helvetica'
|
||||
this.options.fontSize = options.fontSize || 20
|
||||
this.options.lineWidth = options.lineWidth || 4
|
||||
this.options.lineColor = options.lineColor || '#fff000'
|
||||
this.options.color = options.color || '#ffffff'
|
||||
this.options.ground =
|
||||
options.ground || options.ground === false ? options.ground : true
|
||||
this.options.pixelOffset =
|
||||
options.pixelOffset || options.pixelOffset === 0
|
||||
? options.pixelOffset
|
||||
: 20
|
||||
this.options.backgroundColor = options.backgroundColor || [
|
||||
'#42c6ef',
|
||||
'#42c6ef'
|
||||
]
|
||||
this.event = new MouseEvent(this.sdk)
|
||||
this.entity
|
||||
this.create(this.options.position)
|
||||
this.picking = true
|
||||
}
|
||||
|
||||
async create() {
|
||||
let _this = this
|
||||
if (!this.options.position[2] && this.options.position[2] !== 0) {
|
||||
this.options.position[2] = await this.getClampToHeight({
|
||||
lng: this.options.position[0],
|
||||
lat: this.options.position[1]
|
||||
})
|
||||
}
|
||||
this.originalOptions = copyObj(this.options)
|
||||
|
||||
this.entity = this.sdk.viewer.entities.add({
|
||||
show: this.options.show,
|
||||
id: this.options.id + '-label',
|
||||
position: new Cesium.CallbackProperty(function () {
|
||||
if (_this.model) {
|
||||
// return Cesium.Cartesian3.fromDegrees(_this.options.position[0], _this.options.position[1], _this.model.originalBoundingSphereRadius*2*_this.model.customScale.z + _this.options.position[2])
|
||||
if (_this.model.isMove) {
|
||||
let scale = _this.model.customScale.x
|
||||
if (_this.model.customScale.y > scale) {
|
||||
scale = _this.model.customScale.y
|
||||
}
|
||||
if (_this.model.customScale.z > scale) {
|
||||
scale = _this.model.customScale.z
|
||||
}
|
||||
let point1 = Cesium.Cartesian3.fromDegrees(
|
||||
_this.options.position[0],
|
||||
_this.options.position[1],
|
||||
_this.options.position[2] +
|
||||
(_this.model.originalBoundingSphereRadius || 1) *
|
||||
2 *
|
||||
(scale || 0.01)
|
||||
)
|
||||
// 点2的位置,也使用经纬高表示
|
||||
let point2 = Cesium.Cartesian3.fromDegrees(
|
||||
_this.options.position[0],
|
||||
_this.options.position[1],
|
||||
_this.options.position[2] -
|
||||
(_this.model.originalBoundingSphereRadius || 1) *
|
||||
2 *
|
||||
(scale || 0.01)
|
||||
)
|
||||
let direction = Cesium.Cartesian3.subtract(
|
||||
point2,
|
||||
point1,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
let c = Cesium.Cartesian3.normalize(direction, direction)
|
||||
let ray = new Cesium.Ray(point1, c)
|
||||
let pickedObjects = _this.viewer.scene.drillPickFromRay(ray, 5)
|
||||
for (let i = 0; i < pickedObjects.length; i++) {
|
||||
if (
|
||||
pickedObjects[i].object &&
|
||||
pickedObjects[i].object.id &&
|
||||
pickedObjects[i].object.id === _this.model.id
|
||||
) {
|
||||
let pos84 = _this.cartesian3Towgs84(pickedObjects[i].position, _this.sdk.viewer)
|
||||
_this.options.position[0] = pos84.lng
|
||||
_this.options.position[1] = pos84.lat
|
||||
_this.options.position[2] = pos84.alt
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Cesium.Cartesian3.fromDegrees(
|
||||
_this.options.position[0],
|
||||
_this.options.position[1],
|
||||
_this.options.position[2]
|
||||
)
|
||||
} else {
|
||||
return Cesium.Cartesian3.fromDegrees(..._this.options.position)
|
||||
}
|
||||
}, false),
|
||||
billboard: {
|
||||
image: this.getcanvas(),
|
||||
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
disableDepthTestDistance: new Cesium.CallbackProperty(function () {
|
||||
return getGroundCover() ? undefined : Number.POSITIVE_INFINITY
|
||||
}, false),
|
||||
scaleByDistance: this.options.scaleByDistance
|
||||
? new Cesium.NearFarScalar(this.options.near, 1, this.options.far, 0)
|
||||
: undefined,
|
||||
pixelOffsetScaleByDistance: this.options.scaleByDistance
|
||||
? new Cesium.NearFarScalar(this.options.near, 1, this.options.far, 0)
|
||||
: undefined
|
||||
}
|
||||
// label: {
|
||||
// show: this.options.show,
|
||||
// text: new Cesium.CallbackProperty(function () {
|
||||
// return _this.options.text
|
||||
// }, false),
|
||||
// font: this.options.fontSize + "px Helvetica",
|
||||
// fillColor: Cesium.Color.fromCssColorString(this.options.color),
|
||||
// pixelOffset: new Cesium.Cartesian2(0, -this.options.pixelOffset),
|
||||
// outlineColor: Cesium.Color.BLACK,
|
||||
// backgroundColor: Cesium.Color.fromCssColorString('#42c6ef'),
|
||||
// backgroundPadding: new Cesium.Cartesian2(12, 12),
|
||||
// showBackground: true,
|
||||
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
|
||||
// outlineWidth: 1,
|
||||
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
|
||||
// },
|
||||
})
|
||||
}
|
||||
|
||||
get position() {
|
||||
return this.options.position
|
||||
}
|
||||
set position(v) {
|
||||
// console.log(v)
|
||||
this.options.position = v
|
||||
if (!v[2] && v[2] !== 0) {
|
||||
let objectsToExclude = [...this.sdk.viewer.entities.values]
|
||||
this.getClampToHeight({
|
||||
lng: v[0],
|
||||
lat: v[1]
|
||||
}, objectsToExclude).then(height => {
|
||||
v[2] = height
|
||||
this.options.position = [...v]
|
||||
})
|
||||
// let point1 = Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], 0);
|
||||
// let point2 = Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], 10000000);
|
||||
// let direction = Cesium.Cartesian3.subtract(point2, point1, new Cesium.Cartesian3());
|
||||
// let c = Cesium.Cartesian3.normalize(direction, direction);
|
||||
// let ray = new Cesium.Ray(point1, c);
|
||||
// let r = {}
|
||||
// let pickedObjects = this.sdk.viewer.scene.drillPickFromRay(ray);
|
||||
// for (let i = 0; i < pickedObjects.length; i++) {
|
||||
// if (pickedObjects[i].position) {
|
||||
// r = pickedObjects[i]
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// if (r && r.position) {
|
||||
// this.options.position[2] = this.cartesian3Towgs84(r.position, this.sdk.viewer).alt
|
||||
// }
|
||||
// else {
|
||||
// try {
|
||||
// let promise = Cesium.sampleTerrainMostDetailed(this.sdk.viewer.terrainProvider, [Cesium.Cartographic.fromDegrees(this.options.position[0], this.options.position[1])]);
|
||||
// promise.then((p) => {
|
||||
// this.options.position[2] = p[0].height
|
||||
// }).catch((e)=>{
|
||||
// })
|
||||
// } catch (error) {
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
this.options.position = [...v]
|
||||
}
|
||||
}
|
||||
|
||||
get show() {
|
||||
return this.options.show
|
||||
}
|
||||
set show(v) {
|
||||
this.options.show = v
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.entity.show = v
|
||||
if (this.model) {
|
||||
// return Cesium.Cartesian3.fromDegrees(this.options.position[0], this.options.position[1], this.model.originalBoundingSphereRadius*2*this.model.customScale.z + this.options.position[2])
|
||||
let scale = this.model.customScale.x
|
||||
if (this.model.customScale.y > scale) {
|
||||
scale = this.model.customScale.y
|
||||
}
|
||||
if (this.model.customScale.z > scale) {
|
||||
scale = this.model.customScale.z
|
||||
}
|
||||
let point1 = Cesium.Cartesian3.fromDegrees(
|
||||
this.options.position[0],
|
||||
this.options.position[1],
|
||||
this.options.position[2] +
|
||||
(this.model.originalBoundingSphereRadius || 1) *
|
||||
2 *
|
||||
(scale || 0.01)
|
||||
)
|
||||
// 点2的位置,也使用经纬高表示
|
||||
let point2 = Cesium.Cartesian3.fromDegrees(
|
||||
this.options.position[0],
|
||||
this.options.position[1],
|
||||
this.options.position[2] -
|
||||
(this.model.originalBoundingSphereRadius || 1) *
|
||||
2 *
|
||||
(scale || 0.01)
|
||||
)
|
||||
let direction = Cesium.Cartesian3.subtract(
|
||||
point2,
|
||||
point1,
|
||||
new Cesium.Cartesian3()
|
||||
)
|
||||
let c = Cesium.Cartesian3.normalize(direction, direction)
|
||||
let ray = new Cesium.Ray(point1, c)
|
||||
let pickedObjects = this.viewer.scene.drillPickFromRay(ray, 5)
|
||||
for (let i = 0; i < pickedObjects.length; i++) {
|
||||
if (
|
||||
pickedObjects[i].object &&
|
||||
pickedObjects[i].object.id &&
|
||||
pickedObjects[i].object.id === this.model.id
|
||||
) {
|
||||
let pos84 = this.cartesian3Towgs84(pickedObjects[i].position, this.sdk.viewer)
|
||||
this.options.position[0] = pos84.lng
|
||||
this.options.position[1] = pos84.lat
|
||||
this.options.position[2] = pos84.alt
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (this.options.ground) {
|
||||
let objectsToExclude = [...this.sdk.viewer.entities.values]
|
||||
this.getClampToHeight({
|
||||
lng: this.options.position[0],
|
||||
lat: this.options.position[1]
|
||||
}, objectsToExclude).then(height => {
|
||||
this.options.position[2] = height
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
get text() {
|
||||
return this.options.text
|
||||
}
|
||||
set text(v) {
|
||||
this.options.text = v
|
||||
let textArray = this.options.text.split('\n')
|
||||
for (let i = 0; i < textArray.length; i++) {
|
||||
if (textArray[i].length > 40) {
|
||||
textArray[i] = textArray[i].slice(0, 40 - textArray[i].length)
|
||||
}
|
||||
}
|
||||
if (textArray.length > 10) {
|
||||
textArray.splice(10 - textArray.length)
|
||||
}
|
||||
this.options.text = textArray.join('\n')
|
||||
this.entity && (this.updateBillboardImage())
|
||||
}
|
||||
|
||||
get color() {
|
||||
return this.options.color
|
||||
}
|
||||
set color(v) {
|
||||
this.options.color = v
|
||||
this.entity && (this.entity.billboard.image = this.getcanvas())
|
||||
}
|
||||
|
||||
get scaleByDistance() {
|
||||
return this.options.scaleByDistance
|
||||
}
|
||||
set scaleByDistance(v) {
|
||||
this.options.scaleByDistance = v
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
if (this.options.scaleByDistance) {
|
||||
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
} else {
|
||||
this.entity.billboard.scaleByDistance = undefined
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = undefined
|
||||
}
|
||||
}
|
||||
|
||||
get near() {
|
||||
return this.options.near
|
||||
}
|
||||
set near(v) {
|
||||
let near = v
|
||||
if (near > this.far) {
|
||||
near = this.far
|
||||
}
|
||||
this.options.near = near
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
if (this.options.scaleByDistance) {
|
||||
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
} else {
|
||||
this.entity.billboard.scaleByDistance = undefined
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = undefined
|
||||
}
|
||||
}
|
||||
|
||||
get far() {
|
||||
return this.options.far
|
||||
}
|
||||
set far(v) {
|
||||
let far = v
|
||||
if (far < this.near) {
|
||||
far = this.near
|
||||
}
|
||||
this.options.far = far
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
if (this.options.scaleByDistance) {
|
||||
this.entity.billboard.scaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(
|
||||
this.options.near,
|
||||
1,
|
||||
this.options.far,
|
||||
0
|
||||
)
|
||||
} else {
|
||||
this.entity.billboard.scaleByDistance = undefined
|
||||
this.entity.billboard.pixelOffsetScaleByDistance = undefined
|
||||
}
|
||||
}
|
||||
|
||||
get fontSize() {
|
||||
return this.options.fontSize
|
||||
}
|
||||
set fontSize(v) {
|
||||
this.options.fontSize = Number(v)
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.updateBillboardImage()
|
||||
}
|
||||
|
||||
get fontFamily() {
|
||||
return this.options.fontFamily
|
||||
}
|
||||
|
||||
set fontFamily(v) {
|
||||
this.options.fontFamily = v || 0
|
||||
this.font = getFontFamily(this.options.fontFamily) || 'Helvetica'
|
||||
this.updateBillboardImage()
|
||||
}
|
||||
|
||||
get lineWidth() {
|
||||
return this.options.lineWidth
|
||||
}
|
||||
set lineWidth(v) {
|
||||
this.options.lineWidth = Number(v)
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.updateBillboardImage()
|
||||
}
|
||||
|
||||
get pixelOffset() {
|
||||
return this.options.pixelOffset
|
||||
}
|
||||
set pixelOffset(v) {
|
||||
this.options.pixelOffset = Number(v)
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.updateBillboardImage()
|
||||
}
|
||||
updateBillboardImage() {
|
||||
clearTimeout(this.#updateBillboardImageTimeout)
|
||||
this.#updateBillboardImageTimeout = setTimeout(() => {
|
||||
clearTimeout(this.#updateBillboardImageTimeout)
|
||||
this.entity.billboard.image = this.getcanvas()
|
||||
}, 500)
|
||||
}
|
||||
get lineColor() {
|
||||
return this.options.pixelOffset
|
||||
}
|
||||
set lineColor(v) {
|
||||
this.options.lineColor = v
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.entity.billboard.image = this.getcanvas()
|
||||
}
|
||||
|
||||
get backgroundColor() {
|
||||
return this.options.backgroundColor
|
||||
}
|
||||
set backgroundColor(v) {
|
||||
this.options.backgroundColor = v
|
||||
if (!this.entity) {
|
||||
return
|
||||
}
|
||||
this.entity.billboard.image = this.getcanvas()
|
||||
}
|
||||
|
||||
get ground() {
|
||||
return this.options.ground
|
||||
}
|
||||
set ground(v) {
|
||||
this.options.ground = v
|
||||
}
|
||||
|
||||
// get backgroundColorStart() {
|
||||
// return this.options.backgroundColor[0]
|
||||
// }
|
||||
// set backgroundColorStart(v) {
|
||||
// this.options.backgroundColor[0] = v
|
||||
// this.entity.billboard.image = this.getcanvas()
|
||||
// }
|
||||
// get backgroundColorEnd() {
|
||||
// return this.options.backgroundColor[1]
|
||||
// }
|
||||
// set backgroundColorEnd(v) {
|
||||
// this.options.backgroundColor[1] = v
|
||||
// this.entity.billboard.image = this.getcanvas()
|
||||
// }
|
||||
|
||||
getcanvas() {
|
||||
const canvas = document.createElement('canvas')
|
||||
const ctx = canvas.getContext('2d')
|
||||
|
||||
ctx.font = this.options.fontSize + 'px ' + this.font
|
||||
let texts = this.options.text.split('\n')
|
||||
let canvasWidth = 0
|
||||
let canvasHeight = 0
|
||||
for (let i = 0; i < texts.length; i++) {
|
||||
const text = texts[i]
|
||||
const width = ctx.measureText(text).width
|
||||
if (width > canvasWidth) {
|
||||
canvasWidth = width
|
||||
}
|
||||
canvasHeight += this.options.fontSize
|
||||
}
|
||||
canvasHeight = canvasHeight + 20 + (texts.length - 1) * 5
|
||||
canvasWidth = canvasWidth + 30
|
||||
if (canvasWidth < this.options.lineWidth) {
|
||||
canvasWidth = this.options.lineWidth
|
||||
}
|
||||
canvas.width = canvasWidth
|
||||
|
||||
canvas.height = this.options.pixelOffset + canvasHeight
|
||||
const linearGradient = ctx.createLinearGradient(
|
||||
0,
|
||||
0,
|
||||
canvasWidth,
|
||||
canvasHeight + 20
|
||||
)
|
||||
linearGradient.addColorStop(0, this.options.backgroundColor[0])
|
||||
linearGradient.addColorStop(1, this.options.backgroundColor[1])
|
||||
ctx.fillStyle = linearGradient
|
||||
ctx.fillRect(0, 0, canvasWidth, canvasHeight)
|
||||
ctx.fillStyle = this.options.color
|
||||
ctx.font = this.options.fontSize + 'px ' + this.font
|
||||
let maxWidth = 0
|
||||
for (let i = 0; i < texts.length; i++) {
|
||||
let width = ctx.measureText(texts[i]).width
|
||||
if (maxWidth < width) {
|
||||
maxWidth = width
|
||||
}
|
||||
}
|
||||
maxWidth = maxWidth + 30
|
||||
let centerDistance = (canvasWidth - maxWidth) / 2
|
||||
for (let i = 0; i < texts.length; i++) {
|
||||
const text = texts[i]
|
||||
if (this.options.fontSize < 10) {
|
||||
ctx.fillText(text, 15 + centerDistance, this.options.fontSize * (i + 1) + 10 + i * 5)
|
||||
} else {
|
||||
ctx.fillText(
|
||||
text,
|
||||
15 + centerDistance,
|
||||
this.options.fontSize * (i + 1) +
|
||||
(10 * 10) / this.options.fontSize +
|
||||
i * 5
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// 虚线
|
||||
ctx.strokeStyle = this.options.lineColor
|
||||
ctx.setLineDash([4, 4]) //设置虚线长度4,间隔为4
|
||||
ctx.lineWidth = this.options.lineWidth
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(canvasWidth / 2, canvasHeight)
|
||||
ctx.lineTo(canvasWidth / 2, canvasHeight + this.options.pixelOffset)
|
||||
ctx.stroke()
|
||||
ctx.closePath()
|
||||
|
||||
const canvas2 = document.createElement('canvas')
|
||||
const ctx2 = canvas2.getContext('2d')
|
||||
canvas2.width = canvas.width + 10
|
||||
canvas2.height = canvas.height + 10
|
||||
ctx2.drawImage(canvas, 5, 5);
|
||||
|
||||
// const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
// ctx.putImageData(imageData, 40, 40);
|
||||
return canvas2
|
||||
}
|
||||
|
||||
remove() {
|
||||
this.sdk.viewer.entities.remove(this.entity)
|
||||
this.entity = null
|
||||
}
|
||||
|
||||
flicker() { }
|
||||
}
|
||||
|
||||
export default LabelObject
|
||||
|
||||
const copyObj = (obj = {}) => {
|
||||
//变量先置空
|
||||
let newobj = null
|
||||
|
||||
//判断是否需要继续进行递归
|
||||
if (typeof obj == 'object' && obj !== null) {
|
||||
newobj = obj instanceof Array ? [] : {} //进行下一层递归克隆
|
||||
for (var i in obj) {
|
||||
newobj[i] = copyObj(obj[i])
|
||||
} //如果不是对象直接赋值
|
||||
} else newobj = obj
|
||||
return newobj
|
||||
}
|
Reference in New Issue
Block a user