问题:建筑模型属性查看
思路:白膜数据自带属性,
1.用div弹窗监听场景变化逐帧更新div位置,据群友说这样体验不是很好。
2.把属性写到canvas,然后用生成canvas去填充广告牌。
说在前面:第一张3DMaxs建的模型;第二张这是自己用shp文件直接生成的白模根据楼层分成了三类,感觉还不错哩。
但这不是今天讨论的话题。今天的主题是鼠标滑过建筑的时候显示信息,点击双击的时候把属性写到canvas,然后用生成canvas去填充广告牌
自己封装到CommonBuild这个类里面的,代码写的乱七八糟的估计也没几个人看得懂。
上吧:CommonBuild.js
export default class CommonBuild {
constructor(viewer, tilesURL, centerPosintion) {
this.viewer = viewer,
this.tilesURL = tilesURL,
this.build = null,
this.centerPosintion = centerPosintion,
this.isAdded = false,
this.buildHandler = null,
this.buildLable = viewer.entities.add({
label: {
id: "buildLable",
show: false,
showBackground: true,
font: '14px monospace',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,//水平位置
verticalOrigin: Cesium.VerticalOrigin.Bottom,//垂直位置
pixelOffset: new Cesium.Cartesian2(0, -50),//向上偏移50
zIndex: 999
}
})
}
}
CommonBuild.prototype = {
// 添加一般建筑物的3Dtiles
addCommonBuild() {
let _this = this;
this.build = new Cesium.Cesium3DTileset({
url: _this.tilesURL,
skipLevelOfDetail: true,
maximumMemoryUsage: 2000,
preferLeaves: true,
maximumScreenSpaceError: 16,
show: true
});
let buildBIM = this.viewer.scene.primitives.add(_this.build);
buildBIM.readyPromise.then(function (argument) {
let rotationX = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(0)));
let rotationY = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(0)));
let rotationZ = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(0)));
let m = Cesium.Transforms.eastNorthUpToFixedFrame( _this.centerPosintion );
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(m, rotationX, m);
Cesium.Matrix4.multiply(m, rotationY, m);
Cesium.Matrix4.multiply(m, rotationZ, m);
argument._root.transform = m;
});
},
// 监听属性
whatchAttribute(){
let _this = this;
let viewer = this.viewer;
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);// 移除事件
/*鼠标移动选择建筑*/
let selected = {
feature: undefined,
originalColor: new Cesium.Color()
};
let highlighted = {
feature: undefined,
originalColor: new Cesium.Color()
};
let selectedEntity = new Cesium.Entity();
this.buildHandler = new Cesium.ScreenSpaceEventHandler(_this.viewer.scene.canvas);
// 鼠标左键双击
viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
let entity = _this.viewer.entities.getById("buildTable");
if(entity){
_this.viewer.entities.remove(entity);
}
if (Cesium.defined(selected.feature)) {
selected.feature.color = selected.originalColor;
selected.feature = undefined;
}
let pickedObject = _this.viewer.scene.pick(movement.position);
if (!Cesium.defined(pickedObject) || !Cesium.defined(pickedObject.getProperty)) {
return;
}
if (selected.feature === pickedObject) {
return;
}
// 以下才是点击到行建筑的有效操作
selected.feature = pickedObject;
if (pickedObject === highlighted.feature) {
Cesium.Color.clone(highlighted.originalColor, selected.originalColor);
highlighted.feature = undefined;
} else {
Cesium.Color.clone(pickedObject.color, selected.originalColor);
}
pickedObject.color = Cesium.Color.RED;
let cartesian = _this.viewer.scene.pickPosition(movement.position);
let img = document.createElement('img');
img.src = require("./tableBack.png");//这里是背景图片就是广告牌的那个框框
img.onload = function(){
let canvas = document.createElement("canvas");
canvas.width = 215;
canvas.height = 325;
let context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
context.font = '15px bold sans-serif';
context.fillStyle = "#f8e009";
// context.textBaseline = "middle";
let propertyNames = pickedObject.getPropertyNames();
let lineText = "";
let lineHeight = 22;
for (let attribute of propertyNames) {
if( attribute == '_bp' ) continue ;
let value = pickedObject.getProperty(attribute)? pickedObject.getProperty(attribute):"缺失" ;
lineText = attribute +':'+value+ '\n';
context.fillText(lineText, 20, lineHeight);
lineHeight += 18;
}
_this.viewer.entities.add({
id: "buildTable",
position: cartesian,
billboard: {
image: canvas,
scaleByDistance: new Cesium.NearFarScalar(500, 1.0, 5000, 0),
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
width:215,
height:325,
zIndex: 1000,
pixelOffsetScaleByDistance : new Cesium.NearFarScalar(500, 1.0, 5000, 0),
}
}) ;
};
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
// 鼠标滑过事件
viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement) {
let pickedObject = _this.viewer.scene.pick(movement.endPosition);
if (!Cesium.defined(pickedObject) || !Cesium.defined(pickedObject.getProperty)) {
_this.buildLable.label.show = false;
if (highlighted.feature){
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}
return;
}
if (Cesium.defined(highlighted.feature)) {
highlighted.feature.color = highlighted.originalColor;
highlighted.feature = undefined;
}
if (pickedObject !== selected.feature) {
highlighted.feature = pickedObject;
Cesium.Color.clone(pickedObject.color, highlighted.originalColor);
pickedObject.color = new Cesium.Color.fromCssColorString('#1c9408');
}
let cartesian = _this.viewer.scene.pickPosition(movement.endPosition);
if (Cesium.defined(cartesian)) {
// 开启添加模型的监听后移动鼠标显示当前坐标位置
_this.buildLable.position = cartesian;
_this.buildLable.label.show = true;
let str = "";
let name = pickedObject.getProperty('建筑名');
let height = pickedObject.getProperty('高度');
if (!Cesium.defined(name) || !name) {
str += '建筑名称:缺失'+ '\n' +'建筑高度:'+height.toFixed(2)+ '\n'+'左键双击查看详情';
} else {
str += '建筑名称:' +name+ '\n' + '建筑高度:'+height.toFixed(2)+ '\n'+'左键双击查看详情' ;
}
_this.buildLable.label.text = str;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
},
// 停止监听属性
stopWhatchAttribute(){
if(this.buildHandler){
this.buildHandler.destroy();
}
// 可能需要弹窗关闭
let entity = this.viewer.entities.getById("buildTable");
if(entity){
this.viewer.entities.remove(entity);
}
this.buildHandler = null;
this.buildLable.label.show = false;
}
}
最后记录两句心情,今天群里的朋友说我们写csdn是为了==》》骗 流 量。
首先:用优快云是因为习惯了这个编辑风格。文字可以变颜色、图骗可以调大小、会自动突出关键字
然后:个人并木有从写博客中获得利益,完全出于喜欢,而且记录自己走过的弯路。
虽然写的东西很多人都做过,
但是:自己去做的时候也还是废了时间和精力的,而且也有自己的思维和创新。记录下来,以后可以看。