<template>
|
<uni-map v-on="$listeners">
|
<div
|
ref="container"
|
class="uni-map-container"
|
/>
|
<v-uni-cover-image
|
v-for="(control, index) in mapControls"
|
:key="index"
|
:src="control.iconPath"
|
:style="control.position"
|
auto-size
|
@click="controlclick(control)"
|
/>
|
<div class="uni-map-slot">
|
<slot />
|
</div>
|
</uni-map>
|
</template>
|
<script>
|
import {
|
subscriber
|
} from 'uni-mixins'
|
import native from '../../mixins/native'
|
|
const methods = [
|
'getCenterLocation',
|
'moveToLocation',
|
'getRegion',
|
'getScale',
|
'$getAppMap'
|
]
|
|
// const events = [
|
// 'markertap',
|
// 'callouttap',
|
// 'controltap',
|
// 'regionchange',
|
// 'tap',
|
// 'updated'
|
// ]
|
|
const attrs = [
|
'latitude',
|
'longitude',
|
'scale',
|
'markers',
|
'polyline',
|
'polygons',
|
'circles',
|
'controls',
|
'show-location'
|
]
|
|
const convertCoordinates = (lng, lat, callback) => {
|
// plus.maps.Map.convertCoordinates(new plus.maps.Point(lng, lat), {
|
// coordType: 'gcj02'
|
// }, callback)
|
callback({
|
coord: {
|
latitude: lat,
|
longitude: lng
|
}
|
})
|
}
|
|
function parseHex (color) {
|
if (color.indexOf('#') !== 0) {
|
return {
|
color,
|
opacity: 1
|
}
|
}
|
const opacity = color.substr(7, 2)
|
return {
|
color: color.substr(0, 7),
|
opacity: opacity ? Number('0x' + opacity) / 255 : 1
|
}
|
}
|
|
export default {
|
name: 'Map',
|
mixins: [subscriber, native],
|
props: {
|
id: {
|
type: String,
|
default: ''
|
},
|
latitude: {
|
type: [Number, String],
|
default: ''
|
},
|
longitude: {
|
type: [Number, String],
|
default: ''
|
},
|
scale: {
|
type: [String, Number],
|
default: 16
|
},
|
markers: {
|
type: Array,
|
default () {
|
return []
|
}
|
},
|
polyline: {
|
type: Array,
|
default () {
|
return []
|
}
|
},
|
circles: {
|
type: Array,
|
default () {
|
return []
|
}
|
},
|
polygons: {
|
type: Array,
|
default () {
|
return []
|
}
|
},
|
controls: {
|
type: Array,
|
default () {
|
return []
|
}
|
}
|
},
|
data () {
|
return {
|
style: {
|
top: '0px',
|
left: '0px',
|
width: '0px',
|
height: '0px',
|
position: 'static'
|
},
|
hidden: false
|
}
|
},
|
computed: {
|
attrs () {
|
const obj = {}
|
attrs.forEach(key => {
|
let val = this.$props[key]
|
val = key === 'src' ? this.$getRealPath(val) : val
|
obj[key.replace(/[A-Z]/g, str => '-' + str.toLowerCase())] = val
|
})
|
return obj
|
},
|
mapControls () {
|
const list = this.controls.map((control) => {
|
const position = { position: 'absolute' };
|
['top', 'left', 'width', 'height'].forEach(key => {
|
if (control.position[key]) {
|
position[key] = control.position[key] + 'px'
|
}
|
})
|
return {
|
id: control.id,
|
iconPath: this.$getRealPath(control.iconPath),
|
position: position
|
}
|
})
|
return list
|
}
|
},
|
watch: {
|
hidden (val) {
|
this.map && this.map[val ? 'hide' : 'show']()
|
},
|
scale (val) {
|
this.map && this.map.setZoom(parseInt(val))
|
},
|
latitude (val) {
|
this.map && this.map.setStyles({
|
center: new plus.maps.Point(this.longitude, this.latitude)
|
})
|
},
|
longitude (val) {
|
this.map && this.map.setStyles({
|
center: new plus.maps.Point(this.longitude, this.latitude)
|
})
|
},
|
markers (val) {
|
this.map && this._addMarkers(val, true)
|
},
|
polyline (val) {
|
this.map && this._addMapLines(val)
|
},
|
circles (val) {
|
this.map && this._addMapCircles(val)
|
},
|
polygons (val) {
|
this.map && this._addMapPolygons(val)
|
}
|
},
|
mounted () {
|
this._onParentReady(() => {
|
const mapStyle = Object.assign({}, this.attrs, this.position)
|
if (this.latitude && this.longitude) {
|
mapStyle.center = new plus.maps.Point(this.longitude, this.latitude)
|
}
|
const map = this.map = plus.maps.create(this.$page.id + '-map-' + (this.id || Date.now()), mapStyle)
|
map.__markers__ = []
|
map.__markers_map__ = {}
|
map.__lines__ = []
|
map.__circles__ = []
|
map.__polygons__ = []
|
map.setZoom(parseInt(this.scale))
|
plus.webview.currentWebview().append(map)
|
if (this.hidden) {
|
map.hide()
|
}
|
this.$watch('position', () => {
|
this.map && this.map.setStyles(this.position)
|
}, {
|
deep: true
|
})
|
map.onclick = (e) => {
|
this.$trigger('click', {}, e)
|
}
|
map.onstatuschanged = (e) => {
|
this.$trigger('regionchange', {}, {})
|
}
|
this._addMarkers(this.markers)
|
this._addMapLines(this.polyline)
|
this._addMapCircles(this.circles)
|
this._addMapPolygons(this.polygons)
|
})
|
},
|
beforeDestroy () {
|
this.map && this.map.close()
|
delete this.map
|
},
|
methods: {
|
_handleSubscribe ({
|
type,
|
data = {}
|
}) {
|
if (!methods.includes(type)) {
|
return
|
}
|
this.map && this[type](data)
|
},
|
moveToLocation ({ callbackId, longitude, latitude }) {
|
this.map.setCenter(new plus.maps.Point(longitude || this.longitude, latitude || this.latitude))
|
this._publishHandler(callbackId, {
|
errMsg: 'moveToLocation:ok'
|
})
|
},
|
getCenterLocation ({ callbackId }) {
|
this.map.getCurrentCenter((state, point) => {
|
this._publishHandler(callbackId, {
|
longitude: point.longitude,
|
latitude: point.latitude,
|
errMsg: 'getCenterLocation:ok'
|
})
|
})
|
},
|
getRegion ({ callbackId }) {
|
const rect = this.map.getBounds()
|
this._publishHandler(callbackId, {
|
southwest: rect.southwest,
|
northeast: rect.northeast || rect.northease, // 5plus API 名字写错了
|
errMsg: 'getRegion:ok'
|
})
|
},
|
getScale ({ callbackId }) {
|
this._publishHandler(callbackId, {
|
scale: this.map.getZoom(),
|
errMsg: 'getScale:ok'
|
})
|
},
|
controlclick (e) {
|
this.$trigger('controltap', {}, { controlId: e.id })
|
},
|
_publishHandler (callbackId, data) {
|
UniViewJSBridge.publishHandler('onMapMethodCallback', {
|
callbackId,
|
data
|
}, this.$page.id)
|
},
|
_addMarker (nativeMap, marker) {
|
const {
|
id,
|
// title,
|
latitude,
|
longitude,
|
iconPath,
|
// width,
|
// height,
|
// rotate,
|
// alpha,
|
callout,
|
label
|
} = marker
|
convertCoordinates(longitude, latitude, res => {
|
const {
|
latitude,
|
longitude
|
} = res.coord
|
const nativeMarker = new plus.maps.Marker(new plus.maps.Point(longitude, latitude))
|
if (iconPath) {
|
nativeMarker.setIcon(this.$getRealPath(iconPath))
|
}
|
if (label && label.content) {
|
nativeMarker.setLabel(label.content)
|
}
|
let nativeBubble = false
|
if (callout && callout.content) {
|
nativeBubble = new plus.maps.Bubble(callout.content)
|
}
|
if (nativeBubble) {
|
nativeMarker.setBubble(nativeBubble)
|
}
|
if (id || id === 0) {
|
nativeMarker.onclick = (e) => {
|
this.$trigger('markertap', {}, {
|
markerId: id,
|
latitude,
|
longitude
|
})
|
}
|
if (nativeBubble) {
|
nativeBubble.onclick = () => {
|
this.$trigger('callouttap', {}, {
|
markerId: id
|
})
|
}
|
}
|
}
|
nativeMap.addOverlay(nativeMarker)
|
nativeMap.__markers__.push(nativeMarker)
|
nativeMap.__markers_map__[id + ''] = nativeMarker
|
})
|
},
|
_clearMarkers () {
|
const map = this.map
|
const markers = map.__markers__
|
markers.forEach(marker => {
|
map.removeOverlay(marker)
|
})
|
map.__markers__ = []
|
map.__markers_map__ = {}
|
},
|
_addMarkers (markers, clear) {
|
if (clear) {
|
this._clearMarkers()
|
}
|
markers.forEach(marker => {
|
this._addMarker(this.map, marker)
|
})
|
},
|
_translateMapMarker ({
|
autoRotate,
|
callbackId,
|
destination,
|
duration,
|
markerId
|
}) {
|
const nativeMarker = this.map.__markers_map__[markerId + '']
|
if (nativeMarker) {
|
nativeMarker.setPoint(new plus.maps.Point(destination.longitude, destination.latitude))
|
}
|
},
|
_addMapLines (lines) {
|
const nativeMap = this.map
|
|
if (nativeMap.__lines__.length > 0) {
|
nativeMap.__lines__.forEach(circle => {
|
nativeMap.removeOverlay(circle)
|
})
|
nativeMap.__lines__ = []
|
}
|
|
lines.forEach(line => {
|
const {
|
color,
|
width
|
// dottedLine,
|
// arrowLine,
|
// arrowIconPath,
|
// borderColor,
|
// borderWidth
|
} = line
|
const points = line.points.map(point => new plus.maps.Point(point.longitude, point.latitude))
|
const polyline = new plus.maps.Polyline(points)
|
if (color) {
|
const strokeStyle = parseHex(color)
|
polyline.setStrokeColor(strokeStyle.color)
|
polyline.setStrokeOpacity(strokeStyle.opacity)
|
}
|
if (width) {
|
polyline.setLineWidth(width)
|
}
|
nativeMap.addOverlay(polyline)
|
nativeMap.__lines__.push(polyline)
|
})
|
},
|
_addMapCircles (circles) {
|
const nativeMap = this.map
|
|
if (nativeMap.__circles__.length > 0) {
|
nativeMap.__circles__.forEach(circle => {
|
nativeMap.removeOverlay(circle)
|
})
|
nativeMap.__circles__ = []
|
}
|
|
circles.forEach(circle => {
|
const {
|
latitude,
|
longitude,
|
color,
|
fillColor,
|
radius,
|
strokeWidth
|
} = circle
|
const nativeCircle = new plus.maps.Circle(new plus.maps.Point(longitude, latitude), radius)
|
if (color) {
|
const strokeStyle = parseHex(color)
|
nativeCircle.setStrokeColor(strokeStyle.color)
|
nativeCircle.setStrokeOpacity(strokeStyle.opacity)
|
}
|
if (fillColor) {
|
const fillStyle = parseHex(fillColor)
|
nativeCircle.setFillColor(fillStyle.color)
|
nativeCircle.setFillOpacity(fillStyle.opacity)
|
}
|
if (strokeWidth) {
|
nativeCircle.setLineWidth(strokeWidth)
|
}
|
nativeMap.addOverlay(nativeCircle)
|
nativeMap.__circles__.push(nativeCircle)
|
})
|
},
|
_addMapPolygons (polygons) {
|
const nativeMap = this.map
|
|
const nativeMapPolygons = nativeMap.__polygons__
|
nativeMapPolygons.forEach(polygon => {
|
nativeMap.removeOverlay(polygon)
|
})
|
nativeMapPolygons.length = 0
|
|
polygons.forEach(polygon => {
|
const {
|
points,
|
strokeWidth,
|
strokeColor,
|
fillColor
|
} = polygon
|
const plusPoints = []
|
if (points) {
|
points.forEach(({ latitude, longitude }) => {
|
plusPoints.push(new plus.maps.Point(longitude, latitude))
|
})
|
}
|
const nativePolygon = new plus.maps.Polygon(plusPoints)
|
if (strokeColor) {
|
const strokeStyle = parseHex(strokeColor)
|
nativePolygon.setStrokeColor(strokeStyle.color)
|
nativePolygon.setStrokeOpacity(strokeStyle.opacity)
|
}
|
if (fillColor) {
|
const fillStyle = parseHex(fillColor)
|
nativePolygon.setFillColor(fillStyle.color)
|
nativePolygon.setFillOpacity(fillStyle.opacity)
|
}
|
if (strokeWidth) {
|
nativePolygon.setLineWidth(strokeWidth)
|
}
|
nativeMap.addOverlay(nativePolygon)
|
nativeMapPolygons.push(nativePolygon)
|
})
|
}
|
}
|
}
|
</script>
|
|
<style>
|
uni-map {
|
width: 300px;
|
height: 225px;
|
display: inline-block;
|
line-height: 0;
|
overflow: hidden;
|
position: relative;
|
}
|
|
uni-map[hidden] {
|
display: none;
|
}
|
|
.uni-map-container {
|
width: 100%;
|
height: 100%;
|
position: absolute;
|
top: 0;
|
left: 0;
|
overflow: hidden;
|
background-color: transparent;
|
}
|
|
.uni-map-slot {
|
position: absolute;
|
top: 0;
|
width: 100%;
|
height: 100%;
|
overflow: hidden;
|
pointer-events: none;
|
}
|
</style>
|