xy-map 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compontents/detail-dialog.vue +141 -0
- package/image/arrow_white.png +0 -0
- package/image/map_end.png +0 -0
- package/image/map_start.png +0 -0
- package/image/marker.png +0 -0
- package/layers/Line.js +175 -0
- package/layers/Point.js +251 -0
- package/layers/Polygon.js +94 -0
- package/layers/Text.js +46 -0
- package/layers/index.js +119 -0
- package/map.js +400 -0
- package/package.json +13 -0
- package/style/hoverHtml.css +29 -0
- package/style/map.css +7 -0
- package/util/mapEvent.js +108 -0
- package/util/mapHoverHtml.js +54 -0
- package/util/mapTools.js +117 -0
- package/util/measure-area.js +215 -0
- package/util/measure-distance.js +600 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-dialog :title="title"
|
|
3
|
+
:visible.sync="show"
|
|
4
|
+
:width="width"
|
|
5
|
+
append-to-body>
|
|
6
|
+
<el-row :gutter="24">
|
|
7
|
+
<el-col v-for="(item, index) in columns"
|
|
8
|
+
:key="index"
|
|
9
|
+
:span="colSpan"
|
|
10
|
+
v-show="data[item.key]"
|
|
11
|
+
class="item">
|
|
12
|
+
<el-col :span="labelSpan"
|
|
13
|
+
class="label">{{ item.label }}</el-col>
|
|
14
|
+
<el-col :span="24 - labelSpan"
|
|
15
|
+
class="value">
|
|
16
|
+
<span v-if="item.type === 'select'">{{ getValue(item) }}</span>
|
|
17
|
+
<div class="flex flex-wrap flex-align-center"
|
|
18
|
+
style="margin-top: 8px"
|
|
19
|
+
v-else-if="item.type === 'image' && data[key]">
|
|
20
|
+
<el-image class="viewImg margin-right margin-bottom"
|
|
21
|
+
v-for="(img,index) in data[key].split(',').map(m => $website.imgPath + m)"
|
|
22
|
+
:key="index"
|
|
23
|
+
:src="img"
|
|
24
|
+
fit="cover"
|
|
25
|
+
:preview-src-list="data[key].split(',').map(m => $website.imgPath + m)"
|
|
26
|
+
style="width: 100px;height: 100px"
|
|
27
|
+
z-index="9999"></el-image>
|
|
28
|
+
</div>
|
|
29
|
+
<span v-else-if="item.type === 'imgVideo'">
|
|
30
|
+
<imgVideoBox :fileList="getFileList(data[item.key])"
|
|
31
|
+
:mode="3"></imgVideoBox>
|
|
32
|
+
</span>
|
|
33
|
+
<span v-else>{{ data[item.key] }}</span>
|
|
34
|
+
<span v-if="item.suffixText">{{ item.suffixText }}</span>
|
|
35
|
+
</el-col>
|
|
36
|
+
</el-col>
|
|
37
|
+
<div v-if="columns.length === 0">暂无数据~</div>
|
|
38
|
+
</el-row>
|
|
39
|
+
</el-dialog>
|
|
40
|
+
</template>
|
|
41
|
+
|
|
42
|
+
<script>
|
|
43
|
+
export default {
|
|
44
|
+
props: {
|
|
45
|
+
width: {
|
|
46
|
+
type: String,
|
|
47
|
+
default: '60%'
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
data () {
|
|
51
|
+
return {
|
|
52
|
+
title: '详情',
|
|
53
|
+
colSpan: 12,
|
|
54
|
+
labelSpan: 5,
|
|
55
|
+
show: false,
|
|
56
|
+
data: {},
|
|
57
|
+
columns: [
|
|
58
|
+
{
|
|
59
|
+
label: '实时地址',
|
|
60
|
+
key: 'address',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: '汇水面积',
|
|
64
|
+
key: 'catchmentArea',
|
|
65
|
+
suffixText: 'm²',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: '淹水等级',
|
|
69
|
+
key: 'grade',
|
|
70
|
+
type: 'select',
|
|
71
|
+
dicData: [
|
|
72
|
+
{
|
|
73
|
+
label: '轻度',
|
|
74
|
+
value: 0,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: '中度',
|
|
78
|
+
value: 1,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
label: '重度',
|
|
82
|
+
value: 3,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
label: '淹水原因',
|
|
88
|
+
key: 'content',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
label: '积水开始时间',
|
|
92
|
+
key: 'ysdTime',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
label: '上报时间',
|
|
96
|
+
key: 'reportTime',
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
label: '上报用户',
|
|
100
|
+
key: 'userName',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
label: '经度',
|
|
104
|
+
key: 'lgtd',
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
label: '纬度',
|
|
108
|
+
key: 'lttd',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
label: '积水图片/视频',
|
|
112
|
+
key: 'attachUrl',
|
|
113
|
+
type: 'imgVideo',
|
|
114
|
+
span: 24,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
methods: {
|
|
120
|
+
// 获取dic数据
|
|
121
|
+
getValue (item) {
|
|
122
|
+
const currentObj = item.dicData.find(
|
|
123
|
+
(f) => f.value === this.data[item.key]
|
|
124
|
+
)
|
|
125
|
+
if (currentObj) {
|
|
126
|
+
return currentObj.label
|
|
127
|
+
}
|
|
128
|
+
return ''
|
|
129
|
+
},
|
|
130
|
+
openDialog (data, columns, title) {
|
|
131
|
+
if (title) this.title = title
|
|
132
|
+
this.columns = columns
|
|
133
|
+
this.show = true
|
|
134
|
+
this.data = data
|
|
135
|
+
},
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
</script>
|
|
139
|
+
|
|
140
|
+
<style lang="scss" scoped>
|
|
141
|
+
</style>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/image/marker.png
ADDED
|
Binary file
|
package/layers/Line.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import mapSdk from '../map'
|
|
2
|
+
import * as turf from '@turf/turf'
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
hasSource,
|
|
6
|
+
setSource,
|
|
7
|
+
hasLayer,
|
|
8
|
+
} from './index'
|
|
9
|
+
import {
|
|
10
|
+
addLayerText
|
|
11
|
+
} from './Text'
|
|
12
|
+
import {
|
|
13
|
+
mapClick
|
|
14
|
+
} from '../util/mapEvent'
|
|
15
|
+
|
|
16
|
+
const defaultOptions = {
|
|
17
|
+
id: '',
|
|
18
|
+
data: [],
|
|
19
|
+
text: {
|
|
20
|
+
show: true,
|
|
21
|
+
layout: {},
|
|
22
|
+
paint: {}
|
|
23
|
+
},
|
|
24
|
+
style: {},
|
|
25
|
+
hover: null,
|
|
26
|
+
click: null,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 添加线图层
|
|
31
|
+
*/
|
|
32
|
+
export const addLayerLine = (option, layerId) => {
|
|
33
|
+
let {
|
|
34
|
+
map
|
|
35
|
+
} = mapSdk
|
|
36
|
+
|
|
37
|
+
let opt = Object.assign({}, defaultOptions, option)
|
|
38
|
+
let id = opt.id
|
|
39
|
+
if (hasLayer(id)) {
|
|
40
|
+
setSource(id, opt.data)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let layout = opt.style ? opt.style.layout : {}
|
|
45
|
+
let layoutOpt = Object.assign({
|
|
46
|
+
'line-join': 'round',
|
|
47
|
+
'line-cap': 'round',
|
|
48
|
+
'visibility': 'visible',
|
|
49
|
+
}, layout)
|
|
50
|
+
|
|
51
|
+
let paint = opt.style ? opt.style.paint : {}
|
|
52
|
+
let paintOpt = Object.assign({
|
|
53
|
+
'line-color': '#28b2ff',
|
|
54
|
+
'line-width': 3,
|
|
55
|
+
'line-opacity': 1
|
|
56
|
+
}, paint)
|
|
57
|
+
|
|
58
|
+
if (!hasSource(id)) {
|
|
59
|
+
map.addSource(opt.id, {
|
|
60
|
+
type: 'geojson',
|
|
61
|
+
data: opt.data
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
map.addLayer({
|
|
67
|
+
id: id,
|
|
68
|
+
type: 'line',
|
|
69
|
+
source: id,
|
|
70
|
+
layout: layoutOpt,
|
|
71
|
+
paint: paintOpt
|
|
72
|
+
}, layerId)
|
|
73
|
+
|
|
74
|
+
if (opt.click) {
|
|
75
|
+
mapClick(opt.id, opt.click)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (opt.style && opt.style.animate) {
|
|
79
|
+
addLayerLineAnimation(opt, layerId)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// 添加文本图层
|
|
83
|
+
if (opt.text && opt.text.show) {
|
|
84
|
+
addLayerText('line', opt)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 添加动画线图层
|
|
91
|
+
* addLayerLine配置图层
|
|
92
|
+
*/
|
|
93
|
+
export const addLayerLineAnimation = (option, layerId) => {
|
|
94
|
+
let {
|
|
95
|
+
map
|
|
96
|
+
} = mapSdk
|
|
97
|
+
|
|
98
|
+
let opt = option
|
|
99
|
+
let parentId = opt.id
|
|
100
|
+
let id = parentId + '-animate'
|
|
101
|
+
if (hasLayer(id)) {
|
|
102
|
+
setSource(id, opt.data)
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
let layout = opt.style ? opt.style.layout : {}
|
|
107
|
+
let layoutOpt = Object.assign({
|
|
108
|
+
'line-join': 'round',
|
|
109
|
+
'line-cap': 'round',
|
|
110
|
+
'visibility': 'visible',
|
|
111
|
+
}, layout)
|
|
112
|
+
|
|
113
|
+
let paint = opt.style ? opt.style.animate : {}
|
|
114
|
+
let paintOpt = Object.assign({
|
|
115
|
+
'line-width': 3,
|
|
116
|
+
'line-opacity': 1,
|
|
117
|
+
'line-gradient': [
|
|
118
|
+
'interpolate',
|
|
119
|
+
['linear'],
|
|
120
|
+
['line-progress'],
|
|
121
|
+
0, 'transparent',
|
|
122
|
+
1, '#2bffdf',
|
|
123
|
+
]
|
|
124
|
+
}, paint)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if (!hasSource(id)) {
|
|
128
|
+
map.addSource(id, {
|
|
129
|
+
type: 'geojson',
|
|
130
|
+
lineMetrics: true,
|
|
131
|
+
data: {
|
|
132
|
+
type: 'FeatureCollection',
|
|
133
|
+
features: []
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
map.addLayer({
|
|
139
|
+
id: id,
|
|
140
|
+
type: 'line',
|
|
141
|
+
source: id,
|
|
142
|
+
layout: layoutOpt,
|
|
143
|
+
paint: paintOpt
|
|
144
|
+
}, layerId)
|
|
145
|
+
|
|
146
|
+
// 动态节点数据
|
|
147
|
+
let step = opt.animate && opt.animate.step ? opt.animate.step : 400
|
|
148
|
+
opt.data.features.forEach(f => {
|
|
149
|
+
let coordinates = f.geometry.coordinates
|
|
150
|
+
if (coordinates.length > 0) {
|
|
151
|
+
let arc = []
|
|
152
|
+
// 计算起点和终点长度,切割数组
|
|
153
|
+
let lineDistance = turf.lineDistance(f, 'kilometers')
|
|
154
|
+
for (let q = 0; q < lineDistance; q += lineDistance / step) {
|
|
155
|
+
let segment = turf.along(f, q, 'kilometers')
|
|
156
|
+
arc.push(segment.geometry.coordinates)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 更新数据
|
|
160
|
+
let i = 0
|
|
161
|
+
f.geometry.coordinates = [arc[i]]
|
|
162
|
+
setInterval(() => {
|
|
163
|
+
if (arc[i]) {
|
|
164
|
+
f.geometry.coordinates.push(arc[i])
|
|
165
|
+
map.getSource(id).setData(opt.data)
|
|
166
|
+
}
|
|
167
|
+
i++
|
|
168
|
+
if (i > arc.length) {
|
|
169
|
+
i = 0
|
|
170
|
+
f.geometry.coordinates = [arc[i]]
|
|
171
|
+
}
|
|
172
|
+
}, 10)
|
|
173
|
+
}
|
|
174
|
+
})
|
|
175
|
+
}
|
package/layers/Point.js
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import mapSdk from '../map'
|
|
2
|
+
import {
|
|
3
|
+
hasSource,
|
|
4
|
+
hasLayer,
|
|
5
|
+
setSource
|
|
6
|
+
} from './index'
|
|
7
|
+
import {
|
|
8
|
+
mapClick
|
|
9
|
+
} from '../util/mapEvent'
|
|
10
|
+
|
|
11
|
+
const defaultOptions = {
|
|
12
|
+
id: '',
|
|
13
|
+
data: [],
|
|
14
|
+
text: {
|
|
15
|
+
show: true,
|
|
16
|
+
layout: {},
|
|
17
|
+
paint: {}
|
|
18
|
+
},
|
|
19
|
+
image: {
|
|
20
|
+
width: 24,
|
|
21
|
+
height: 24,
|
|
22
|
+
imageList: [],
|
|
23
|
+
},
|
|
24
|
+
style: {},
|
|
25
|
+
cluster: {
|
|
26
|
+
cluster: false,
|
|
27
|
+
clusterMaxZoom: 16,
|
|
28
|
+
clusterRadius: 500
|
|
29
|
+
},
|
|
30
|
+
hover: null,
|
|
31
|
+
click: null,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 添加点图层
|
|
36
|
+
*/
|
|
37
|
+
export const addLayerPoint = (option, layerId) => { // 点
|
|
38
|
+
let {
|
|
39
|
+
map
|
|
40
|
+
} = mapSdk
|
|
41
|
+
|
|
42
|
+
let opt = Object.assign({}, defaultOptions, option)
|
|
43
|
+
let id = opt.id
|
|
44
|
+
if (hasLayer(id)) {
|
|
45
|
+
setSource(id, opt.data)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let paint = opt.style ? opt.style.paint : {}
|
|
50
|
+
let paintOpt = Object.assign({
|
|
51
|
+
'circle-color': '#11b4da',
|
|
52
|
+
'circle-radius': 4,
|
|
53
|
+
'circle-stroke-width': 1,
|
|
54
|
+
'circle-stroke-color': '#fff'
|
|
55
|
+
}, paint)
|
|
56
|
+
|
|
57
|
+
if (!hasSource(id)) {
|
|
58
|
+
map.addSource(id, {
|
|
59
|
+
type: 'geojson',
|
|
60
|
+
data: opt.data,
|
|
61
|
+
...opt.cluster
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
map.addLayer({
|
|
66
|
+
id: id,
|
|
67
|
+
type: 'circle',
|
|
68
|
+
source: id,
|
|
69
|
+
paint: paintOpt
|
|
70
|
+
}, layerId)
|
|
71
|
+
|
|
72
|
+
if (opt.cluster.cluster) {
|
|
73
|
+
let style = opt.style || {}
|
|
74
|
+
clusterLayer(id, style)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (opt.click) {
|
|
78
|
+
mapClick(id, opt.click)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 添加图片点图层
|
|
84
|
+
*/
|
|
85
|
+
export const addLayerImagePoint = async (option, layerId) => { // 点
|
|
86
|
+
let {
|
|
87
|
+
map
|
|
88
|
+
} = mapSdk
|
|
89
|
+
|
|
90
|
+
let opt = Object.assign({}, defaultOptions, option)
|
|
91
|
+
let id = opt.id
|
|
92
|
+
if (hasLayer(id)) {
|
|
93
|
+
setSource(id, opt.data)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let image = opt.image
|
|
98
|
+
|
|
99
|
+
let layout = opt.style ? opt.style.layout : {}
|
|
100
|
+
let layoutOpt = Object.assign({
|
|
101
|
+
'icon-image': image.imageList && image.imageList.length > 0 ? ['get', 'imgId'] : `${id}-marker`,
|
|
102
|
+
'icon-size': 1,
|
|
103
|
+
'text-field': ['get', 'name'],
|
|
104
|
+
/* 使用text标签显示的值,Feature属性使用{域名}格式*/
|
|
105
|
+
'text-font': ['Open Sans Semibold'],
|
|
106
|
+
/* 文本字体 */
|
|
107
|
+
'text-size': 10,
|
|
108
|
+
'text-offset': [0, 1], // 该属性表示文本偏移锚点的距离,正值表示向右和向下,负值表示向左和向上
|
|
109
|
+
'text-anchor': 'top', // 图标与锚点的位置关系
|
|
110
|
+
'icon-allow-overlap': false, // 是否允许图标重叠
|
|
111
|
+
'icon-ignore-placement': false, // 是否忽略图标位置(可选,默认值为 false。当值为 true 时,其他符号即使与此图标触碰也会显示)
|
|
112
|
+
'text-allow-overlap': false, // 是否允许文本重叠(可选,默认值为 false。当值为 true 时,文本即使和其他符号触碰也会显示)
|
|
113
|
+
'text-ignore-placement': false, // 是否忽略文本位置(可选,默认值为 false。当值为 true 时,其他符号即使与此文本触碰也会显示)
|
|
114
|
+
// 'text-max-width': 12, // 文本宽度
|
|
115
|
+
'visibility': 'visible'
|
|
116
|
+
}, layout)
|
|
117
|
+
|
|
118
|
+
let paint = opt.style ? opt.style.paint : {}
|
|
119
|
+
let paintOpt = Object.assign({
|
|
120
|
+
'text-color': '#ffffff',
|
|
121
|
+
'text-halo-color': 'rgba(0, 0, 0, .5)',
|
|
122
|
+
'text-halo-width': 0.8,
|
|
123
|
+
'text-opacity': 1
|
|
124
|
+
}, paint)
|
|
125
|
+
|
|
126
|
+
if (!hasSource(id)) {
|
|
127
|
+
map.addSource(id, {
|
|
128
|
+
type: 'geojson',
|
|
129
|
+
data: opt.data,
|
|
130
|
+
...opt.cluster
|
|
131
|
+
})
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 图片加载完成后的操作
|
|
135
|
+
const afterOperation = () => {
|
|
136
|
+
map.addLayer({
|
|
137
|
+
id: id,
|
|
138
|
+
type: 'symbol',
|
|
139
|
+
source: id,
|
|
140
|
+
layout: layoutOpt,
|
|
141
|
+
paint: paintOpt
|
|
142
|
+
}, layerId)
|
|
143
|
+
|
|
144
|
+
if (opt.cluster.cluster) {
|
|
145
|
+
let style = opt.style || {}
|
|
146
|
+
clusterLayer(id, style)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (opt.click) {
|
|
150
|
+
mapClick(id, opt.click)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//图像处理导入
|
|
154
|
+
if (image.imageList && image.imageList.length > 0) {
|
|
155
|
+
// 循环遍历图片,同步执行,避免layer重复创建
|
|
156
|
+
for (let i = 0; i < image.imageList.length; i++) {
|
|
157
|
+
const img = image.imageList[i]
|
|
158
|
+
const loadImg = new Promise((resolve, reject) => {
|
|
159
|
+
loadImage(img.url, image.width, image.height).then(image => {
|
|
160
|
+
map.addImage(`${img.id}`, image)
|
|
161
|
+
resolve()
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
await loadImg
|
|
165
|
+
}
|
|
166
|
+
afterOperation()
|
|
167
|
+
} else {
|
|
168
|
+
const img = require('../image/marker.png')
|
|
169
|
+
loadImage(img).then(image => {
|
|
170
|
+
map.addImage(`${id}-marker`, image)
|
|
171
|
+
afterOperation()
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 加载图片
|
|
178
|
+
*/
|
|
179
|
+
export const loadImage = (src, width = 24, height = 24) => {
|
|
180
|
+
return new Promise((resolve) => {
|
|
181
|
+
let image = new Image(width, height)
|
|
182
|
+
image.src = src
|
|
183
|
+
image.onload = () => {
|
|
184
|
+
resolve(image)
|
|
185
|
+
}
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 点聚合图层
|
|
191
|
+
*/
|
|
192
|
+
export const clusterLayer = (option, style) => {
|
|
193
|
+
let {
|
|
194
|
+
map
|
|
195
|
+
} = mapSdk
|
|
196
|
+
|
|
197
|
+
let id = option.id
|
|
198
|
+
if (hasLayer(id)) {
|
|
199
|
+
setSource(id, option.data)
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
let layout = style ? style.layout : {}
|
|
204
|
+
let layoutOpt = Object.assign({
|
|
205
|
+
'text-field': '{point_count_abbreviated}',
|
|
206
|
+
'text-size': 12,
|
|
207
|
+
'visibility': 'visible'
|
|
208
|
+
}, layout)
|
|
209
|
+
|
|
210
|
+
let paint = style ? style.paint : {}
|
|
211
|
+
let paintOpt = Object.assign({
|
|
212
|
+
'circle-color': [
|
|
213
|
+
'step',
|
|
214
|
+
['get', 'point_count'],
|
|
215
|
+
'#51bbd6',
|
|
216
|
+
100,
|
|
217
|
+
'#f1f075',
|
|
218
|
+
750,
|
|
219
|
+
'#f28cb1'
|
|
220
|
+
],
|
|
221
|
+
'circle-radius': [
|
|
222
|
+
'step',
|
|
223
|
+
['get', 'point_count'],
|
|
224
|
+
20,
|
|
225
|
+
100,
|
|
226
|
+
30,
|
|
227
|
+
750,
|
|
228
|
+
40
|
|
229
|
+
]
|
|
230
|
+
}, paint)
|
|
231
|
+
|
|
232
|
+
map.addLayer({
|
|
233
|
+
id: id + '-clusters',
|
|
234
|
+
type: 'circle',
|
|
235
|
+
source: id,
|
|
236
|
+
filter: ['has', 'point_count'],
|
|
237
|
+
paint: paintOpt
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
map.addLayer({
|
|
241
|
+
id: id + '-cluster-count',
|
|
242
|
+
type: 'symbol',
|
|
243
|
+
source: option.id,
|
|
244
|
+
filter: ['has', 'point_count'],
|
|
245
|
+
layout: layoutOpt
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
mapClick(id + 'clusters', (e) => {
|
|
249
|
+
mapSdk.zoom('in', e.position)
|
|
250
|
+
})
|
|
251
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import mapSdk from '../map'
|
|
2
|
+
import {
|
|
3
|
+
addLayerText
|
|
4
|
+
} from './Text'
|
|
5
|
+
import {
|
|
6
|
+
setSource,
|
|
7
|
+
hasSource,
|
|
8
|
+
hasLayer
|
|
9
|
+
} from './index'
|
|
10
|
+
import {
|
|
11
|
+
mapClick
|
|
12
|
+
} from '../util/mapEvent'
|
|
13
|
+
|
|
14
|
+
const defaultOptions = {
|
|
15
|
+
id: '',
|
|
16
|
+
data: [],
|
|
17
|
+
text: {
|
|
18
|
+
show: true,
|
|
19
|
+
layout: {},
|
|
20
|
+
paint: {}
|
|
21
|
+
},
|
|
22
|
+
style: {},
|
|
23
|
+
hover: null,
|
|
24
|
+
click: null,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 添加面图层
|
|
29
|
+
*/
|
|
30
|
+
export const addLayerPolygon = (option, layerId) => {
|
|
31
|
+
let {
|
|
32
|
+
map
|
|
33
|
+
} = mapSdk
|
|
34
|
+
|
|
35
|
+
let opt = Object.assign({}, defaultOptions, option)
|
|
36
|
+
let id = opt.id
|
|
37
|
+
if (hasLayer(id)) {
|
|
38
|
+
setSource(id, opt.data)
|
|
39
|
+
return
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let layout = option.style ? option.style.layout : {}
|
|
43
|
+
let layoutOpt = Object.assign({
|
|
44
|
+
'visibility': 'visible',
|
|
45
|
+
}, layout)
|
|
46
|
+
|
|
47
|
+
let paint = option.style ? option.style.paint : {}
|
|
48
|
+
let paintOpt = Object.assign({
|
|
49
|
+
'fill-color': '#28b2ff',
|
|
50
|
+
'fill-opacity': 0.3
|
|
51
|
+
}, paint)
|
|
52
|
+
|
|
53
|
+
let line = option.style ? option.style.line : {}
|
|
54
|
+
let lineOpt = Object.assign({
|
|
55
|
+
'line-color': '#fff',
|
|
56
|
+
'line-width': 1,
|
|
57
|
+
'line-opacity': 0.8
|
|
58
|
+
}, line)
|
|
59
|
+
|
|
60
|
+
if (!hasSource(id)) {
|
|
61
|
+
map.addSource(id, {
|
|
62
|
+
type: 'geojson',
|
|
63
|
+
data: opt.data
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
map.addLayer({
|
|
68
|
+
id: id,
|
|
69
|
+
type: 'fill',
|
|
70
|
+
source: id,
|
|
71
|
+
layout: layoutOpt,
|
|
72
|
+
paint: paintOpt
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// 面描边
|
|
76
|
+
map.addLayer({
|
|
77
|
+
id: id + '-line',
|
|
78
|
+
type: 'line',
|
|
79
|
+
source: id,
|
|
80
|
+
layout: {
|
|
81
|
+
'visibility': 'visible',
|
|
82
|
+
},
|
|
83
|
+
paint: lineOpt
|
|
84
|
+
}, layerId)
|
|
85
|
+
|
|
86
|
+
if (opt.click) {
|
|
87
|
+
mapClick(id, opt.click)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 添加文本图层
|
|
91
|
+
if (opt.text && opt.text.show) {
|
|
92
|
+
addLayerText('point', opt)
|
|
93
|
+
}
|
|
94
|
+
}
|
package/layers/Text.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import mapSdk from '../map'
|
|
2
|
+
import {
|
|
3
|
+
setSource,
|
|
4
|
+
hasLayer
|
|
5
|
+
} from './index'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 添加文字图层
|
|
9
|
+
*/
|
|
10
|
+
export const addLayerText = (placement = 'point', option, layerId) => { // 文本
|
|
11
|
+
let {
|
|
12
|
+
map
|
|
13
|
+
} = mapSdk
|
|
14
|
+
|
|
15
|
+
let opt = option
|
|
16
|
+
let parentId = opt.id
|
|
17
|
+
let id = parentId + '-text'
|
|
18
|
+
if (hasLayer(id)) {
|
|
19
|
+
setSource(id, opt.data)
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
map.addLayer({
|
|
24
|
+
id: id,
|
|
25
|
+
type: 'symbol',
|
|
26
|
+
source: parentId,
|
|
27
|
+
layout: Object.assign({
|
|
28
|
+
'symbol-placement': placement,
|
|
29
|
+
'text-field': ['get', 'name'],
|
|
30
|
+
/* 使用text标签显示的值,Feature属性使用{域名}格式*/
|
|
31
|
+
'text-font': ['Open Sans Semibold'],
|
|
32
|
+
/* 文本字体 */
|
|
33
|
+
'text-size': 10,
|
|
34
|
+
'text-offset': [0, 0], // 该属性表示文本偏移锚点的距离,正值表示向右和向下,负值表示向左和向上
|
|
35
|
+
// 'text-anchor': 'top',
|
|
36
|
+
'text-ignore-placement': false, // 是否忽略文本位置
|
|
37
|
+
'visibility': 'visible'
|
|
38
|
+
}, opt.text.layout),
|
|
39
|
+
paint: Object.assign({
|
|
40
|
+
'text-color': '#ffffff',
|
|
41
|
+
'text-halo-color': 'rgba(0, 0, 0, .5)',
|
|
42
|
+
'text-halo-width': 0.8,
|
|
43
|
+
'text-opacity': 1
|
|
44
|
+
}, opt.text.paint)
|
|
45
|
+
}, layerId)
|
|
46
|
+
}
|