本文主要讲解Cesium加载小车模型(glb或gltf),并在三维地球上移动。
访问http://127.0.0.1:8089/index/getRoute?startLon=100&startLat=30&endLon=115&endLat=35获取小车的行驶路径:
CesiumViewer代码:
<template>
<div id="cesiumDiv">
<div id="cesiumContainer">
</div>
</div>
</template>
<script>
import Cesium from 'cesium/Source/Cesium.js'
import buildModuleUrl from "cesium/Source/Core/buildModuleUrl"
import "cesium/Source/Widgets/widgets.css";
import axios from 'axios';
import Bus from '@/Bus/bus.js'
export default {
name: 'CesiumViewer',
components:{},
data () {
return {
viewer:'',
handler:'',
carEntity:'',
routeDataArr:[] //路径分析返回的线经纬度数组
}
},
mounted:function(){
var _this = this;
//设置静态资源目录
buildModuleUrl.setBaseUrl('../../static/Cesium/');
//创建viewer实例
this.viewer = new Cesium.Viewer('cesiumContainer',{
animation: false,
baseLayerPicker: false,
fullscreenButton: false,
geocoder: false,
homeButton: false,
sceneModePicker: false,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
infoBox: false,
navigationInstructionsInitiallyVisible: false,
imageryProvider:new Cesium.WebMapTileServiceImageryProvider({
url:"http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles",
layer:"tiandituImg",
style:"default",
format:"image/jpeg",
tileMatrixSetID:"tiandituImg",
show:true,
maximumLevel:18
})
// imageryPorvider:new Cesium.UrlTemplateImageryProvider({
// url:'http://localhost:9090/gisserver/tiles/BaseMap/{z}/{x}/{y}.jpg'
// })
});
this.viewer._cesiumWidget._creditContainer.style.display = "none"; //去掉logo
//设置初始位置
this.viewer.camera.setView({
destination:Cesium.Cartesian3.fromDegrees(110, 35, 10000000)
});
// var annotationImageryProvider = new Cesium.UrlTemplateImageryProvider({
// url:'http://localhost:9090/gisserver/tiles/Tdt_Annotation/{z}/{x}/{y}.png'
// });
// this.viewer.imageryLayers.addImageryProvider(annotationImageryProvider)
_this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
//路径分析
var positions = [];
axios.get('http://127.0.0.1:8089/index/getRoute?startLon=100&startLat=30&endLon=115&endLat=35').then(function(response){
console.log(response);
var routeDataArr = response.data;
_this.routeDataArr = routeDataArr;
for (var i = 0; i < routeDataArr.length; i+= 2) {
positions.push(Cesium.Cartesian3.fromDegrees(routeDataArr[i], routeDataArr[i+1]));
}
_this.viewer.entities.add({
polyline : {
positions : positions,
width : 10.0,
material : new Cesium.PolylineGlowMaterialProperty({
color : Cesium.Color.DEEPSKYBLUE,
glowPower : 0.25
})
}
});
Bus.$emit('sliderShow',{routeDataArr:routeDataArr});
});
//设置初始位置
_this.viewer.camera.setView({
destination:Cesium.Cartesian3.fromDegrees(110.20, 20, 8000000)
});
//时间滑块
Bus.$on('sliderChange',function(args){
var index = args.index;
if(index+3 < _this.routeDataArr.length){
_this.createModel2('http://localhost:8080/static/3d_modules/CesiumMilkTruck.glb',{lng:_this.routeDataArr[index],lat:_this.routeDataArr[index+1]},{lng:_this.routeDataArr[index+2],lat:_this.routeDataArr[index+3]});
}else if(index+1 < _this.routeDataArr.length){
_this.createModel2('http://localhost:8080/static/3d_modules/CesiumMilkTruck.glb',{lng:_this.routeDataArr[index],lat:_this.routeDataArr[index+1]},{lng:_this.routeDataArr[index],lat:_this.routeDataArr[index+1]});
}else{
_this.createModel2('http://localhost:8080/static/3d_modules/CesiumMilkTruck.glb',{lng:_this.routeDataArr[index-1],lat:_this.routeDataArr[index]},{lng:_this.routeDataArr[index-1],lat:_this.routeDataArr[index]});
}
});
},
methods:{
createModel2: function(url,position,nextPosition) {
var _this = this;
if(_this.carEntity == ''){
var heading = Cesium.Math.toRadians(0);
var pitch = 0;
var roll = 0;
var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(new Cesium.Cartesian3.fromDegrees(position.lng, position.lat), hpr);
_this.carEntity = _this.viewer.entities.add({
name : 'truck',
position : new Cesium.Cartesian3.fromDegrees(position.lng, position.lat),
orientation : orientation,
model : {
uri : url,
minimumPixelSize:50,
maximumScale:20000
}
});
}else{
var heading = _this.calRadians(position.lng,position.lat,nextPosition.lng,nextPosition.lat);
var hpr = new Cesium.HeadingPitchRoll(heading, 0, 0);
var orientation = Cesium.Transforms.headingPitchRollQuaternion(new Cesium.Cartesian3.fromDegrees(position.lng, position.lat), hpr);
_this.carEntity.orientation = orientation;
_this.carEntity.position = new Cesium.Cartesian3.fromDegrees(position.lng, position.lat);
}
_this.viewer.trackedEntity= _this.carEntity;
},
//计算两点与水平方向的夹角(向右为0,顺时针旋转0-360)
calRadians:function(lng1,lat1,lng2,lat2){
if(lng2 == lng1 && lat2 > lat1){
return Math.PI * (3/2);
}else if(lng2 == lng1 && lat2 < lat1){
return Math.PI * (1/2);
}else if(lng2 == lng1 && lat2 == lat1){
return 0;
}
var tanValue = Math.tan((lat2-lat1)/(lng2-lng1));
var radians = Math.atan(Math.abs(tanValue));
if(lng2>lng1 && lat2>lat1){ //第一象限
return Math.PI * 2 - Math.abs(radians);
}else if(lng2<lng1 && lat2>lat1){ //第二象限
return Math.PI + Math.abs(radians);
}else if(lng2<lng1 && lat2<lat1){ //第三象限
return Math.PI - Math.abs(radians);
}else{ //第四象限
return Math.abs(radians);
}
}
}
}
</script>
<style scoped>
#cesiumDiv{
width:100%;
height:88%;
position: absolute;
top:76px;
}
#cesiumContainer{
width:100%;
height:100%;
}
</style>
SliderViewer代码:
<template>
<div class="sliderClass" v-show="isShow">
<el-select v-model="driveValue" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<span class="demonstration"><img src="static/image/play/stop2.png" @click="playClick" id="img"></span>
<el-slider v-model="sliderValue" :max="max" :min="min"></el-slider>
</div>
</template>
<script>
import Bus from '@/Bus/bus.js'
export default {
name:'SliderViewer',
data(){
return {
max:100,
min:0,
step:1,
sliderValue:0,
intervalTotalTime1:200*1000, // 正常速度的总播放时间
intervalTotalTime2:100*1000, // 二倍速度的总播放时间
intervalTotalTime4:50*1000, // 四倍速度的总播放时间
intervalTimeStep:0.1,
isShow:false,
isPlaying:false,
intervalId: null,
options: [{
value: '1',
label: '正常速度'
}, {
value: '2',
label: '2倍速度'
}, {
value: '4',
label: '4倍速度'
}],
driveValue:'1',
routeDataArr:[]
}
},
mounted:function(){
let _this = this;
Bus.$on("sliderShow",function(args){
_this.isShow = true;
_this.sliderValue = _this.min;
_this.routeDataArr = args.routeDataArr;
// _this.intervalTimeStep = (_this.intervalTotalTime)/(_this.routeDataArr.length);
// _this.step = (_this.max)/(_this.routeDataArr.length);
});
Bus.$on("sliderRemove",function(){
clearInterval(_this.intervalId);
_this.isShow = false;
})
},
methods:{
playClick:function(event){
let _this = this;
if(this.isPlaying){ // 播放->暂停
this.isPlaying = false;
event.target.src= _this.GLOBAL.PROJECT_URL +"/static/image/play/stop2.png";
clearInterval(_this.intervalId);
console.log("清除定时器");
}else{ //暂停->播放
this.isPlaying = true;
event.target.src= _this.GLOBAL.PROJECT_URL +"/static/image/play/play2.png";
//重新播放
if(this.sliderValue==this.max){
this.sliderValue = this.min;
// setTimeout(function(){
// },1000);
}
//根据用户选择的播放速度计算总播放时间
switch(_this.driveValue){
case '1':
_this.intervalTimeStep = (_this.intervalTotalTime1)/(_this.routeDataArr.length);
_this.step = (_this.max)/(_this.routeDataArr.length);
break;
case '2':
_this.intervalTimeStep = (_this.intervalTotalTime2)/(_this.routeDataArr.length);
_this.step = (_this.max)/(_this.routeDataArr.length);
break;
case '4':
_this.intervalTimeStep = (_this.intervalTotalTime4)/(_this.routeDataArr.length);
_this.step = (_this.max)/(_this.routeDataArr.length);
break;
default: //正常速度
_this.intervalTimeStep = (_this.intervalTotalTime1)/(_this.routeDataArr.length);
_this.step = (_this.max)/(_this.routeDataArr.length);
}
console.log(_this.routeDataArr.length);
console.log(_this.intervalTimeStep);
console.log(_this.step);
this.intervalId = setInterval(function(){
if(_this.sliderValue >= _this.max){
_this.sliderValue = _this.max;
_this.isPlaying = false;
clearInterval(_this.intervalId);
event.target.src= _this.GLOBAL.PROJECT_URL +"/static/image/play/stop2.png";
}else{
_this.sliderValue += _this.step;
}
},_this.intervalTimeStep);
}
}
},
watch:{
sliderValue:function(newValue,oldValue){
var _this = this;
var index = parseInt((parseFloat(newValue))/(_this.max) * (_this.routeDataArr.length));
if(index%2 != 0){
index -= 1;
}
// if(index == _this.routeDataArr.length){
// index = index-1;
// }
Bus.$emit("sliderChange",{index:index});
}
}
}
</script>
<style scoped>
.sliderClass{
width: 700px;
height: 45px;
position: absolute;
left: 30%;
bottom: 60px;
/*margin-left: -500px;*/
}
span{
position: relative;
top: 50px;
right: 155px;
}
</style>
<style>
.el-select{
width: 105px !important;
position: relative !important;
top: 38px !important;
right: 155px !important;
}
</style>
bus.js代码:
import Vue from 'vue'
export default new Vue()