C2 —— 建筑属性查看:带属性的广告牌

问题:建筑模型属性查看

思路:白膜数据自带属性,

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是为了==》》骗 流 

首先:用CSDN是因为习惯了这个编辑风格。文字可以变颜色图骗可以调大小会自动突出关键字

然后:个人并木有从写博客中获得利益,完全出于喜欢,而且记录自己走过的弯路。

虽然写的东西很多人都做过,

但是:自己去做的时候也还是废了时间精力的,而且也有自己的思维创新。记录下来,以后可以看。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值