本学习系列以Cesium + Vue3 +Typescript+elementplus作为主要技术栈。详情请查阅原文Vue3+Cesium学习教程系列(23)——Cesium动态标绘和编辑文字、图标(图片)、glb模型
以下便是在Cesium中实现文字、图标(图片)、模型标绘与编辑的步骤。首先新建文字类(CommonLabel)、图标类(CommonBillboard)、模型类(CommonModel)。三个类均继承BaseDraw即可。具体代码如下
import { CallbackPositionProperty, Cartesian2, Cartesian3, Color, Entity, HeightReference, HorizontalOrigin, LabelGraphics, LabelStyle, VerticalOrigin, Viewer } from "cesium";
import { BaseDraw, GeometryType } from "../BaseDraw";
import EventDispatcher from "@/system/EventDispatcher/EventDispatcher";
export default class CommonLabel extends BaseDraw {
private labelOption: LabelGraphics.ConstructorOptions
constructor(viewer: Viewer, dispatcher: EventDispatcher) {
super(viewer, dispatcher);
this.geometryType = GeometryType.COMMON_LABEL;
this.labelOption = {
text: '测试名称xttx110',
font: '14pt Source Han Sans CN',
fillColor: Color.BLUE,
backgroundColor: Color.YELLOW,
showBackground: true,
scale: 1.0,
style: LabelStyle.FILL_AND_OUTLINE,
// 相对于坐标的水平位置
verticalOrigin: VerticalOrigin.CENTER,
// 相对于坐标的水平位置
horizontalOrigin: HorizontalOrigin.LEFT,
// 该属性指定标签在屏幕空间中距此标签原点的像素偏移量
pixelOffset: new Cartesian2(10, 0),
// 关闭深度测试,避免被地形遮挡
disableDepthTestDistance: Number.POSITIVE_INFINITY,
// 贴地显示(与 point 保持一致)
heightReference: HeightReference.CLAMP_TO_GROUND,
// 是否显示
show: true
}
}
protected buildFinalEntity(): Entity {
const pos = this.getPositions()[0];
return this.viewer.entities.add({
position: pos,
point: { pixelSize: 12, color: Color.RED, heightReference: HeightReference.CLAMP_TO_GROUND, disableDepthTestDistance: Number.POSITIVE_INFINITY },
label: this.labelOption
});
}
protected buildTempEntity(): Entity | undefined {
return this.viewer.entities.add({
position: new CallbackPositionProperty(() => this.tempCursor || new Cartesian3(), false),
point: { pixelSize: 12, color: Color.RED, heightReference: HeightReference.CLAMP_TO_GROUND, disableDepthTestDistance: Number.POSITIVE_INFINITY },
label: this.labelOption
});
}
protected onLeftClick(e: any) {
super.onLeftClick(e);
// 点只需要 1 次点击即可结束
this.finish();
}
}
import { BillboardGraphics, CallbackPositionProperty, Cartesian3, Entity, HeightReference, HorizontalOrigin, VerticalOrigin, Viewer } from "cesium";
import { BaseDraw, GeometryType } from "../BaseDraw";
import EventDispatcher from "@/system/EventDispatcher/EventDispatcher";
export default class CommonBillboard extends BaseDraw {
private billboardOption:BillboardGraphics.ConstructorOptions
constructor(viewer: Viewer, dispatcher: EventDispatcher) {
super(viewer, dispatcher);
this.geometryType = GeometryType.COMMON_LABEL;
this.billboardOption={
// 图像地址,URI或Canvas的属性
image: '/testdata/images/mark1.png',
// 高度(以像素为单位)
height: 50,
// 宽度(以像素为单位)
width: 50,
// 相对于坐标的垂直位置
verticalOrigin: VerticalOrigin.BOTTOM,
// 相对于坐标的水平位置
horizontalOrigin: HorizontalOrigin.CENTER,
// 关闭深度测试,避免被地形遮挡
disableDepthTestDistance: Number.POSITIVE_INFINITY,
// 贴地显示(与 point 保持一致)
heightReference: HeightReference.CLAMP_TO_GROUND,
// 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。
scale: 1.0,
// 是否显示
show: true
}
}
protected buildFinalEntity(): Entity {
const pos = this.getPositions()[0];
return this.viewer.entities.add({
position: pos,
// point: { pixelSize: 12, color: Color.RED, heightReference: HeightReference.CLAMP_TO_GROUND, disableDepthTestDistance: Number.POSITIVE_INFINITY },
billboard: this.billboardOption
});
}
protected buildTempEntity(): Entity | undefined {
return this.viewer.entities.add({
position: new CallbackPositionProperty(() => this.tempCursor || new Cartesian3(), false),
billboard: this.billboardOption
});
}
protected onLeftClick(e: any) {
super.onLeftClick(e);
// 点只需要 1 次点击即可结束
this.finish();
}
}
import { CallbackPositionProperty, Cartesian3, Cartographic, Entity, HeightReference, ModelGraphics, Viewer } from "cesium";
import { BaseDraw, GeometryType } from "../BaseDraw";
import EventDispatcher from "@/system/EventDispatcher/EventDispatcher";
export default class CommonModel extends BaseDraw {
private modelOption: ModelGraphics.ConstructorOptions;
constructor(viewer: Viewer, dispatcher: EventDispatcher) {
super(viewer, dispatcher);
this.geometryType = GeometryType.COMMON_MODEL;
this.modelOption = {
// 引入模型
uri: '/testdata/CesiumBalloon.glb',
// 模型的近似最小像素大小,而不考虑缩放。
minimumPixelSize: 150,
// 是否执行模型动画
runAnimations: true,
// 应用于图像的统一比例。比例大于会1.0放大标签,而比例小于会1.0缩小标签。
scale: 1.0,
// 贴地显示(与 point 保持一致)
heightReference: HeightReference.CLAMP_TO_GROUND,
// 是否显示
show: true
}
}
protected buildFinalEntity(): Entity {
const pos = this.getPositions()[0];
// 把模型抬高一小段,避免被地形遮挡
const carto = Cartographic.fromCartesian(pos);
const raised = Cartesian3.fromRadians(carto.longitude, carto.latitude, carto.height + 2);
return this.viewer.entities.add({
position: raised,
model: this.modelOption,
});
}
protected buildTempEntity(): Entity | undefined {
return this.viewer.entities.add({
position: new CallbackPositionProperty(() => {
const p = this.tempCursor || new Cartesian3();
const c = Cartographic.fromCartesian(p);
return Cartesian3.fromRadians(c.longitude, c.latitude, c.height + 2);
}, false),
model: this.modelOption,
});
}
protected onLeftClick(e: any) {
super.onLeftClick(e);
// 点只需要 1 次点击即可结束
this.finish();
}
}
然后将新添加的文字类、图表类和模型类添加到EditHelper中完成编辑功能。
case GeometryType.COMMON_LABEL:
case GeometryType.COMMON_BILLBOARD:
case GeometryType.COMMON_MODEL:
this.shapeEntity.position = new ConstantPositionProperty(this.positions[this.positions.length - 1]);
break;
来看看效果:
更多代码请查阅原文Vue3+Cesium学习教程系列(23)——Cesium动态标绘和编辑文字、图标(图片)、glb模型