map-marker.js 8.2 KB
Newer Older
Q
qiang 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
import getRealPath from 'uni-platform/helpers/get-real-path'

export default {
  props: {
    id: {
      type: [Number, String],
      default: ''
    },
    latitude: {
      type: [Number, String],
      require: true
    },
    longitude: {
      type: [Number, String],
      require: true
    },
    title: {
      type: String,
      default: ''
    },
    iconPath: {
      type: String,
      require: true
    },
    rotate: {
      type: [Number, String],
      default: 0
    },
    alpha: {
      type: [Number, String],
      default: 1
    },
    width: {
      type: [Number, String],
      default: ''
    },
    height: {
      type: [Number, String],
      default: ''
    },
    callout: {
      type: Object,
      default: null
    },
    label: {
      type: Object,
      default: null
    },
    anchor: {
      type: Object,
      default: null
    },
    clusterId: {
      type: [Number, String],
      default: ''
    },
    customCallout: {
      type: Object,
      default: null
    },
    ariaLabel: {
      type: String,
      default: ''
    }
  },
Q
qiang 已提交
66 67 68 69 70
  data () {
    return {
      idString: String(isNaN(Number(this.id)) ? '' : this.id)
    }
  },
Q
qiang 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  mounted () {
    const $parent = this.$parent
    $parent.mapReady(() => {
      this._maps = $parent._maps
      this._map = $parent._map
      this.addMarker(this.$props)
      Object.keys(this.$props).forEach(key => {
        this.$watch(key, () => {
          this.updateMarker(this.$props)
        })
      })
    })
  },
  beforeDestroy () {
    this.removeMarker()
  },
  methods: {
    addMarker (props) {
      const maps = this._maps
      const map = this._map
      const marker = this._marker = new maps.Marker({
        map,
        flat: true,
        autoRotation: false
      })
Q
qiang 已提交
96
      this.$parent._markers[this.idString] = marker
Q
qiang 已提交
97
      this.updateMarker(props)
98
      maps.event.addListener(marker, 'click', (e) => {
Q
qiang 已提交
99 100 101 102 103 104 105 106 107 108 109 110
        const callout = marker.callout
        if (callout) {
          const div = callout.div
          const parent = div.parentNode
          if (!callout.alwaysVisible) {
            callout.set('visible', !callout.visible)
          }
          if (callout.visible) {
            parent.removeChild(div)
            parent.appendChild(div)
          }
        }
Q
qiang 已提交
111
        if (this.idString) {
Q
qiang 已提交
112
          this.$parent.$trigger('markertap', {}, {
113 114 115
            markerId: Number(this.idString),
            latitude: typeof e.latLng.lat === 'function' ? e.latLng.lat() : e.latLng.lat,
            longitude: typeof e.latLng.lat === 'function' ? e.latLng.lng() : e.latLng.lng
Q
qiang 已提交
116 117
          })
        }
118 119 120

        const event = e.event || e.domEvent
        event.stopPropagation()
Q
qiang 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
      })
    },
    updateMarker (option) {
      const map = this._map
      const maps = this._maps
      const marker = this._marker
      const title = option.title
      const position = new maps.LatLng(option.latitude, option.longitude)
      const img = new Image()
      img.onload = () => {
        const anchor = option.anchor || {}
        let icon
        let w
        let h
        const x = typeof anchor.x === 'number' ? anchor.x : 0.5
        const y = typeof anchor.y === 'number' ? anchor.y : 1
        if (option.iconPath && (option.width || option.height)) {
          w = option.width || (img.width / img.height) * option.height
          h = option.height || (img.height / img.width) * option.width
        } else {
          w = img.width / 2
          h = img.height / 2
        }
144
        const top = h - (h - y * h)
Q
qiang 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
        if ('MarkerImage' in maps) {
          icon = new maps.MarkerImage(
            img.src,
            null,
            null,
            new maps.Point(x * w, y * h),
            new maps.Size(w, h)
          )
        } else {
          icon = {
            url: img.src,
            anchor: new maps.Point(x, y),
            size: new maps.Size(w, h)
          }
        }
        marker.setPosition(position)
        marker.setIcon(icon)
        if ('setRotation' in marker) {
          marker.setRotation(option.rotate || 0)
        }
        const labelOpt = option.label || {}
        if ('label' in marker) {
          marker.label.setMap(null)
          delete marker.label
        }
        let label
        if (labelOpt.content) {
Q
qiang 已提交
172 173 174 175 176 177 178 179 180
          const labelStyle = {
            borderColor: labelOpt.borderColor,
            borderWidth: (Number(labelOpt.borderWidth) || 0) + 'px',
            padding: (Number(labelOpt.padding) || 0) + 'px',
            borderRadius: (Number(labelOpt.borderRadius) || 0) + 'px',
            backgroundColor: labelOpt.bgColor,
            color: labelOpt.color,
            fontSize: (labelOpt.fontSize || 14) + 'px',
            lineHeight: (labelOpt.fontSize || 14) + 'px',
Q
qiang 已提交
181 182
            marginLeft: (Number(labelOpt.anchorX || labelOpt.x) || 0) + 'px',
            marginTop: (Number(labelOpt.anchorY || labelOpt.y) || 0) + 'px'
Q
qiang 已提交
183
          }
Q
qiang 已提交
184 185 186 187 188 189
          if ('Label' in maps) {
            label = new maps.Label({
              position: position,
              map: map,
              clickable: false,
              content: labelOpt.content,
Q
qiang 已提交
190
              style: labelStyle
Q
qiang 已提交
191 192 193
            })
            marker.label = label
          } else if ('setLabel' in marker) {
Q
qiang 已提交
194
            const className = this.updateMarkerLabelStyle(this.idString, labelStyle)
Q
qiang 已提交
195 196
            marker.setLabel({
              text: labelOpt.content,
Q
qiang 已提交
197 198 199
              color: labelStyle.color,
              fontSize: labelStyle.fontSize,
              className
Q
qiang 已提交
200 201 202 203 204 205 206
            })
          }
        }
        const calloutOpt = option.callout || {}
        let callout = marker.callout
        let calloutStyle
        if (calloutOpt.content || title) {
207
          const boxShadow = '0px 0px 3px 1px rgba(0,0,0,0.5)'
Q
qiang 已提交
208 209 210 211 212 213 214 215 216 217 218
          calloutStyle = calloutOpt.content
            ? {
              position,
              map,
              top,
              content: calloutOpt.content,
              color: calloutOpt.color,
              fontSize: calloutOpt.fontSize,
              borderRadius: calloutOpt.borderRadius,
              bgColor: calloutOpt.bgColor,
              padding: calloutOpt.padding,
219
              boxShadow: calloutOpt.boxShadow || boxShadow,
Q
qiang 已提交
220 221 222 223 224 225 226
              display: calloutOpt.display
            }
            : {
              position,
              map,
              top,
              content: title,
227
              boxShadow: boxShadow
Q
qiang 已提交
228 229 230 231 232
            }
          if (callout) {
            callout.setOption(calloutStyle)
          } else {
            callout = marker.callout = new maps.Callout(calloutStyle)
Q
qiang 已提交
233
            callout.div.onclick = ($event) => {
Q
qiang 已提交
234
              if (this.idString) {
Q
qiang 已提交
235
                this.$parent.$trigger('callouttap', $event, {
Q
qiang 已提交
236
                  markerId: Number(this.idString)
Q
qiang 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249
                })
              }
              $event.stopPropagation()
              $event.preventDefault()
            }
          }
        } else {
          if (callout) {
            callout.setMap(null)
            delete marker.callout
          }
        }
      }
Q
qiang 已提交
250 251 252 253 254
      if (option.iconPath) {
        img.src = getRealPath(option.iconPath)
      } else {
        console.error('Marker.iconPath is required.')
      }
Q
qiang 已提交
255
    },
Q
qiang 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
    updateMarkerLabelStyle (id, style) {
      const className = 'uni-map-marker-label-' + id
      let styleEl = document.getElementById(className)
      if (!styleEl) {
        styleEl = document.createElement('style')
        styleEl.id = className
        document.head.appendChild(styleEl)
        this.$once('hook:destroyed', () => {
          styleEl.remove()
        })
      }
      const newStyle = Object.assign({}, style, {
        position: 'absolute',
        top: '70px',
        borderStyle: 'solid'
      })
      const div = document.createElement('div')
      Object.keys(newStyle).forEach(key => {
        div.style[key] = newStyle[key] || ''
      })
      styleEl.innerText = `.${className}{${div.getAttribute('style')}}`
      return className
    },
Q
qiang 已提交
279 280 281
    removeMarker () {
      const marker = this._marker
      if (marker) {
Q
qiang 已提交
282
        if (marker.label && 'setMap' in marker.label) {
Q
qiang 已提交
283 284 285 286 287 288 289
          marker.label.setMap(null)
        }
        if (marker.callout) {
          marker.callout.setMap(null)
        }
        marker.setMap(null)
      }
Q
qiang 已提交
290
      delete this.$parent._markers[this.idString]
Q
qiang 已提交
291 292 293 294 295 296 297
      this._marker = null
    }
  },
  render () {
    return null
  }
}