Cesium里面的气泡

平面GIS中,点击地图出气泡是非常普遍的操作。三维地图框架Cesium里面,当然也支持,只不过样式和内容不一定符合我们要求就是了。
在这里插入图片描述
Cesium是默认支持弹出气泡的,只要在初始化时不明确将infoBox置为false,点击地图都会弹出气泡:

var viewer = new Cesium.Viewer("cesiumViewer",{
	imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
		url:"http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer"//午夜
	}),
	//点击后显示详细信息
	infoBox: true,
	……
});

但如上所述,气泡的样式和内容,在实际应用中,我们需要进行设置。但问题是,在运行过程中,viewer初始化后,默认的infoBox是只读的,样式设置无效,内容也添加不进去。怎么办?这时候需要隐藏默认的infoBox,然后构造新的infoBox。

一、隐藏默认infoBox,构造新infoBox

默认的infoBox是只读的,可以说任何设置对它都无效。那如何隐藏?方法是设置infoBox对应的css样式,添加一个display=none的属性。然后再构造一个新的infoBox。

<style>
	.cesium-infoBox.hidden{
		display:none!important;
	}
</style>
//得到当前默认的infoBox
var curInfoBox = $(".cesium-infoBox");
//隐藏
curInfoBox.addClass("hidden");
//找到infoBox所在容器
var container = document.getElementsByClassName("cesium-viewer-infoBoxContainer")[0];
if(!container){//如果容器不存在,则构造一个。不存在的情况,估计是viewer初始化时,infoBox=false
	container = document.createElement('div');
	container.className = 'cesium-viewer-infoBoxContainer';
	viewer.container.appendChild(container);
}
//构造infoBox
var infoBox = new Cesium.InfoBox(container);
viewModel = infoBox.viewModel;//只要设置这个viewModel,就能控制气泡的显隐
viewModel.closeClicked.addEventListener(function(){//点击气泡右上角的关闭按钮
	viewModel.showInfo = false;//关闭气泡
});

二、点击时,设置内容并弹出infoBox

var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function (movement) {
	let pick = viewer.scene.pick(movement.position);
	if (Cesium.defined(pick)) {
		setView(pick);
	}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);//鼠标左键点击

function setView(pick){//展示气泡
	//pick是被点击的对象。pick.id不是一个数值,而是一个json对象,它会自动将被点击对象的属性包含在内。我们可以将关键性信息存放在这里。
	let name = pick.id.name;
	if(name == 'node'){
		showNode();
	} else if(name == 'fnode'){
		。。。
	}
	viewModel.showInfo = true;//显示气泡
}
function showNode(){//装配气泡
	let n = ...;
	if(n){
		viewModel.titleText = n.cname + "(" + n.code + ")";//气泡标题
		let nd = n.nd;
		let wc = nd.windCircle;
		let desc = TIPSTYLE + getTplNode(nd,wc);//气泡具体内容,见下面
		viewModel.description = desc;					
	}
	
	let TIPSTYLE = `<style>
		.tfhidden{visibility:hidden;}
		t{width:120px;text-align:right;font-weight:bold;margin-left:3px;margin-right:7px;color:#ccc;}	
		table,th,td{font-size:12px!important}
		th{color:#ccc;}
		</style>`;
	function getTplNode(nd,wc){ 
		return `<div><t>过去时间:</t>${getDateStr(nd.date)}</div>
		<div><t>中心位置:</t>${nd.y}N/${nd.x}E</div>
		<div><t>最大风速:</t>${nd.maxWindSpeed}米/秒</div>
		<div><t>中心气压:</t>${nd.centerPower}百帕</div>
		<div><t>移动方向:</t>${nd.direction}</div>
		<div><t>移动速度:</t>${nd.speed}公里/小时</div>
		<div><t>类<span class='tfhidden'>类型</span>型:</t>${nd.type.name}</div>
		<div><table><thead><tr><th>风圈半径</th><th>东北</th><th>东南</th><th>西南</th><th>西北</th><th style='width:25px;'></th></tr></thead>
		<tr><td>7级</td><td>${wc.c7.EN||''}</td><td>${wc.c7.ES||''}</td><td>${wc.c7.WS||''}</td><td>${wc.c7.WN||''}</td><td>KM</td></tr>
		<tr><td>10级</td><td>${wc.c10.EN||''}</td><td>${wc.c10.ES||''}</td><td>${wc.c10.WS||''}</td><td>${wc.c10.WN||''}</td><td>KM</td></tr>
		<tr><td>12级</td><td>${wc.c12.EN||''}</td><td>${wc.c12.ES||''}</td><td>${wc.c12.WS||''}</td><td>${wc.c12.WN||''}</td><td>KM</td></tr>
		</table></div>`;
	}
}
//某对象,鼠标点击它出气泡
function getNode(nd,index,tfId){
	var point = Cesium.Cartesian3.fromDegrees(nd.x, nd.y,HEIGHT);
	return viewer.entities.add({//以下属性,都会在pick.id里出现
		id : 'n-' + tfId + '-' + index,
		name : 'node',
		position : point,
		point : {
			pixelSize: 10,
			...
		}
	});
}

效果见下图右上角
在这里插入图片描述

三、简易提示

气泡点击时弹出。但动静比较大,我们可以设置鼠标划过一些对象时,弹出一些简易的提示,如上图下方。

简易提示主要使用 Label。用法也比较简单:

function TipLabel(td){//小提示
	let scene = viewer.scene;
	let label = getLable();
	
	let handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
	handler.setInputAction(function (movement) {
		var pick = viewer.scene.pick(movement.endPosition);
		if (pick && Cesium.defined(pick)) {
			show(pick,movement);
		}
	}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
	
	function show(pick,movement) {
		var cartesian = viewer.camera.pickEllipsoid(movement.endPosition,scene.globe.ellipsoid);
		if (cartesian) {
		    let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
		    let longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(2);
		    let latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(2);

			let d = td.point(pick.id.id);
		    label.position = cartesian;
		    label.label.show = true;
			if(d.type == 'c'){
				label.label.text = getTplCircleSimple(d.nd,d.wc);
			} else if(d.type == 'f'){
				...
			} else {
				...
			}
		}
	}
	function getTplCircleSimple(nd,wcLevel){ 
		let wc = nd.windCircle;
		let wn = wc['c' + wcLevel].WN||'';
		let en = wc['c' + wcLevel].EN||'';
		let ws = wc['c' + wcLevel].WS||'';
		let es = wc['c' + wcLevel].ES||'';
		
		return `时    间:${getDateStr(nd.date)}\n风圈级别:${wcLevel}级\n风圈半径:\n西北${wn}公里 | 东北${en}公里\n-------------------------\n西南${ws}公里 | 东南${es}公里`;
	}		
	function getLable() {//构造一个label
	    return viewer.entities.add({
	        label: {
	            show: false,
	            showBackground: true,
	            font: "14px monospace",
	            horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
	            verticalOrigin: Cesium.VerticalOrigin.TOP,
	            pixelOffset: new Cesium.Cartesian2(5, 0),
				eyeOffset: new Cesium.Cartesian3(0.0, 0.0, 45000.0),
	        },
	    });
	}
	function hideLabel(){//隐藏简易提示
		label.label.show = false;
	}
}
相关推荐
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页