'a'
mh-two-thousand-and-two
2024-04-12 44d2c92345cd156a59fc327b3060292a282d2893
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
66
67
68
69
70
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
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
172
173
174
175
176
177
178
179
180
181
182
183
import { IS_AMAP } from '../../../../helpers/location'
 
export function createCallout (maps) {
  function onAdd () {
    const div = this.div
    const panes = this.getPanes()
    panes.floatPane.appendChild(div)
  }
  function onRemove () {
    const parentNode = this.div.parentNode
    if (parentNode) {
      parentNode.removeChild(this.div)
    }
  }
 
  function createAMapText () {
    const option = this.option
    this.Text = new maps.Text({
      text: option.content,
      anchor: 'bottom-center', // 设置文本标记锚点
      offset: new maps.Pixel(0, option.offsetY - 16),
      style: {
        padding: (option.padding || 8) + 'px',
        'line-height': (option.fontSize || 14) + 'px',
        'border-radius': (option.borderRadius || 0) + 'px',
        'border-color': `${option.bgColor || '#fff'} transparent transparent`,
        'background-color': option.bgColor || '#fff',
        'box-shadow': '0 2px 6px 0 rgba(114, 124, 245, .5)',
        'text-align': 'center',
        'font-size': (option.fontSize || 14) + 'px',
        color: option.color || '#000'
      },
      position: option.position
    })
    // 不通过 addListener 方式绑定事件,为了规避高德地图覆盖物点击触发map点击问题
    this.Text.dom.addEventListener('click', e => {
      handleAMapTextClick(this, e)
    })
    this.Text.dom.addEventListener('touchend', e => {
      handleAMapTextClick(this, e)
    })
 
    this.Text.setMap(option.map)
  }
 
  function handleAMapTextClick (self, e) {
    self.callback(e, self.parent)
    e.stopPropagation()
  }
 
  function removeAMapText () {
    if (this.Text) {
      this.option.map.remove(this.Text)
    }
  }
 
  class Callout {
    option
    position
    index
    visible
    alwaysVisible
    div
    triangle
    callback
    parent
    Text
 
    set onclick (callback) {
      this.div.onclick = callback
    }
 
    get onclick () {
      return this.div.onclick
    }
 
    constructor (option = {}, callback, parent) {
      this.option = option || {}
      this.visible = this.alwaysVisible = option.display === 'ALWAYS'
      if (IS_AMAP) {
        this.callback = callback
        this.parent = parent
        if (this.visible) {
          this.createAMapText()
        }
      } else {
        const map = option.map
        this.position = option.position
        this.index = 1
        const div = (this.div = document.createElement('div'))
        const divStyle = div.style
        divStyle.position = 'absolute'
        divStyle.whiteSpace = 'nowrap'
        divStyle.transform = 'translateX(-50%) translateY(-100%)'
        divStyle.zIndex = '1'
        divStyle.boxShadow = option.boxShadow || 'none'
        divStyle.display = this.visible ? 'block' : 'none'
        const triangle = (this.triangle = document.createElement('div'))
        triangle.setAttribute(
          'style',
          'position: absolute;white-space: nowrap;border-width: 4px;border-style: solid;border-color: #fff transparent transparent;border-image: initial;font-size: 12px;padding: 0px;background-color: transparent;width: 0px;height: 0px;transform: translate(-50%, 100%);left: 50%;bottom: 0;'
        )
        this.setStyle(option)
        div.appendChild(triangle)
        if (map) {
          this.setMap(map)
        }
      }
    }
 
    createAMapText = createAMapText
    removeAMapText = removeAMapText
 
    onAdd = onAdd
    construct = onAdd
    setOption (option) {
      this.option = option
      if (option.display === 'ALWAYS') {
        this.alwaysVisible = this.visible = true
      } else {
        this.alwaysVisible = false
      }
      if (IS_AMAP) {
        if (this.visible) {
          this.createAMapText()
        }
      } else {
        this.setPosition(option.position)
        this.setStyle(option)
      }
    }
 
    setStyle (option) {
      const div = this.div
      const divStyle = div.style
      div.innerText = option.content || ''
      divStyle.lineHeight = (option.fontSize || 14) + 'px'
      divStyle.fontSize = (option.fontSize || 14) + 'px'
      divStyle.padding = (option.padding || 8) + 'px'
      divStyle.color = option.color || '#000'
      divStyle.borderRadius = (option.borderRadius || 0) + 'px'
      divStyle.backgroundColor = option.bgColor || '#fff'
      divStyle.marginTop = '-' + ((option.top || 0) + 5) + 'px'
      this.triangle.style.borderColor = `${option.bgColor || '#fff'} transparent transparent`
    }
 
    setPosition (position) {
      this.position = position
      this.draw()
    }
 
    draw () {
      const overlayProjection = this.getProjection()
      if (!this.position || !this.div || !overlayProjection) {
        return
      }
      const pixel = overlayProjection.fromLatLngToDivPixel(this.position)
      const divStyle = this.div.style
      divStyle.left = pixel.x + 'px'
      divStyle.top = pixel.y + 'px'
    }
 
    changed () {
      const divStyle = this.div.style
      divStyle.display = this.visible ? 'block' : 'none'
    }
 
    onRemove = onRemove
 
    destroy = onRemove
  }
  if (!IS_AMAP) {
    const prototype = Callout.prototype
    const overlay = new (maps.OverlayView || maps.Overlay)()
    for (const key in overlay) {
      if (!(key in prototype)) {
        prototype[key] = overlay[key]
      }
    }
  }
 
  return Callout
}