使用cesium简单封装基础功能方便调用简化代码
新建cesium.js
引入cesium
import * as Cesium from 'cesium'
//在class外 定义viewer由于有些方法在this.viewer中使用会失效
var viewer = undefined
class cesium {}
export default cesium
cesium地图初始化首先需要domID 然后需要一些基础配置
class cesium {
domId = null //页面定义div id
viewer = null //viewer对象
handler = null //cesium一些事件对象
setting = { //cesium地图初始化一些基础配置
animation: false, //是否显示动画控件
baseLayerPicker: false, //是否显示图层选择控件
geocoder: false, //是否显示地名查找控件
timeline: false, //是否显示时间线控件
sceneModePicker: false, //是否显示投影方式控件
navigationHelpButton: false, //是否显示帮助信息控件
infoBox: false, //是否显示点击要素之后显示的信息
selectionIndicator: false,
fullscreenButton: false,
homeButton: false,
scene3DOnly: false, //仅仅显示3d,可隐藏右上角2d和3d按钮
selectionoIndicatr: false,
terrainProvider: Cesium.createWorldTerrain({
requestWaterMask: true, // 水面效果
requestVertexNormals: true // 地形
}),
initNoFlyTo: false//地图初始化完成是否飞向默认视角
}
constructor(config, domId) {
Cesium.Ion.defaultAccessToken = '在官网申请的token'
this.domId = domId
this.setting = Object.assign(config || {}, this.setting)
this.init()
}
init(){
viewer && viewer.destroy()
viewer = new Cesium.Viewer(this.domId || 'Map', this.setting)
this.viewer = viewer
this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
document.querySelector('.cesium-widget-credits').style.display = 'none'
viewer.scene.globe.depthTestAgainstTerrain = false
//设置限制缩放大小
// viewer.scene.screenSpaceCameraController.minimumZoomDistance = 0
!this.setting.initNoFlyTo && this.mapViweinit()
this.mouseMove() //地图鼠标移入事件默认触发
this.leftClick() //地图点击事件默认触发
}
mapViweinit() {
this.fly({ lon: '页面默认角度视角', lat: '页面默认角度视角', duration: 0 })
}
fly({ lon, lat, h, pitch, heading, roll, duration }) {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(lon, lat, h || 165735.68887336738),
duration: duration != undefined ? duration : 0.8,
orientation: {
pitch: pitch || -0.6948421594587542,
heading: heading || 6.233297860090907,
roll: roll || 0.0017611927790515125
}
})
}
//加载倾斜摄影可以使用常量接收并且调用此方法定位到模型加载位置
zoomTo(target) {
viewer.zoomTo(target)
}
//地图添加点之后可以通过id默认飞行到点的对应位置 使用viewer.camera.flyTo可能会有经纬度不准的情况
flyTo(key) {
let rider = viewer.entities.getById(key)
let offset = new Cesium.HeadingPitchRange(0.10074559078582723, -0.49977131690671905, 3000)
viewer.flyTo(rider, {
offset,
duration: 0.8
})
}
//调用此方法创建点用于标注在地图上
createPoint(attrs, config) {
const { name = '', lon, lat, id, type = 'display' } = attrs
const { height, show = true, fontSize, fillColor, pixelOffsetX, pixelOffsetY, image, imgWidth, imgHeight, textDistance, imgDistance } = config
return new Cesium.Entity({
attrs: attrs,
id: id,
type: type,
position: Cesium.Cartesian3.fromDegrees(lon * 1, lat * 1, height || 100), // 文字标签
label: {
show: show,
text: name,
font: (fontSize || '12px') + ' monospace',
// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// fillColor: Cesium.Color.LIME,
fillColor: Cesium.Color.fromCssColorString(fillColor || '#fff'),
// outline: true,// 字体边框
// outlineColor: Cesium.Color.WHITE, // 字体边框颜色
// outlineWidth: fillWidth || 4, // 字体边框尺寸
showBackground: true, // 是否显示背景颜色
backgroundColor: Cesium.Color.fromCssColorString('#018081'), // 背景颜色
verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
pixelOffset: new Cesium.Cartesian2(pixelOffsetX || 50, pixelOffsetY || -30), // 偏移量
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, textDistance || 550000) // 文字标签多少距离内设置可见
},
billboard: {
// 图标
image: image || '',
width: imgWidth || 61,
height: imgHeight || 113,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, imgDistance || 550000) // 图片多少距离内设置可见
}
})
}
//用于把创建好的点加载到地图上
addPointer(obj) {
viewer.entities.add(obj)
}
//添加点之前可以调用一下移除所有的点防止重复添加
removePointer() {
let allEntitiesPoint = []
viewer.entities.values.forEach((item) => {
allEntitiesPoint.push(item.id)
})
allEntitiesPoint.forEach((item) => {
const entity_obj = viewer.entities.getById(item)
viewer.entities.remove(entity_obj)
})
}
//添加线
addLine({ postions, polylineWidth, show = true }) {
const obj = {
polyline: {
name: 'polyline',
// fromDegrees返回给定的经度和纬度值数组(以度为单位),该数组由Cartesian3位置组成。
positions: Cesium.Cartesian3.fromDegreesArray(postions),
// 宽度
width: polylineWidth || 5,
// 线的颜色
material: Cesium.Color.TURQUOISE,
// 线的顺序,仅当`clampToGround`为true并且支持地形上的折线时才有效。
// clampToGround: true,
zIndex: 10,
// 是否显示
show: show
}
}
viewer.entities.add(obj)
}
removeLine() {
let allEntitiesPoint = []
viewer.entities.values.forEach((item) => {
if (item.polyline) {
allEntitiesPoint.push(item.id)
}
})
allEntitiesPoint.forEach((item) => {
const entity_obj = viewer.entities.getById(item)
viewer.entities.remove(entity_obj)
})
}
//添加3dtiles
// 添加 tities
addCesiumTileset(url, name) {
let tileset = new Cesium.Cesium3DTileset({
url: url,
name,
skipLevelOfDetail: true,
baseScreenSpaceError: 1024,
// maximumScreenSpaceError: 256, // 数值加大,能让最终成像变模糊
skipScreenSpaceErrorFactor: 16,
skipLevels: 1,
immediatelyLoadDesiredLevelOfDetail: false,
loadSiblings: true, // 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋
cullWithChildrenBounds: true,
cullRequestsWhileMoving: true,
cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
preloadWhenHidden: true,
preferLeaves: true,
maximumMemoryUsage: 128, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验
progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
dynamicScreenSpaceErrorDensity: 0.5, // 数值加大,能让周边加载变快
dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先
dynamicScreenSpaceError: true // 根据测试,有了这个后,会在真正的全屏加载完之后才清晰化房屋
})
tileset.name = name
tileset.readyPromise.then(function (tileset) {
//笛卡尔转换为弧度
var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center)
var lng = Cesium.Math.toDegrees(cartographic.longitude) //使用经纬度和弧度的转换,将WGS84弧度坐标系转换到目标值,弧度转度
var lat = Cesium.Math.toDegrees(cartographic.latitude)
//计算中心点位置的地表坐标
var surface = Cesium.Cartesian3.fromDegrees(lng, lat, 0)
//偏移后的坐标
var offset = Cesium.Cartesian3.fromDegrees(lng, lat, 5)
var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3())
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation)
})
viewer.scene.primitives.add(tileset)
}
//左键点击事件
leftClick(fn) {
this.handler.setInputAction((event) => {
let cartesian = viewer.camera.pickEllipsoid(event.position, viewer.scene.globe.ellipsoid)
if (cartesian == undefined) {
console.log('没有获取到坐标')
} else {
this.currentVisualAngle() //获取当前视角的经纬度高度角度
let pick = viewer.scene.pick(event.position)
if (Cesium.defined(pick)) {
fn && fn(pick)
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}
//鼠标移入事件
mouseMove(fn) {
// 鼠标移动事件
this.handler.setInputAction((event) => {
let pick = viewer.scene.pick(event.endPosition)
fn && fn(event, pick)
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}
//获取当前页面视角的经纬度及偏移值
currentVisualAngle() {
const point = viewer.scene.camera.position
let cartesian33 = new Cesium.Cartesian3(point.x, point.y, point.z)
let cartographic = Cesium.Cartographic.fromCartesian(cartesian33)
let lat = Cesium.Math.toDegrees(cartographic.latitude)
let lon = Cesium.Math.toDegrees(cartographic.longitude)
let alt = cartographic.height
const params = {
lon,
lat,
h: alt,
pitch: viewer.scene.camera.pitch,
heading: viewer.scene.camera.heading,
roll: viewer.scene.camera.roll,
position: point
}
console.log(params)
}
//通过两个点的经纬度获取两个点的直线距离
getDistance(start, end) {
const geodesic = new Cesium.EllipsoidGeodesic()
geodesic.setEndPoints(Cesium.Cartographic.fromDegrees(start.lon, start.lat), Cesium.Cartographic.fromDegrees(end.lon, end.lat))
return geodesic.surfaceDistance
}
//通过世界坐标获取对应屏幕坐标
getWindowByWord(position) {
return Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, position)
}
//通过透明度转换成十六进制颜色色值
getHexOpacity(opacity) {
opacity = opacity / 100
opacity = Math.max(opacity, 0)
opacity = Math.min(opacity, 1)
let num = Math.round(255 * opacity) //向下取整
let str = ''
let arrHex = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'] //十六进制数组
while (num > 0) {
let mod = num % 16
num = (num - mod) / 16
str = arrHex[mod] + str
}
if (str.length == 1) str = '0' + str
if (str.length == 0) str = '00'
return `${str}`
}
}
页面调用默认初始化