Cesium实现自定义标签功能
实现的底层逻辑和方法跟实现Popup弹窗功能类似,只需要修改对应的创建的html内容和css样式,即可定义出更好看的标签。
实现效果
源码
LabelPlot 标签类
const defaultNameField = "label";
const defaultIdField = "id";
const billboardPointDatasourceName = "LABELPLOT_BILLBOARD_POINT"
/**
* 标签类
*/
class LabelPlot {
constructor(info) {
let _this = this;
_this.viewer = info.viewer; //弹窗创建的viewer
_this.geometry = info.position; //弹窗挂载的位置
_this.properties = info.properties; // 属性信息
if (!info || !info.viewer || !info.position) {
throw new Error("缺少构造参数!");
}
let labelPlotId = _this._getKeyVal(info.properties,defaultIdField);
if (!labelPlotId) {
labelPlotId = "LabelPlot_" + (new Date().getTime() + Math.random() + '').replace('.', '');
}
_this.id = labelPlotId;
_this.ctn = $("<div class='LabelPlot-container' id = '" + _this.id + "'>");
$(_this.viewer.container).append(_this.ctn);
_this.ctn.append(_this._createHtml(info.properties));
//生成底座小圆点
if (!!info.showBillboardPoint) {
_this.entity = _this._createBillboardPoint(info.position);
}
try {
_this._render(_this.geometry);
_this.eventListener = _this.viewer.clock.onTick.addEventListener(function (clock) {
_this._render(_this.geometry);
})
} catch (e) {
}
}
//关闭当前标签
close() {
let _this = this;
_this.ctn.remove();
_this.viewer.clock.onTick.removeEventListener(_this.eventListener);
if (_this.entity) {
let myEntityCollection = _this._getBillboardPointEntityCollection();
myEntityCollection.entities.remove(_this.entity);
}
}
//清除所有的小圆点
static clearBillboardPointEntityCollection(){
let dats = Viewer.dataSources.getByName(billboardPointDatasourceName);
if (!!dats && !!dats.length) {
dats.forEach(item => {
Viewer.dataSources.remove(item);
})
}
}
_render(geometry) {
let _this = this;
let position = Cesium.SceneTransforms.wgs84ToWindowCoordinates(_this.viewer.scene, geometry);
if (position) {
_this.ctn.css("left", position.x);
_this.ctn.css("top", position.y - _this.ctn.get(0).offsetHeight - 85);
//摄像头高度超过一定值,标签隐藏
/*let cameraHeight = _this.viewer.camera.positionCartographic.height;
if (cameraHeight > 50000) {
_this.ctn.hide();
} else {
_this.ctn.show();
}*/
}
}
//生成标签
_createHtml(properties) {
let _this = this;
let labelName = _this._getKeyVal(properties,defaultNameField);
labelName = !!labelName ? labelName : "";
let html = '<div class="LabelPlot-content">' +
'<div class="info-item">'+ labelName +'</div></div>';
return html;
}
//生成底下的小圆点
_createBillboardPoint(position) {
let _this = this;
let myEntityCollection = _this._getBillboardPointEntityCollection();
let entityOption = {
name: "LABELPLOT_BILLBOARD_POINT_ENTITY",
position: position,
point: { //点
color: Cesium.Color.DARKBLUE.withAlpha(.4),
pixelSize: 6,
outlineColor: Cesium.Color.YELLOW.withAlpha(.4),
outlineWidth: 2,
// scaleByDistance: new Cesium.NearFarScalar(300, 1, 1200, .4),
// disableDepthTestDistance: 500
}
}
let entity = new Cesium.Entity(entityOption);
if (entity && myEntityCollection) {
myEntityCollection.entities.add(entity);
}
return entity;
}
_getKeyVal(data,keyName) {
let keyVal = null;
if (!!data && !!keyName && !!Object.keys(data).length) {
let keys = Object.keys(data);
for (let index = 0 ; index < keys.length;index++) {
if (keys[index].toLowerCase() === keyName) {
keyVal = data[keys[index]];
break;
}
}
}
return keyVal;
}
_getBillboardPointEntityCollection() {
let _this = this;
let myEntityCollection = null;
let dats = _this.viewer.dataSources.getByName(billboardPointDatasourceName);
if (!dats || !dats.length) {
myEntityCollection = new Cesium.CustomDataSource(billboardPointDatasourceName);
_this.viewer.dataSources.add(myEntityCollection);
} else {
myEntityCollection = dats[0];
}
return myEntityCollection;
}
}
export default LabelPlot;
css样式
.LabelPlot-container {
background: rgba(227,238,229,.62);
position: absolute;
z-index: 999;
}
.LabelPlot-content {
left: 0;
bottom: 0;
cursor: default;
padding: 5px;
border: 1px solid rgba(156,153,68,.91);
}
.LabelPlot-container:before {
position: absolute;
content: "";
left: 0%;
bottom: -80px;
height: 80px;
border-left: 2px dashed rgba(197,226,39,.44);
}
调用示例
let labelPlotList = [];
let handler3D = new Cesium.ScreenSpaceEventHandler(Viewer.scene.canvas);
handler3D.setInputAction(function (click) {
let pick = new Cesium.Cartesian2(click.position.x, click.position.y);
if (pick) {
// 获取点击位置坐标
let cartesian = Viewer.scene.globe.pick(Viewer.camera.getPickRay(pick), Viewer.scene);
if (cartesian) {
//生成标签
let labelPlot = new LabelPlot({
viewer: Viewer,
position: cartesian,
properties: {
id: 'ilabel-'+new Date().getTime()+Math.random(),
label: 'ilabel-'+new Date().getTime()+Math.random(),
},
showBillboardPoint: true
})
labelPlotList.push(labelPlot);
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
//清除标签
if (!!labelPlotList && labelPlotList.length) {
labelPlotList.forEach(ee=>{
ee.close();
})
}
labelPlotList = [];