Cesium开发实践

【Cesium开发实践】做了大概三个月的基于cesium地图开发的应用场景和大屏;主要想从cesium基本的入门到一些简单的场景交互做一个代码分享。
Cesium是三维地图开发的一个前端gis引擎;支持wtms、影像、模型、地形、倾斜摄影的数据加载。并通过对点线面、材质、视角等图形学知识对它进行一个正式三维场景的一个复现。
包括一些最

  • 基本的创建地图、创建点位、数据源组、创建图层、加载gif,相机视角;
  • 加载图层、绘制点、线、面,调节情景参数;
  • 对接天地图、高德地图、百度地图;
  • 事件:点击事件、移除事件、移除事件、拖拽事件
  • 弹框:视频弹框、详情弹框、报警弹框
  • 轨迹:动态轨迹、轨迹漫游
  • 流线图:喷泉、流线图
  • 场景:模拟下雪、下雨、雷达图
  • 基本工具箱:放大、缩小,定位、画线
  • kml、geojson文件转换和加载
  • 性能优化
  • 常用工具方法
    1、基本的创建地图
viewer = new Cesium.Viewer('maps', { animation: false, //是否创建动画小器件,左下角仪表 baseLayerPicker: false, //是否显示图层选择器 fullscreenButton: false, //是否显示全屏按钮 geocoder: false, //是否显示geocoder小器件,右上角查询按钮 homeButton: false, //是否显示Home按钮 infoBox: false, //是否显示信息框 sceneModePicker: false, //是否显示3D/2D选择器 selectionIndicator: false, //是否显示选取指示器组件 timeline: false, //是否显示时间轴 sceneMode: Cesium.SceneMode.SCENE3D, //设定3维地图的默认场景模式:Cesium.SceneMode.SCENE2D、Cesium.SceneMode.SCENE3D、Cesium.SceneMode.MORPHING navigationHelpButton: false, //是否显示右上角的帮助按钮 scene3DOnly: true, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源 navigationInstructionsInitiallyVisible: false, showRenderLoopErrors: false, //是否显示渲染错误 shouldAnimate: true,//允许动画 //这个得必须有! })

  • 创建的点位:
- layer && layer.entities.add({ id: item.id, name: item.name, type: "marker", featureType: type, feature: item.feature, lon: item.lon, lat: item.lat, mapTools: tools,//地图右边按钮 position: Cesium.Cartesian3.fromDegrees(parseFloat(lon), parseFloat(lat), height), billboard: { image: new Cesium.CallbackProperty(() => { return _self.superGif.get_canvas().toDataURL("image/png"); }, false), scale: 1, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, width: 60, height: imageheight }, label: { text: type == "wrj" ? `${item.name}` : "", font: '14pt 微软雅黑', style: Cesium.LabelStyle.FILL_AND_OUTLINE, // backgroundColor: Cesium.Color.YELLOW, // showBackground: true, outlineColor: new Cesium.Color.fromCssColorString("tranparent"), fillColor: new Cesium.Color.fromCssColorString("#fff"), outlineWidth: 5, verticalOrigin: Cesium.VerticalOrigin.CENTER, pixelOffset: new Cesium.Cartesian2(-110, -25) },})

  • 创建数据图层
-markersLayer = new Cesium.CustomDataSource('marker-layer') - viewer.dataSources.add(markersLayer)

  • 创建地图底图图层
viewer.imageryLayers.addImageryProvider(new Cesium.SingleTileImageryProvider({ url: '/static/map/worldimage.jpg' }));

  • 加载gif动态图片,需要引入SuperGif插件进行gif转换,再通过Cesium.CallbackProperty一帧帧获取,需要注意得加上dom元素
-Cesium开发实践
文章图片

_self.superGif = new SuperGif({ gif: this.$refs.gifRef }); _self.superGif.load(function () { layer && layer.entities.add({ id: item.id, name: item.name, type: "marker", featureType: type, feature: item.feature, lon: item.lon, lat: item.lat, mapTools: tools,//地图右边按钮 position: Cesium.Cartesian3.fromDegrees(parseFloat(lon), parseFloat(lat), height), billboard: { image: new Cesium.CallbackProperty(() => { return _self.superGif.get_canvas().toDataURL("image/png"); }, false), scale: 1, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, width: 60, height: imageheight }, label: { text: type == "wrj" ? `${item.name}` : "", font: '14pt 微软雅黑', style: Cesium.LabelStyle.FILL_AND_OUTLINE, // backgroundColor: Cesium.Color.YELLOW, // showBackground: true, outlineColor: new Cesium.Color.fromCssColorString("tranparent"), fillColor: new Cesium.Color.fromCssColorString("#fff"), outlineWidth: 5, verticalOrigin: Cesium.VerticalOrigin.CENTER, pixelOffset: new Cesium.Cartesian2(-110, -25) }, _lng: lon, _lat: lat, _obj: item }) }); }

  • 相机视角(有entity则用viewer,坐标用camera)
let heading = viewer.camera.heading, pitch = viewer.camera.pitch, roll = viewer.camera.roll; viewer.flyTo(_self.pickValue, { offset: { heading: 2.990358455542995, // 方向 pitch: -0.5403975721607086,// 倾斜角度 range: 11100 } //定位 let lon = list[0].lon || list[0].longitude, lat = list[0].lat || list[0].latitude; viewer.camera.flyTo(this.mapCenter, 5000);

2、加载图层、绘制点、线、面,调节情景参数
加载图层
天地图超图方式对接
let IMG_C = viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({ mapStyle: Cesium.TiandituMapsStyle.IMG_C, token: 'e8865a2cd69468263ca650b1c73ee698' })) IMG_C.show = true; //let IMG_C = viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({ //mapStyle: Cesium.TiandituMapsStyle.TER_C, //token: 'e8865a2cd69468263ca650b1c73ee698' // })) // IMG_C.show = true; viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({ mapStyle: Cesium.TiandituMapsStyle.CIA_C,//天地图全球中文注记服务(经纬度) token: 'xxx' //由天地图官网申请的密钥 }))

  • 原生对接
// 叠加影像服务 var imgMap = new Cesium.UrlTemplateImageryProvider({ url: tdtUrl + 'DataServer?T=img_w&x={x}&y={y}&l={z}&tk=' + token, subdomains: subdomains, tilingScheme: new Cesium.WebMercatorTilingScheme(), maximumLevel: 22 }); viewer.imageryLayers.addImageryProvider(imgMap);

  • 绘制面
ttMaplayer.entities.add({ position: Cesium.Cartesian3.fromDegrees(lon, lat, height), ellipse: { heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, disableDepthTestDistance: 99000000, outlineColor: Cesium.Color.YELLOW.withAlpha(0.5), outline: true, outlineWidth: 2, semiMinorAxis: 5000.0, semiMajorAxis: 5000.0, fill: false, } });

  • 绘制矩形
let east = points[0].split(','),west = points[1].split(','); layer.entities.add({ type:"marker", name: item.name, _obj:item, position: Cesium.Cartesian3.fromDegrees(parseFloat((+east[0]+(+west[0]))/2), parseFloat((+west[1]+(+east[1]))/2)), rectangle: { coordinates: Cesium.Rectangle.fromDegrees(+east[0], +east[1],+west[0], +west[1]), outlineColor:Cesium.Color.RED, outlineWidth:24, fill:true, material: Cesium.Color.BLUE.withAlpha(0.6), outline:true } })

  • 绘制线段(可以设置线段宽度和材质)
_t.appendLayer.entities.add({ polyline: { positions: new Cesium.CallbackProperty(function() { return _t.routeList }, false), width: 5, material: Cesium.Color.RED, depthFailMaterial: Cesium.Color.RED, clampToGround: true } })

  • 参数调节
let Options = function () { this.contrast = 128; this.brightness = -0.3; this.delta = 1; this.gamma = 3.5; this.enabled = false; this.highDynamicRange = true; this.shadows = false; } let option = new Options(); let gui = new dat.GUI(); gui.__closeButton.innerHTML = "收缩面板"; let bloom = viewer.scene.postProcessStages.bloom; gui.add(option, 'highDynamicRange').name("高动态范围").onChange(function (value) { viewer.scene.highDynamicRange = value; }) gui.add(option, 'gamma', 0, 5).name("伽马亮度").onChange(function (value) { viewer.scene.gamma = value; })gui.add(option, 'enabled').name("启用模糊").onChange(function (value) { bloom.enabled = value; }) gui.add(option, 'contrast', -128, 128).name("对比度").onChange(function (value) { bloom.uniforms.contrast = value; }) gui.add(option, 'brightness', -2, 2).name("光泽亮度").onChange(function (value) { bloom.uniforms.brightness = value; }) gui.add(option, 'delta', -5, 5).name("因子(delta)").onChange(function (value) { bloom.uniforms.delta = value; })gui.add(option, 'shadows').name("启用阴影").onChange(function (value) { viewer.shadows = value; }) $('.dg.ac').css('top', '10%');

事件
  • 鼠标左键点击事件
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas), _self = this; let ellipsoid = viewer.scene.globe.ellipsoid; //点击地图视频标志窗口弹窗 handler.setInputAction(async e => { let lng, lat, height var cartesian = viewer.scene.pickPosition(e.position); //地图点位查询 let pick = viewer.scene.pick(e.position); if (Cesium.defined(pick) && pick.id && pick.id.type === "marker") { }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

  • 鼠标移入事件
-//鼠标移入事件 handler.setInputAction(async movement => { let lng, lat, height; if (viewer.scene.mode !== Cesium.SceneMode.MORPHING) { let pick = viewer.scene.pick(movement.endPosition); if (Cesium.defined(pick) && pick.id) } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

鼠标移除事件
rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE); rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN); rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);

弹框(生成弹框和弹框移动)
生成:
dom节点
positionPopUp(c) { this.tempPostion = c; var x = c.x - 290; var y = c.y - 250 this.boxStyle = `left:${x}px; top:${y}px` }, destroy() { this.options = {}; this.hide(); }, hide() { this.getActionFlg = false; this.visible = false; this.showPlayer = false; this.tempPostion = null; }

  • js方式控制dom节点
_self.$refs.poiRef.open({ position: changedC, item: _self.pickValue, removeHandler: () => { _self.removeHandler() } })

  • 移动:postRender监听位置移动改变坐标
    viewer.scene.postRender.addEventListener(function () {
    })
    相关链接:bigMap kml和geojson转换
    在线图层处理
    常用的地图json下载和svg下载
    Ceisum文档比官网快
    github代码:https://github.com/holidaying/Cesium/tree/master

    推荐阅读