官方示例之地球模块十三:建筑拔高

/**
 * 该示例主要展示了根据底面坐标轮廓和高度进行拔楼的功能
 * 该示例中的插值功能主要用到了Tween.js
 * 该示例用到的数据地址为:https://www.thingjs.com/uearth/uGeo/chaoyang_building.geojson
 * 其中建筑的高度为随机值,无特殊意义
 */
var app = new THING.App();
app.background = [0, 0, 0];
var map;
THING.Utils.dynamicLoad('https://www.thingjs.com/uearth/uearth.min.js', function () {
	map = app.create({
		type: 'Map',
		attribution: 'Google'
	});

	// 创建一个瓦片图层
	var tileLayer1 = app.create({
		type: 'TileLayer',
		name: 'tileLayer1',
		url: 'https://mt{0,1,2,3}.google.cn/vt/lyrs=s&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}',
		style: {
			template: CMAP.TileLayerStyle.DARKGREEN // 设置瓦片图层的样式为DARKGREEN
		}
	});
	// 将瓦片图添加到地图中
	map.addLayer(tileLayer1);
	// 创建一个建筑物图层
	var buildingLayer = app.create({
		type: 'ThingLayer',
		name: 'buildingLayer'
	});
	// 将 buildingLayer 添加到 map 中
	map.addLayer(buildingLayer);

	// 飞到地理位置和高度
	app.camera.earthFlyTo({
		lonlat: [116.4488, 39.9187],
		height: 4000,
		time: 2000,
		lerp: THING.LerpType.Linear.None,
		complete: function () {
			app.camera.curOrbit.setState();
			setTimeout(createBuilding, 1000);
		}
	});
	var createBuilding = function () {
		$.ajax({
			type: 'GET',
			url: 'https://www.thingjs.com/uearth/uGeo/chaoyang_building.geojson',
			dataType: 'json',
			success: function (data) {
				// 对数据进行排序
				sortBuildData(data);
				// 加载楼宇
				addBuildAsync(data, 0, function () {
				});
			}
		});
	};
	// 每次创建建筑数量
	var step = 70;
	function addBuildAsync(arr, start, cb) {
		var building;
		var i = start;
		var j = THING.Math.min(start + step, arr.features.length);
		// 循环创建建筑,先将其高度都设置成1米
		for (; i < j; i += 1) {
			building = app.create({
				type: 'GeoBuilding',
				name: 'build' + i,
				coordinates: arr.features[i].geometry.coordinates,
				userData: arr.features[i].properties,
				height: 1,
				renderer: {
					type: 'image',
					imageUrl: ['https://www.thingjs.com/uearth/uGeo/building_top.png', 'https://www.thingjs.com/uearth/uGeo/building.png'], // 楼宇顶部贴图和侧边贴图
					blending: true, // 贴图叠加混合
					textureWrap:CMAP.TextureWrapMode.Stretch
				}
			});
			buildingLayer.add(building);
		}
		if (j < arr.features.length) {
			// 异步递归下一次循环
			setTimeout(function () {
				addBuildAsync(arr, j, cb);
			}, 0);
		}
		else if (typeof cb === 'function') {
			cb();
		}
	}
	// 对楼宇数据按照其中心点,从西到东排序
	function sortBuildData(arr) {
		arr.features.sort(function (a, b) {
			return (a.properties.centerx - b.properties.centerx);
		});
	}
	// 不同街道的相机视角
	var camPos = {
		'建外街道': {
			position: [2179362.5621945052, 4091446.2018570947, 4382089.316474768],
			target: [2178592.77284655, 4091931.0390559826, 4380492.883422022],
			up: [0.34164472651390604, 0.6413960312283457, 0.6869425099451665]
		},
		'朝外街道': {
			position: [2177287.5596858454, 4093097.7380608646, 4381963.4315843275],
			target: [2177867.783281599, 4092609.529367086, 4380219.533160159],
			up: [0.3413043969490713, 0.6416204643836936, 0.6869020951396816]
		},
		'呼家楼街道': {
			position: [2180796.208593407, 4092585.7199409953, 4381166.2383312695],
			target: [2178653.476017196, 4092893.444632129, 4379563.480796406],
			up: [0.3415888171867664, 0.6417205149940622, 0.6866672124171224]
		},
		'三里屯街道': {
			position: [2180049.8274386693, 4094127.8027542974, 4379868.140003332],
			target: [2178462.4045711374, 4094071.222602554, 4378557.5679814685],
			up: [0.34172853816543197, 0.6417652897142498, 0.6865558383127347]
		},
		'东外街道': {
			position: [2176806.062780602, 4093945.081429624, 4381311.039653606],
			target: [2177692.216493408, 4093814.228132429, 4379180.936632392],
			up: [0.3412325931407259, 0.641760200965019, 0.6868072231971607]
		},
		'左家庄街道': {
			position: [2178343.586772876, 4095041.600086432, 4379738.026890182],
			target: [2178049.2702569016, 4095201.3772697616, 4377706.140884884],
			up: [0.3414940843927409, 0.6420823733568143, 0.6863760020202075]
		},
		'团结湖街道': {
			position: [2180423.2727790484, 4093298.1298934473, 4380347.1220772965],
			target: [2179657.996113762, 4093548.054626523, 4378451.706304496],
			up: [0.3417463148500724, 0.6418231506156354, 0.6864928984484943]
		}, '麦子店街道': {
			position: [2180809.303744469, 4097285.615845475, 4377199.009997367],
			target: [2178441.4391688984, 4094647.778341093, 4378028.833554901],
			up: [0.34155557214940396, 0.6419955751553925, 0.686426596669003]
		}
	};

	var blocks = ['全景', '建外街道', '朝外街道', '呼家楼街道', '三里屯街道', '东外街道', '左家庄街道', '团结湖街道', '麦子店街道'];
	// 创建一个tween对象
	function grow(fromBlock, toBlock, cb) {
		var indexForm = blocks.indexOf(fromBlock);
		var indexTo = blocks.indexOf(toBlock);
		var tw = buildTween(blocks[indexForm], blocks[indexTo], cb);
		return tw;
	}
	// 创建生长动画对象
	function buildTween(fromBlock, toBlock, cb) {
		var growTween = new TWEEN.Tween({ num: 0 }).to({ num: 1 }, 3000).easing(TWEEN.Easing.Linear.None)
			.onUpdate(function (obj) {
				setBuildingHeight(fromBlock, toBlock, obj.num);
			}).onStart(function () {
				app.camera.flyTo({
					position: camPos[toBlock].position,
					target: camPos[toBlock].target,
					time: 1000,
					up: camPos[toBlock].up,
					lerp: THING.LerpType.Linear.None,
					upLerp: THING.LerpType.Linear.None
				});
			});
		return growTween;
	}
	// 遍历buildingLayer中的楼宇对象,对其设置高度
	function setBuildingHeight(fromBlock, toBlock, num) {
		// 进度条onChange触发的情况
		if (fromBlock == toBlock) {
			var temp_blocks = blocks.slice(0, blocks.indexOf(toBlock) + 1);
			buildingLayer.children.forEach(function (v) {
				v.height = 1;
				if (temp_blocks.indexOf(v.userData['district']) >= 0) {
					v.visible = true;
					v.height = v.userData['height'];
				}
			});
		}
		// tween触发的情况
		else {
			buildingLayer.children.forEach(function (v) {
				if (v.userData['district'] == toBlock) {
					var startHeight = 1;
					var stopHeight = v.userData['height'];
					var currentHeight = startHeight + (stopHeight - startHeight) * num;
					v.visible = true;
					v.height = currentHeight;
				}
			});
		}
	}
	var progressObj = { progress: 0 };
	// 创建一个进度条
	function creatProgress() {
		var bar = new THING.widget.Panel({ width: '800px' });
		bar.position = [10, 10];
		var progress = bar.addProgress(progressObj, 'progress', [
			{ name: '全景', describe: '建外街道' },
			{ name: '建外街道', describe: '朝外街道' },
			{ name: '朝外街道', describe: '呼家楼街道' },
			{ name: '呼家楼街道', describe: '三里屯街道' },
			{ name: '三里屯街道', describe: '东外街道' },
			{ name: '东外街道', describe: '东外街道' },
			{ name: '左家庄街道', describe: '团结湖街道' },
			{ name: '团结湖街道', describe: '团结湖街道' },
			{ name: '麦子店街道', describe: '全景' },
		]);

		var tween = undefined;
		// 设置每一步播放需要的时间,单位毫秒
		progress.time(3000);
		// 进度条变化
		progress.on('change', function (id) {
			setBuildingHeight(blocks[id], blocks[id], 1);
			if (tween) {
				tween.stop();
				if (id < blocks.length - 1) {
					tween = grow(blocks[id], blocks[id + 1]);
					tween.start();
				}
				else {
					app.camera.earthFlyTo({
						lonlat: [116.4488, 39.9187],
						height: 4000,
						time: 2000
					});
				}
			}
		});
		progress.startCallback(function (state, id) {
			if (tween) {
				tween.stop();
				setBuildingHeight(blocks[id], blocks[id], 1);
			}
			if (state) {
				tween = grow(blocks[id], blocks[id + 1]);
				tween.start();
			}
		});
	}
	creatProgress();
});

posted @ 2020-10-19 15:09  ThingJS_森友鹿锘  阅读(117)  评论(0编辑  收藏  举报