8

Cesium开发实践

 3 years ago
source link: https://segmentfault.com/a/1190000040530729
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

做了大概三个月的基于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元素
-  <img src="/biz/alarm.gif" width="20px" height="20px" ref="gifRef" rel:auto_play="1" rel:rubbable="1"
            style="position: absolute;z-index: -1;" />
  _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节点

<poiDetail ref="poiRef"></poiDetail>
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()
                                }
                            })

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK