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.
@@ -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
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
+ }
@@ -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
+ }