cesium的下载和安装,这里就不做赘述了,大家可自行查找,实在找不到的话可以给我留言.
这里封装的cusium组件,主要功能包括:地图加载、扎点 、画线、叠加图层、监听鼠标聚焦和点击事件并给出相应的回调。
<template>
<div class="cesiumMap">
<div :id="mapConfig.mapBoxId" class="fullSize"></div>
<!-- 弹窗dom -->
<div
v-show="mapConfig.popupBoxShow"
:id="mapConfig.popupBoxId"
class="ol-popup"
>
<slot :markerInfo="markerInfo"></slot>
<!-- <slot name="mouseMove" :markerInfo="markerInfo"></slot>
<slot name="mouseClick" :markerInfo="markerInfo"></slot> -->
</div>
</div>
</template>
<script>
import { addWmtsLayer } from "./addWmts";
import overLayer from "./overLayer";
let TileMapServiceImageryProvider = null;
const DEFAULT_CONFIG = {
//定义地图服务地址
DEFAULT_PMTS_URL:"http://xxxxxxxxxxx",
DEFAULT_WETS_URL:"http://xxxxxxxxxxxxxxxxx",
DEFAULT_WMTS_URL:"http:XXXxxxxxxxxxxx",
};
let mapViewer = null; //定义地图容器
let markerLayer = null;
let tileset = null;
let onMouseClick = null; //鼠标点击监听事件
let currOverlay = null; //弹窗图层
export default {
name: "MapCesium",
props: {
// 地图个性化配置,在父组件内调用该组件时根据需要传值
mapConfig: {
type: Object,
default: () => {
return {
mapBoxId: "mapId",
popupBoxId: "",
popupOffset: {
//弹窗距点位的偏移量
x: 0,
y: 0,
},
needPointClickCallback: false, //是否需要点击扎点的回调
showLabelText: false, //是否显示图标旁的文字
textName: "", //要显示的文字的取值字段名
textOffset: 0, ///要显示的文字偏移量
needMouseClickHandler: false, //是否需要监听鼠标点击事件
needMouseMoveHandler: false, //是否需要监听鼠标移动事件
popupBoxShow: false, //默认不显示弹框
initCenter: {}, //初始化地图中心
needFocusChange:true
};
},
},
//打点数据
pointList: {
type: Array,
default: function () {
return [];
},
},
},
data() {
return {
tileset: null,
TileMapServiceImageryProvider: null,
pointInfo: {},
markerInfo: {},
initLoad: true,
};
},
mounted() {
this.$nextTick(() => {
this.initMap();//初始化加载地图
});
},
methods: {
initMap() {
let serviceUrl = DEFAULT_CONFIG.DEFAULT_PMTS_URL;
let wmtsUrl = DEFAULT_CONFIG.DEFAULT_WMTS_URL;
mapViewer = new Cesium.Viewer(this.mapConfig.mapBoxId, {
imageryProvider: new Cesium.TileMapServiceImageryProvider({
url: Cesium.buildModuleUrl("Assets/Textures/NaturalEarthII"),
}),
geocoder: false, //是否显示地名查找控件
homeButton: false,
sceneModePicker: false, //是否显示投影方式控件
baseLayerPicker: false, //是否显示图层选择控件
navigationHelpButton: false, //是否显示帮助信息控件
animation: false, //是否显示动画控件(左下方那个)
timeline: false, //是否显示时间线控件
fullscreenButton: false,
vrButton: false,
infoBox: false, //去除原生自带右上角弹窗
selectionIndicator: false, //点击球体显示绿色标识框
});
// mapViewer.scene.screenSpaceCameraController.minimumZoomDistance = 20;
// mapViewer.scene.screenSpaceCameraController.maximumZoomDistance = 2000;
// mapViewer.clock.shouldAnimate = true;
// mapViewer.clock.multiplier = 20000;
// mapViewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
//拉取3维地图资源
tileset = new Cesium.Cesium3DTileset({
url: serviceUrl,
});
tileset.readyPromise
.then(function (tileset) {
mapViewer.scene.primitives.add(tileset);
mapViewer.zoomTo(
tileset,
new Cesium.HeadingPitchRange(
0.0,
-0.5,
tileset.boundingSphere.radius * 2.0
)
);
})
.otherwise(function (error) {
console.log(error);
});
// WMTS二维底图
addWmtsLayer(mapViewer, {
url: wmtsUrl,
autoFly: true,
});
// 鼠标监听事件
if (this.mapConfig.needMouseClickHandler || false) {
this.addMouseClickHandler();
}
if (this.mapConfig.needMouseMoveHandler || false) {
this.addMouseMoveHandler();
}
},
//监听鼠标点击事件
addMouseClickHandler() {
onMouseClick = new Cesium.ScreenSpaceEventHandler(mapViewer.canvas);
onMouseClick.setInputAction((event) => {
let marker = mapViewer.scene.pick(event.position);
if (!marker || marker.id._id == -1) {
console.log("点击的内容不是一个点位");
return;
}
if (currOverlay) {
currOverlay.close();
}
this.markerInfo = this.pointList.find((i) => marker.id._id == i.id);
if (!this.markerInfo) {
console.log("获取不到点位的信息");
return;
}
//父组件是否需要点击地图的回调事件
if (this.mapConfig.needPointClickCallback) {
this.$emit("clickPointCallback", this.markerInfo);
}
//是否需要点击扎点位置后,在扎点位置弹窗显示内容
if(this.mapConfig.popupBoxId){
// 只有设置了popupBoxId才会新增图层
let element = document.getElementById(this.mapConfig.popupBoxId);
let position = Cesium.Cartesian3.fromDegrees(
this.markerInfo.longitude * 1,
this.markerInfo.latitude * 1,
this.markerInfo.floorHeight || 30
);
let id = marker.id;
this.addOverlay(element, position, id);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
//这里的事件类型有:
// LEFT_DOWN,LEFT_UP,LEFT_CLICK,LEFT_DOUBLE_CLICK
// RIGHT_DOWN,RIGHT_UP,RIGHT_CLICK
// MIDDLE_DOWN,MIDDLE_UP,MIDDLE_CLICK,MOUSE_MOVE,WHEEL
},
//监听鼠标移动事件
addMouseMoveHandler() {
onMouseClick = new Cesium.ScreenSpaceEventHandler(mapViewer.canvas);
onMouseClick.setInputAction((event) => {
let marker = mapViewer.scene.pick(event.endPosition);
if (marker) {
this.markerInfo = this.pointList.find((i) => marker.id._id == i.id);
if (!this.markerInfo) {
console.log("获取不到点位的信息");
return;
}
//点击点位的回调
let element = document.getElementById(this.mapConfig.popupBoxId);
let position = Cesium.Cartesian3.fromDegrees(
this.markerInfo.longitude * 1,
this.markerInfo.latitude * 1,
this.markerInfo.floorHeight || 30
);
let id = this.markerInfo.id;
this.addOverlay(element, position, id);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
},
// 添加点数据
addMarkers(markers) {
mapViewer.entities.removeAll();
markers.map((item, index) => {
//地图扎点时每个点的信息如下:
let iconWidth = item.iconWidth || 40;
let iconHeight = item.iconHeight || 40;
let longitude = item.longitude;
let latitude = item.latitude;
let floorHeight = item.floorHeight || 50; //高度默认0
let icon = item.icon || null;
if (longitude && latitude) {
mapViewer.entities.add({
name: "build",
id: item.id,
position: Cesium.Cartesian3.fromDegrees(
longitude,
latitude,
floorHeight // TODO: 高程未知,暂设置为地面高程
),
// 打点图标
billboard: {
image: icon,
width: iconWidth,
height: iconHeight,
},
//文字标签
label:
this.mapConfig.showLabelText || false
? this.getText(`${item[this.mapConfig.textName]}`)
: null,
// pixelOffset: new Cesium.Cartesian2(16, -39),
// 默认值为0,0,默认所加载的图片的中心位置与撒点坐标叠在一起, 此参数用于调整图片的哪个点和撒点位置重合
// 第一个参数为往屏幕右边平移的像素值,第二个参数为往屏幕下方平移的参数值
});
}
});
//切换中心点
let longitude = "";
let latitude = "";
let floorHeight = "";
if (
this.mapConfig.initCenter &&
this.mapConfig.initCenter.latitude &&
this.initLoad
) {
//指定初始化中心点坐标
longitude = this.mapConfig.initCenter.longitude ;
latitude = this.mapConfig.initCenter.latitude ;
this.initLoad = false;
mapViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, 800),
});
//800为视野高度,数字越大视野范围越广
} else if (this.mapConfig.needFocusChange && markers[0].longitude && markers[0].latitude) {
//不指定中心点,取第一个坐标点作为中心点
longitude = markers[0].longitude ;
latitude = markers[0].latitude ;
mapViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, 7500),
});
}
},
//添加弹窗图层
addOverlay(element, position, id) {
//销毁当前弹出的浮云框
if (currOverlay) {
currOverlay.close();
}
let option = {
id: id,
element: element,
position: position,
offset: {
//默认整个div的【左下角】,跟地图上指定的点重合
x: this.mapConfig.popupOffset ? this.mapConfig.popupOffset.x : 0, //向屏幕左边平移的像素值
y: this.mapConfig.popupOffset ? this.mapConfig.popupOffset.y : 0, //向屏幕下方平移的像素值
},
};
currOverlay = new overLayer(option);
mapViewer.addOverlay(currOverlay);
currOverlay.setPosition(position);
},
//获取可配置的文字内容
getText(text) {
return {
show: this.mapConfig.showLabelText,
text: text,
font: "500 30px Helvetica", // 15pt monospace
scale: 0.5,
style: Cesium.LabelStyle.FILL,
fillColor: Cesium.Color.WHITE,
pixelOffset: new Cesium.Cartesian2(this.mapConfig.textOffset * 2, 0), //偏移量
showBackground: true,
};
},
//画线
AddPolyline(polylineInfo) {
if(polylineInfo.positions.length === 0){
this.$message.warning('无轨迹路线');
return;
}
let positions=Cesium.Cartesian3.fromDegreesArray(polylineInfo.positions);
mapViewer.entities.removeById("polylineId");
mapViewer.entities.add({
id: "polylineId",
name:polylineInfo.name || '线',
show:true,
polyline:{
show:true,
positions: positions,
width:polylineInfo.width || 3,
material: new Cesium.PolylineDashMaterialProperty({
color: Cesium.Color.RED
}),
clampToGround: true
}
});
},
//添加图片
addHeatMap(markers){
var latMax = 36.12552698032415;
var latMin = 36.0654854;
var lonMax = 120.48212;
var lonMin = 120.4137071;
mapViewer.entities.removeById("heatmapId");
mapViewer.entities.add({
name: 'heatmap',
id:"heatmapId",
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(lonMin, latMin, lonMax, latMax),
material: new Cesium.ImageMaterialProperty({
image: require("@/assets/images/streetCloudImg/home/heatMap.png"),
width:112,
height:56,
transparent: false
})
}
})
},
//弹窗关闭事件
closePopup() {
if (currOverlay) {
currOverlay.close();
}
},
},
};
</script>
<style scoped lang="scss">
.cesiumMap {
height: 100%;
width: 100%;
.fullSize {
height: 100%;
width: 100%;
}
}
.ol-popup {
// width: 289px;
min-width: 289px;
height: 180px;
position: absolute;
top: 0; //默认顶部不占高度
}
</style>
父组件调用:
其中mapConfig内的配置项可参考封装组件内的备注自行添加.pointList是扎点坐标list
<map-cesium
ref="cesiumMap"
:mapConfig="mapConfig"
:pointList="pointList"
@clickPointCallback="clickPointCallback"
v-slot="slotProps"
>
<div class="popupBox">
<div class="popupInfo">
<span class="title">设备名称</span
><span class="info">{{ slotProps.markerInfo.deviceName }}</span>
</div>
<div class="popupInfo">
<span class="title">设备类型</span
><span class="info">{{ slotProps.markerInfo.deviceType }}</span>
</div>
</div>
</map-cesium>
以上,时间较紧张写的比较粗糙,大家有什么问题可以给我留言,或者我的代码里有哪个不太好的地方,也欢迎大家补充,一起交流学习.