Newer
Older
smartwell_front_dz / src / components / Mars3D / Mars3dMap.vue
<template>
  <div v-loading="loading" :id="`mars3d-container${mapKey}`" class="mars3d-container" />
</template>
<script>

import Vue from 'vue'
import * as Cesium from 'mars3d-cesium'
import 'mars3d/dist/mars3d.css'
import 'mars3d-cesium/Build/Cesium/Widgets/widgets.css'
import * as mars3d from 'mars3d'
import mapJson from '@/assets/overview/map.json'

// 为了方便使用,绑定到原型链,在其他vue文件,直接 this.mars3d 来使用
Vue.prototype.mars3d = mars3d
Vue.prototype.Cesium = Cesium

import axios from 'axios'
export default {
  name: 'Mars3dMap',
  props: {
    // 地图唯一性标识
    mapKey: {
      type: String,
      default: ''
    },
    // 底图
    basemap: {
      type: Number,
      default: 1113
    },
    // 自定义参数
    options: Object,
    // 是否插入到body元素上
    appendToBody: {
      type: Boolean,
      default: false
    },
    // 是否需要加光
    needBloomEffect: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      mapJson: mapJson,
      center: ['', ''], // 地图中心
      loading: true,
    }
  },
  watch: {
    basemap(val) {
      this.changeBaseLayer(val)
    }
  },
  mounted() {
    if (this.appendToBody) {
      document.body.appendChild(this.$el)
    }
    if (this.mapKey) {
      this.center = [Vue.prototype.mars3dConfig.scene.center.lng, Vue.prototype.mars3dConfig.scene.center.lat]
      this.initMars3d(Vue.prototype.mars3dConfig)
    }
  },

  beforeDestroy() {
    if (window.map) {
      window.map.clear()
      window.map.destroy()
      window.map = null
    }
  },
  methods: {
    initMars3d(options) {
      this.loading = true
      options.layers = []
      this.mapJson.forEach(item => {
        item.children.forEach(child => {
          switch (child.type) {
            case 0:
              // 图标点
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: Vue.prototype.baseConfig.arcgisUrl + child.url,
                symbol: {
                  type: "billboardP",
                  styleOptions: {
                    image: child.style,
                    pixelOffsetY: -15,
                    clampToGround: true,
                    scaleByDistance: true,
                  }
                },
                clustering: {
                  enabled: true,
                  pixelRange: 10,
                  clampToGround: false,
                  addHeight: 20
                },
                popup: child.popup,
                show: true
              })
              break
            case 4:
              // 图标点 + 文字
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: Vue.prototype.baseConfig.arcgisUrl + child.url,
                symbol: {
                  type: "billboardP",
                  styleOptions: {
                    image: child.style,
                    pixelOffsetY: -15,
                    clampToGround: true,
                    scaleByDistance: true,
                    label: {
                      text: child.name,
                      font_size: 15,
                      color: child.color,
                      background: true,
                      backgroundColor: "#fdfdbe",
                      pixelOffsetY: -40,
                      distanceDisplayCondition: true,
                      distanceDisplayCondition_far: 10000,
                      distanceDisplayCondition_near: 0
                    },
                  }
                },
                clustering: {
                  enabled: true,
                  pixelRange: 10,
                  clampToGround: false,
                  addHeight: 20
                },
                popup: child.popup,
                show: true
              })
              break
            case 1:
              // 线
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: Vue.prototype.baseConfig.arcgisUrl + child.url,
                symbol: {
                  type: "polylineC",
                  styleOptions: {
                    // color: child.style,
                    width: 6,
                    materialType: mars3d.MaterialType.PolylineOutline,
                    materialOptions: {
                      color: child.style,
                      outlineWidth: 2,
                      outlineColor: Cesium.Color.WHITE
                    },
                    hasShadows: false
                  }
                },
                popup: child.popup,
                show: true
              })
              break
            case 5:
              // 线 + 连表查
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: child.url,
                symbol: {
                  type: "polylineC",
                  styleOptions: {
                    width: 4, // 线宽
                    // color: child.style,
                    // arcType: Cesium.ArcType.RHUMB,
                    depthFailColor: Cesium.Color.WHITE,
                    depthFailOpacity: 1,
                    materialType: mars3d.MaterialType.PolylineOutline,
                    materialOptions: {
                      color: child.style,
                      outlineWidth: 1,
                      outlineColor: Cesium.Color.WHITE
                    },
                  }
                },
                popup: '',
                show: true
              })
              break
            case 2:
              // 面
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: Vue.prototype.baseConfig.arcgisUrl + child.url,
                symbol: {
                  type: "polygonC",
                  styleOptions: {
                    color: "#006aff",
                    opacity: 0.9,
                    outline: true,
                    outlineWidth: 3,
                    outlineColor: "#00f7ff",
                    clampToGround: false,
                    addHeight: 20
                  }
                },
                popup: child.popup,
                show: true
              })
              break
            case 3:
              // point点
              options.layers.push({
                id: child.id,
                type: "arcgis_wfs",
                url: Vue.prototype.baseConfig.arcgisUrl + child.url,
                symbol: {
                  type: "pointC",
                  styleOptions: {
                    color: "#d6013b",
                    pixelSize: 10,
                    outlineColor: "#e87998",
                    outlineWidth: 2,
                    clampToGround: false,
                    addHeight: 10
                  }
                },
                clustering: {
                  enabled: true,
                  pixelRange: 10,
                  clampToGround: false,
                  addHeight: 10
                },
                popup: child.popup,
                show: true
              })
              break
          }
        })
      })
      const mapOptions = {
        ...options,
        ...this.options
      }
      window.map = new mars3d.Map(`mars3d-container${this.mapKey}`, mapOptions)
      window.map.scene.screenSpaceCameraController.tiltEventTypes = [Cesium.CameraEventType.RIGHT_DRAG]
      window.map.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.MIDDLE_DRAG, Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH]
      window.map.scene.screenSpaceCameraController.rotateEventTypes = [Cesium.CameraEventType.LEFT_DRAG]
      window.map.scene.screenSpaceCameraController.enableCollisionDetection = false
      window.map.viewer.scene.globe.depthTestAgainstTerrain = false;
      window.map.viewer.scene.fxaa = false
      window.map.viewer.scene.postProcessStages.fxaa.enabled = false;

      window.map.viewer.scene.screenSpaceCameraController.minimumZoomDistance = 1000; //距离地形的距离?这个值可以多测试几个值,,我这不太好描述
      window.map.viewer.clock.onTick.addEventListener(function () {
        if (window.map.viewer.camera.pitch * (180 / Math.PI) > -20) {
          window.map.viewer.scene.screenSpaceCameraController.enableTilt = false;
        }
      })

      // var startMousePosition;
      // var mousePosition;
      // var handler = new Cesium.ScreenSpaceEventHandler(window.map.viewer.canvas);
      // handler.setInputAction(function(movement) {
      //   mousePosition = startMousePosition = Cesium.Cartesian3.clone(movement.position);
      //   handler.setInputAction(function(movement) {
      //     mousePosition = movement.endPosition;
      //     var y = mousePosition.y - startMousePosition.y;
      //     if( window.map.viewer.camera.pitch * (180 / Math.PI) > -20){
      //       window.map.viewer.scene.screenSpaceCameraController.enableTilt = false;
      //     }
      //     if(y>0){
      //       window.map.viewer.scene.screenSpaceCameraController.enableTilt = true;
      //     }
      //   }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
      // }, Cesium.ScreenSpaceEventType.RIGHT_DOWN);


      this.$emit('onload', window.map, this.center)

      setTimeout(() => {
        this.loading = false
        console.log('初始化完成,可以操作')
      }, 1000)

      // map.basemap = this.basemap
      // const that= this
      // map.on(mars3d.EventType.load, function(event) {
      //   that.$emit('onload', map, that.center)
      // })

      // map.on(mars3d.EventType.renderError, function(event) {
      //   window.location.reload()
      // })
      // const handler = new Cesium.ScreenSpaceEventHandler(map.viewer.canvas)
      // handler.setInputAction(function(evt) {
      //   var cartesian = map.viewer.camera.pickEllipsoid(evt.position, map.viewer.scene.globe.ellipsoid)
      //   var cartographic = Cesium.Cartographic.fromCartesian(cartesian)
      //   var lng = Cesium.Math.toDegrees(cartographic.longitude)// 经度值
      //   var lat = Cesium.Math.toDegrees(cartographic.latitude)// 纬度值
      //   console.log(' {point: [' + lng + ',' + lat + ',0]},')
      // }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

      // this[`map${this.mapKey}`] = map
      // if (this.needBloomEffect) {
      //   const bloomEffect = new mars3d.effect.BloomEffect({
      //     enabled: true
      //   })
      //   map.addEffect(bloomEffect)
      // }
      // const graphicLayer = new mars3d.layer.GraphicLayer()
      // map.addLayer(graphicLayer)

      // // 挂载到全局对象下,所有组件通过 this.map 访问
      // Vue.prototype[`map${this.mapKey}`] = map

    },
    changeBaseLayer(basemap) {
      console.log(basemap, 'basemap')
      window.map.basemap = basemap
    }
  }
}
</script>

<style scoped>
.mars3d-container {
  height: 100vh;
  overflow: hidden;
}
</style>