Cesium+Vue实战

1,334 阅读3分钟

cesium-创建地图实例

1.在cesium官网注册获取token.

Cesium.Ion.defaultAccessToken = token

2.地图相关配置项

const mapOptions = {
    homeButton: false, //是否显示主页按钮
    sceneModePicker: false, //是否显示场景按钮
    baseLayerPicker: false, //是否显示图层选择控件
    navigationHelpButton: false, //导航帮助按钮
    selectionIndicator: false, //鼠标选择指示器
    infoBox: false, //信息提示框
    animation: false, //是否创建动画小器件,左下角仪表
    timeline: false, //是否显示时间线控件
    geocoder: false, //是否显示地名查找控件
    fullscreenButton: true, //是否全屏按钮
    shouldAnimate: false, 
    destination: {
      x: 114.861202305258697,
      y: 35.1132378100476,
      z: 900,
    },
    orientation: [0, -25, 0],
    tileDataOption: {
        name: "倾斜摄影",
        type: "OsgbModelLayer",
        url: "http://xxxxxx/3dtileset.json",
        height: 0
    },
}

2.基于div的id创建viewer,viewer尽量不要挂载在vue的data上面,viewer添加地图内容过多,vue对其监听可能会造成页面崩溃,更多地图的配置项可去官网查询.

this.viewer = new Cesium.Viewer("map-view", mapOptions)

// 去除版权
this.viewer._cesiumWidget._creditContainer.style.display = "none"
// 地图中心点,destination:经纬度和高度,orientation:倾斜角度
this.viewer.scene.camera.setView({
  destination: Cesium.Cartesian3.fromDegrees(
      mapOptions.destination.x,
      mapOptions.destination.y,
      mapOptions.destination.z,
  ),
  orientation: {
      heading: Cesium.Math.toRadians(mapOptions.orientation[0]),
      pitch: Cesium.Math.toRadians(mapOptions.orientation[1]),
      roll: Cesium.Math.toRadians(mapOptions.orientation[2])
  }
})
this.viewer.terrainProvider = Cesium.createWorldTerrain({
  requestWaterMask: false, // 否需要请求额外的水
  requestVertexNormals: false // 光数据
})
this.viewer.scene.globe.depthTestAgainstTerrain = true
this.viewer.scene.screenSpaceCameraController.minimumZoomDistance = 10 // 距离地形的距离

cesium-实现倾斜摄影

creatTileset: function(name) {
    const tileOption = mapOptions.tileDataOption
    const option = { ...tileOption, url: dataUrl }
    const _height = Cesium.defaultValue(option.height, 0.0)

    this.viewer.scene.morphStart.addEventListener(function() {
        if (this.viewer.scene.mode !== 1) {
            this.viewer.scene.primitives.remove(this.tileset[name])
        } else {
            if (
                !this.viewer.scene.primitives.contains(this.tileset[name])
            ) {
                this.tileset[name] = this.createTileset(option)
                this.viewer.scene.primitives.add(this.tileset[name])
            }
        }
    })
    this.tileset[name] = this.createTileset(option)
    this.viewer.scene.primitives.add(this.tileset[name])
    
},
createTileset: function(option) {
    let tileset
    if (option.url) {
        tileset = new Cesium.Cesium3DTileset({
            url: option.url,
            skipLevelOfDetail: true, // 开启跳级加载
            maximumMemoryUsage: 4000, // 最大内存占用
            dynamicScreenSpaceError: true
        })
        tileset.colorBlendMode = Cesium.Cesium3DTileColorBlendMode.REPLACE
    }
    return tileset
},

cesium-点位展示

cesium点位展示需要创建一个广告牌集合,添加到primitives中.需要注意的是billboard中的image属性,image可以为本地图片或线上图片,也可以为canvas画布

this.billboards = this.viewer.scene.primitives.add(
    new Cesium.BillboardCollection()
)
const billboard = this.viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(
        longitude,
        latitude,
        altitude
    ),
    id: 'xxx',
    billboard: {
        show: true,
        image: newImage,
        scaleByDistance:new Cesium.NearFarScalar(1000, 1, 100000,0.1),//设置随图缩放距离和比例
        distanceDisplayCondition:new Cesium.DistanceDisplayCondition(50, 100000),//设置可见距离
        disableDepthTestDistance: Number.POSITIVE_INFINITY,//贴地
    },
})
this.billboards.add(billboard)

cesium-点位自定义tooltip

当鼠标悬浮在点位上时,弹出自定义tooltip,监听鼠标悬浮事件,获取鼠标最后停留的坐标点位,确定鼠标悬浮在点位上时,得到该点位的屏幕坐标,显示tooltip,

this.viewer.screenSpaceEventHandler.setInputAction((movement) => {
    //将鼠标手样式设置为普通
    this.viewer._container.style.cursor = "default"
    //通过pick方法获取具有' primitive'属性的对象
    const pickedFeature = this.viewer.scene.pick(movement.endPosition)
    if (lastEntity && lastEntity.id !== undefined) {
        //鼠标悬浮事件移除,隐藏弹出框
        this.pointMouseremove()
    }
    if (Cesium.defined(pickedFeature)) {
        //鼠标悬浮的坐标处于点位上时
        if (pickedFeature.id !== undefined) {
            //设置鼠标手样式
            this.viewer._container.style.cursor = "pointer"
            const entityId = pickedFeature.id._id || pickedFeature.id
            currentEntity = this.viewer.entities.getById(entityId)
            lastEntity = currentEntity
            //鼠标悬浮事件触发,显示弹出框
            this.pointMouseover()
        }
    }

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

cesium-点位自定义弹框

监听鼠标左键点击事件,得到点击坐标,通过camera.getPickRay得到笛卡尔3射线的位置和方向,找的位于该位置的实体即点位,获得该点位的屏幕坐标,显示自定义弹框,同时地图移动时需要监听该点位的位置变化,时刻改变该弹框的位置,保持点位和弹框在移动下联动。

this.viewer.screenSpaceEventHandler.setInputAction((event) => {
    const scene = this.viewer.scene
    const pick = scene.pick(event.position)
    this.clickEntity = scene.globe.pick(this.viewer.camera.getPickRay(event.position), scene)

    if (Cesium.defined(pick) && typeof pick.id !== "undefined") {
        const entityId = pick.id.id || pick.id._id
        this.eventCallbacks.pointClick(entityId, event.position)
        // this.getWindowPosition为获取屏幕坐标的方法,可根据点位的经纬度、高度,scene的cartesianToCanvasCoordinates方法获得
        const windowPotion = this.getWindowPosition(entityId, event.endPosition)
        if (!windowPotion) {
            //清除弹框
            this.destroyPopup()
        }
        // 监听事件,保持点位和弹框的位置联动
        this.eventListener = this.viewer.scene.postRender.addEventListener(() => {
            if (this.clickEntity && this.clickEntity.x) {
                this.updatedPopup(), entityId)
            }
        })
    } else {
        this.destroyPopup()
    }
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)

cesium-加载geojson数据

加载geojson并设置该实体上面展示的label

const jsonData = Cesium.GeoJsonDataSource.load('xxxxxx.json', {
    clampToGround: true,
})
jsonData.then((result) => {
    this.viewer.dataSources.add(result)
    const entities = result.entities.values
    for (let i = 0; i < entities.length; i++) {
        const entity = entities[i]
        entity.polygon.material = Cesium.Color.PALEGREEN.withAlpha(0.5)
        entity.polygon.outline = true
        entity.polygon.zIndex = 999
        // 通过geojson面的数据获得该面的中心点
        let polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions
        let polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center
        polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter)
        entity.position = polyCenter

        entity.label = {
            text: `Hello World`,
            color: Cesium.Color.fromCssColorString('#fff'),
            font: '16 px PingFang SC',
            backgroundColor: color,
            showBackground: true,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
            heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            disableDepthTestDistance: Number.POSITIVE_INFINITY
        }
    }
})