Newer
Older
smartwell_front / src / components / CMap / components / cmapSmart.vue
<template>
  <div>
    <div id="map" ref="map" class="mapDiv"/>
    <slot/>
  </div>
</template>

<script>
import bindEvents from './../base/bindEvents'
import { createIcon } from '../base/factory.js'

export default {
  name: 'Cmap',
  props: {
    center: { // 地图中心
      type: Object,
      default: function() {
        return { lat: 39.9, lng: 116.4 }
      }
    },
    wellObj: { // 井对象
      type: Object,
      default: function() {
        return { wellCode: '', id: '', coordinateY: 39.9, coordinateX: 116.4, radius: '0' }
      }
    },
    zoom: { // 缩放层级
      type: Number,
      default: 12
    },
    minZoom: { // 最小缩放层级
      type: Number,
      default: 9
    },
    maxZoom: { // 最大缩放层级
      type: Number,
      default: 21
    },
    autoResize: { // 自动重绘
      type: Boolean,
      default: true
    },
    size: { // marker大小
      type: Array,
      default: function() {
        return [30, 30]
      }
    },
    anchor: { // 位移
      type: Array,
      default: function() {
        return [15, 30]
      }
    }, // 图标位移
    popupTemplate: { // 弹窗html内容
      type: String,
      default: '<div>hello</div>'
    },
    popupAnchor: { // 弹窗位移
      type: Array,
      default: function() {
        return [0, -15]
      }
    },
    valves: { // 阀门原始数据
      type: Array,
      default: () => []
    },
    closeAreas: { // 关阀影响区域原始数据
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      affectCicle: null, // 影响区域
      mapLayers: null, // 地图图层
      wellOverlay: null, // 井overlay
      affectAreaOverlay: [], // 影响区域overlay
      valvesOverlays: [], // 阀门overlay列表
      closeAreaOverlays: [] // 关阀影响区域overlay
    }
  },
  watch: {
    center(val, oldVal) {
      const { mapLayers, zoom } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(val.lat, val.lng))
      }
    },
    'center.lng'(val, oldVal) {
      const { mapLayers, zoom, center } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(center.lat, val))
      }
    },
    'center.lat'(val, oldVal) {
      const { mapLayers, zoom, center } = this
      if (mapLayers != null && val !== oldVal) {
        mapLayers.setCenter(new CLatLng(val, center.lng))
      }
    },
    zoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setZoom(val)
    },
    minZoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setMinZoom(val)
    },
    maxZoom(val, oldVal) {
      const { mapLayers } = this
      mapLayers.setMaxZoom(val)
    },
    wellObj(val) {
      if (val == null) {
        this.removeOverlays()
      } else {
        this.renderAffectAP()
      }
    },
    valves(val) {
      console.log('renderValves')
      this.renderValves()
    },
    closeAreas(val) {
      console.log('renderValves')
      this.renderCloseArea()
    }
  },
  mounted() {
    console.log('map mounted')
    this.reset()
  },
  activated() {
    console.log('map activated')
    this.init()
  },
  methods: {
    // 初始化地图
    init() {
      if (this.mapLayers) {
        return
      }
      const $el = this.$refs.map
      // 影像和矢量地图
      // const sateLayer = new CTileLayer(2, 18, 'sate', null, null)// 影像
      // const sateLabelLayer = new CTileLayer(2, 18, 'satelabel', null, null)// 影像注记
      // const mapLayer = new CTileLayer(2, 18, 'map', null, null)// 矢量
      // const mapLabelLayer = new CTileLayer(2, 18, 'maplabel', null, null)// 矢量注记

      var tianditusateLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'sate',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })

      var tianditusateLabelLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'satelabel',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })

      var tianditumapLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'map',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })

      const tianditumapLabelLayer = new CTileLayer({
        zbound: [2, 18],
        tileName: 'maplabel',
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        url: 'http://t{s}.tianditu.com/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=80310778300778a15b36e70a6da5af00'
      })

      const TianDiTuBASEMAP = new CMapType([tianditumapLayer], '矢量')
      const TianDiTuVECTORMAP = new CMapType([tianditumapLayer, tianditumapLabelLayer], '矢量')
      const TianDiTuSATEMAP = new CMapType([tianditusateLayer, tianditusateLabelLayer], '影像')

      const VECTORMAP = new CMapType([tianditumapLayer, tianditumapLabelLayer], '矢量')
      const SATEMAP = new CMapType([tianditusateLayer, tianditusateLabelLayer], '影像')
      // const VECTORMAP = new CMapType([mapLayer, mapLabelLayer], '矢量')
      // const SATEMAP = new CMapType([sateLayer, sateLabelLayer], '影像')

      const { getCenterPoint, zoom } = this
      // 初始化配置
      const opts = {
        mapTypes: [VECTORMAP],
        center: getCenterPoint(),
        zoom: zoom
      }
      // 加载图层
      this.mapLayers = new CMapLayers($el, opts)
      this.mapLayers.addMapTypeControl()

      bindEvents.call(this, this.mapLayers)

      // 此处强行初始化一次地图 回避一个由于错误的 center 字符串导致初始化失败抛出的错误
      // this.mapLayers.reset()
      this.reset()
      this.mapLayers.setCenter(getCenterPoint(), zoom)
      this.$emit('ready', { mapLayers: this.mapLayers })
      // this.renderMarkers()
    },
    // 渲染影响区域
    renderAffectAP() {
      const { mapLayers } = this
      if (!mapLayers) {
        return
      }
      this.removeOverlays() // 清除所有overlay
      // 渲染井
      if (this.wellObj != null) {
        this.affectCircle = {
          lat: this.wellObj.coordinateY,
          lng: this.wellObj.coordinateX,
          radius: parseFloat(this.wellObj.radius)
        }
        this.renderWell()
        // 当影响区域不为空的时候显示影响区域
        if (this.affectCircle != null) {
          this.renderAffectArea()
        }
      }
    },
    // 移除影响区域
    removeAffectAP() {
      // 移除影响区域
      if (this.affectArea != null) {
        this.removeAffectArea()
      }
    },
    // 渲染影响区域
    renderAffectArea() {
      const { mapLayers, affectCircle } = this
      // 绘制影响区域
      const opts = { color: '#boacfc', weight: 0, opacity: 0.9, fill: true, fillColor: '#32d3eb', fillOpacity: 0.5 }
      this.affectAreaOverlay = mapLayers.drawCircle(new CLatLng(affectCircle.lat, affectCircle.lng), affectCircle.radius, opts)
    },
    // 移除影响区域
    removeAffectArea() {
      const { mapLayers } = this
      if (this.affectAreaOverlay) {
        mapLayers.removeOverlay(this.affectAreaOverlay)
        this.affectAreaOverlay = null
      }
    },
    // 渲染井
    renderWell() {
      const { mapLayers, size, anchor, wellObj } = this
      const options = {
        url: './static/images/map_images/alarm-well1.png',
        size: size,
        anchor: [15, 30]
      }
      const cmapIcon = createIcon(options)
      const opts = {
        icon: cmapIcon,
        title: wellObj.wellCode,
        draggable: false
      }
      this.wellOverlay = new CMarker(new CLatLng(wellObj.coordinateY, wellObj.coordinateX), opts)
      mapLayers.addOverlay(this.wellOverlay)
      mapLayers.setZoom(17)
      mapLayers.setCenter(new CLatLng(wellObj.coordinateY, wellObj.coordinateX))
    },
    // 移除井
    removeWell() {
      const { mapLayers } = this
      if (!this.wellOverlay) {
        mapLayers.removeOverlay(this.wellOverlay)
        this.wellOverlay = null
      }
    },
    // 渲染阀门
    renderValves() {
      const { mapLayers, size, valves } = this
      for (const valve of valves) {
        const options = {
          url: './static/images/map_images/valve1.png',
          size: [20, 20],
          anchor: [10, 10]
        }
        const cmapIcon = createIcon(options)
        const opts = {
          icon: cmapIcon,
          title: valve.valveCode,
          draggable: false
        }
        const valveOverlay = new CMarker(new CLatLng(valve.coordinateY, valve.coordinateX), opts)
        mapLayers.addOverlay(valveOverlay)
        this.valvesOverlays.push(valveOverlay)
        mapLayers.setZoom(16)
      }
    },
    // 移除影响管线
    removeValves() {
      const { mapLayers } = this
      for (const overlay of this.valves) {
        mapLayers.removeOverlay(overlay)
      }
      this.valves = []
    },
    // 渲染关阀影响区域
    renderCloseArea() {
      const { mapLayers, closeAreas } = this
      this.removeCloseArea()
      // 绘制影响区域
      for (const valveArea of closeAreas) {
        const opts = { color: '#e7944f', weight: 1, opacity: 0.9, fill: true, fillColor: '#e7944f', fillOpacity: 0.4 }
        const polygon = mapLayers.drawPolygon(valveArea.position, opts)
        this.closeAreaOverlays.push(polygon)
      }
    },
    // 移除关阀影响区域
    removeCloseArea() {
      const { mapLayers } = this
      if (this.closeAreaOverlays) {
        mapLayers.removeOverlay(this.closeAreaOverlays)
        this.closeAreaOverlays = []
      }
    },
    // 清除所有overlay
    removeOverlays() {
      const { mapLayers } = this
      mapLayers.clearOverlays()
    },
    // 获取中点
    getCenterPoint() {
      const { center } = this
      console.log('getCenterPoint:' + center.lat + ',' + center.lng)
      return new CLatLng(center.lat, center.lng)
    },
    initMap(CMapLayers) {
      this.CMapLayers = CMapLayers
      this.init(CMapLayers)
    },
    getMapScript() {
      // 动态获取cmap的脚本
      // const TMapURL = 'http://satellite.casm.ac.cn:8020/geowinmap/api?version=tapi&map=map&utils=mapcase'
      const TMapURL = 'http://119.3.228.125:8080/geowinmap/api?version=tapi&map=map&utils=mapcase,mapv'
      return new Promise((resolve, reject) => {
        console.log(window.CMapLayers)
        // 如果已加载直接返回
        if (typeof window.CMapLayers !== 'undefined') {
          console.log('地图脚本初始化成功1111...')
          resolve(window.CMapLayers)
          // return true
        } else {
          // 插入script脚本
          const scriptNode = document.createElement('script')
          scriptNode.setAttribute('type', 'text/javascript')
          scriptNode.setAttribute('src', TMapURL)

          if (scriptNode.readyState) { // IE
            scriptNode.onreadystatechange = function() {
              if (scriptNode.readyState === 'loaded' || scriptNode.readyState === 'complete') {
                scriptNode.onreadystatechange = null
                console.log('地图脚本初始化成功2...')
                // eslint-disable-next-line
                resolve(window.CMapLayers)
              }
            }
          } else { // 其他浏览器
            scriptNode.onload = function() {
              console.log('地图脚本初始化成功3...')
              resolve(window.CMapLayers)
            }
          }
          document.body.appendChild(scriptNode)
          console.log(scriptNode)
        }
      })
    },
    reset() {
      console.log('map reset')
      const { initMap, getMapScript } = this
      getMapScript()
        .then(initMap)
    }
  }
}
</script>

<style rel="stylesheet/scss" lang="scss">
  .mapDiv{
    width:100%;
    height: calc(100vh - 84px);
  }
  /*.alarm-window{*/
    /*max-width: 250px;*/
  /*!*background-color: #ffeaf1;*!*/
    /*.alarm-header {*/
      /*padding: 10px 10px 5px 10px;*/
      /*line-height: 30px;*/
      /*color: red;*/
      /*font-weight: bold;*/
      /*!*background-color: #ffecec;*!*/
    /*}*/
    /*.alarm-body{*/
      /*padding: 5px 10px 10px 10px;*/
      /*line-height: 23px;*/
      /*font-size: 14px;*/
    /*.alarm-red{*/
      /*color: #ff0000;*/
    /*}*/
  /*}*/
  /*}*/
</style>