@ohuoy/easymap 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,468 @@
1
+
2
+ import {hasProperty,transform} from '../../utils/util'
3
+ import mapboxgl from 'mapbox-gl';
4
+ export default class ScanLayer{
5
+ drawArray = []
6
+ defaultDrawInfo = {
7
+ id:'',
8
+ image:null,
9
+ coords:[],
10
+ refreshTime:null
11
+ }
12
+ opacity=0.7
13
+ //超时删除时间(秒)
14
+ outTime = 300
15
+ image;
16
+ positionRect;
17
+ gl;
18
+ renderBack = ()=>{}
19
+ textCtx=null;
20
+ textLayer;
21
+ timeLabels = {
22
+ 'type': 'FeatureCollection',
23
+ 'features':[]
24
+ }
25
+ constructor(id,_scanInfo) {
26
+ this.id = id;
27
+ this.type = 'custom';
28
+ this.renderingMode = '2d';
29
+ this.textCtx = document.createElement("canvas").getContext("2d");
30
+ if(_scanInfo){
31
+ this.drawList(_scanInfo)
32
+ }
33
+ this.timeClear()
34
+ }
35
+
36
+ // 将文字放在画布中间 创建文本纹理
37
+
38
+ makeTextCanvas(text,style) {
39
+ let _style = {
40
+ fontSize:16,
41
+ fontFamily:'',
42
+ textAlign:'center',
43
+ fillStyle:'#000',
44
+ strokeStyle:"#fff",
45
+ textBaseline:'middle',
46
+ lineWidth:3
47
+ }
48
+
49
+ let styleObj = Object.assign({},_style,style)
50
+ let padding = 2;
51
+ let width = styleObj.fontSize * text.length + padding * 2;
52
+ let height = styleObj.fontSize + padding * 2;
53
+
54
+ this.textCtx.canvas.width = width;
55
+ this.textCtx.canvas.height = height;
56
+ this.textCtx.font = `${styleObj.fontSize}px ${styleObj.fontFamily}`;
57
+ for(let i in styleObj){
58
+ if(i == 'fontSize' || i == 'fontFamily'){}
59
+ else{
60
+ this.textCtx[i] = styleObj[i]
61
+ }
62
+ }
63
+ this.textCtx.clearRect(0, 0, width, height);
64
+ this.textCtx.fillText(text, width / 2, height / 2);
65
+ return this.textCtx.canvas;
66
+ }
67
+ timeClear(){
68
+ setInterval(function(){
69
+ this.drawArray = this.drawArray.filter(a=>{
70
+ return (new Date().getTime() - a.refreshTime.getTime()) / 1000 < this.outTime
71
+ })
72
+ }.bind(this),1000)
73
+ }
74
+ // {
75
+ // id:'',
76
+ // image:''
77
+ // }
78
+ //添加图像object
79
+ drawList(_scanInfo){
80
+ let props = ['id','image','coords']
81
+ if(_scanInfo instanceof Array){
82
+ for(let _info of _scanInfo){
83
+ hasProperty(_info,props)
84
+ let currIndex = this.drawArray.findIndex(a=>a.id == _info.id)
85
+ _info.coords = _info.coords.map(a=>transform(a))
86
+ if(currIndex <0){
87
+ let entity = Object.assign({},this.defaultDrawInfo,_info)
88
+ entity.refreshTime = new Date();
89
+ this.drawArray.push(entity)
90
+ if(entity.text){
91
+ this.drawTextByLayer(entity)
92
+ }else{
93
+ this.removeText(entity)
94
+ }
95
+ }else{
96
+ let entity = Object.assign({},this.defaultDrawInfo,_info)
97
+ entity.refreshTime = new Date();
98
+ this.drawArray[currIndex] = entity
99
+ if(entity.text){
100
+ this.drawTextByLayer(entity)
101
+ }else{
102
+ this.removeText(entity)
103
+ }
104
+ }
105
+ }
106
+ }else{
107
+ hasProperty(_scanInfo,props)
108
+ _scanInfo.coords = _scanInfo.coords.map(a=>transform(a))
109
+ let currIndex = this.drawArray.findIndex(a=>a.id == _scanInfo.id)
110
+ if(currIndex <0){
111
+ let entity = Object.assign({},this.defaultDrawInfo,_scanInfo)
112
+ entity.refreshTime = new Date();
113
+ this.drawArray.push(entity)
114
+ if(entity.text){
115
+ this.drawTextByLayer(entity)
116
+ }else{
117
+ this.removeText(entity)
118
+ }
119
+ }else{
120
+ let entity = Object.assign({},this.defaultDrawInfo,_scanInfo)
121
+ entity.refreshTime = new Date();
122
+ this.drawArray[currIndex] = entity
123
+ if(entity.text){
124
+ this.drawTextByLayer(entity)
125
+ }else{
126
+ this.removeText(entity)
127
+ }
128
+ }
129
+ }
130
+ }
131
+
132
+ del(id){
133
+ this.drawArray = this.drawArray.filter(a=>a.id != id);
134
+ }
135
+
136
+ onAdd(map, gl) {
137
+ //两个着色器
138
+ // const vertexSource = `
139
+ // uniform mat4 u_matrix;
140
+ // void main() {
141
+ // gl_Position = u_matrix * vec4(0.5, 0.5, 0.0, 1.0);
142
+ // gl_PointSize = 20.0;
143
+ // }`;
144
+
145
+ // const fragmentSource = `
146
+ // void main() {
147
+ // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
148
+ // }`;
149
+
150
+ const vertexSource = `
151
+ uniform mat4 u_matrix;
152
+ attribute vec3 a_pos;
153
+ attribute vec2 a_uv;
154
+ varying vec2 v_uv;
155
+ void main() {
156
+ v_uv = a_uv;
157
+ gl_Position = u_matrix * vec4(a_pos, 1.0);
158
+ }
159
+ `;
160
+
161
+ const fragmentSource = `
162
+ precision mediump float;
163
+ uniform float opa;
164
+ varying vec2 v_uv;
165
+ uniform sampler2D u_sampler;
166
+ void main() {
167
+ gl_FragColor = texture2D(u_sampler , v_uv) * opa;
168
+ }
169
+ `;
170
+ const vertexShader = gl.createShader(gl.VERTEX_SHADER);
171
+ gl.shaderSource(vertexShader, vertexSource);
172
+ gl.compileShader(vertexShader);
173
+ const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
174
+ gl.shaderSource(fragmentShader, fragmentSource);
175
+ gl.compileShader(fragmentShader);
176
+
177
+ this.program = gl.createProgram();
178
+ gl.attachShader(this.program, vertexShader);
179
+ gl.attachShader(this.program, fragmentShader)
180
+ gl.linkProgram(this.program);
181
+ this.aPos = gl.getAttribLocation(this.program, 'a_pos')
182
+ this.aUv = gl.getAttribLocation(this.program, 'a_uv')
183
+ this.opa = gl.getAttribLocation(this.program, 'opa')
184
+ this.uSamplerLoc = gl.getUniformLocation(this.program, 'u_sampler')
185
+ this.gl = gl;
186
+ this.map = map;
187
+ //添加时间图层 消耗内存大 废弃
188
+ let timeTextLayer = this.map.getLayer('timeLabelLayer')
189
+ if(!this.map.getSource('timeLabels')){
190
+ this.map.addSource('timeLabels',{
191
+ 'type': 'geojson',
192
+ 'data':this.timeLabels,
193
+ 'dynamic':true
194
+ })
195
+ }
196
+ if(!timeTextLayer){
197
+ this.map.addLayer({
198
+ 'id': 'timeLabelLayer',
199
+ 'type': 'symbol',
200
+ 'source': 'timeLabels',
201
+ 'layout': {
202
+ 'text-field': ['get', 'label'],
203
+ //'text-anchor':'center',
204
+ 'text-size':18,
205
+ 'text-variable-anchor': ['top', 'bottom', 'left', 'right'],
206
+ //'text-radial-offset': 0.5,
207
+ 'text-justify': 'auto',
208
+ 'icon-image': ['get', 'icon'],
209
+ 'icon-anchor':'center',
210
+ 'icon-offset':['get', 'icon-offset'],
211
+ 'text-ignore-placement':true,
212
+ 'icon-ignore-placement':true
213
+ //'icon-text-fit':'width',
214
+ },
215
+ 'paint':{
216
+ 'text-color':['get', 'text-color'],
217
+ 'icon-color':'#0f3ad0',
218
+ 'text-halo-color':['get', 'text-border-color'],
219
+ 'text-halo-width':1
220
+ }
221
+ });
222
+ timeTextLayer = this.map.getLayer('timeLabelLayer')
223
+ }
224
+ }
225
+
226
+ draw(){
227
+ for(let i in this.drawArray) {
228
+ this.drawArrayItem(this.drawArray[i])
229
+ }
230
+ }
231
+
232
+ drawText(item){
233
+ let gl = this.gl;
234
+ let scale = 12
235
+ if(!item.textTextture){
236
+ item.textTextture = gl.createTexture()
237
+ }
238
+ let center = item.coords[3]//transform(item.center)
239
+ gl.bindTexture(gl.TEXTURE_2D,item.textTextture)
240
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
241
+ let textCanvas = this.makeTextCanvas(item.text?.label,item?.text?.textStyle)
242
+ if(!textCanvas){
243
+ return
244
+ }
245
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, textCanvas);
246
+ item.textBuffer = gl.createBuffer()
247
+ gl.bindBuffer(gl.ARRAY_BUFFER, item.textBuffer)
248
+ let p1 = mapboxgl.MercatorCoordinate.fromLngLat({
249
+ lng: center[0],
250
+ lat: center[1]
251
+ }, 10)
252
+ let p2 = mapboxgl.MercatorCoordinate.fromLngLat({
253
+ lng: center[0]+0.03 * scale,
254
+ lat: center[1]
255
+ }, 10)
256
+ let p3 = mapboxgl.MercatorCoordinate.fromLngLat({
257
+ lng: center[0]+0.03 * scale,
258
+ lat: center[1]+0.001 * scale
259
+ }, 10)
260
+ let p4 = mapboxgl.MercatorCoordinate.fromLngLat({
261
+ lng: center[0],
262
+ lat: center[1]+0.001 * scale
263
+ }, 10)
264
+ gl.bufferData(
265
+ gl.ARRAY_BUFFER,
266
+ new Float32Array([
267
+ // position, uv
268
+ p1.x, p1.y, p1.z, 0, 0,
269
+ p2.x, p2.y, p2.z, 1, 0,
270
+ p3.x, p3.y, p3.z, 1, 1,
271
+
272
+ p1.x, p1.y, p1.z, 0, 0,
273
+ p3.x, p3.y, p3.z, 1, 1,
274
+ p4.x, p4.y, p4.z, 0, 1,
275
+ ]),
276
+ gl.STATIC_DRAW
277
+ )
278
+ gl.bindTexture(gl.TEXTURE_2D, item.textTextture)
279
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
280
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
281
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
282
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
283
+
284
+ // 每帧都要绑定 VBO,并启用 vertexAttributes、设置 vertexAttributes 的参数
285
+ gl.bindBuffer(gl.ARRAY_BUFFER, item.textBuffer)
286
+ // gl.enableVertexAttribArray(this.aPos)
287
+ // gl.enableVertexAttribArray(this.aUv)
288
+ // gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 20, 0)
289
+ // gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, 20, 12)
290
+
291
+ gl.enable(gl.BLEND)
292
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
293
+
294
+ // 触发绘制
295
+ gl.enableVertexAttribArray(this.aPos)
296
+ gl.enableVertexAttribArray(this.aUv)
297
+ gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 20, 0)
298
+ gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, 20, 12)
299
+ gl.vertexAttrib1f(this.opa,1)
300
+ gl.drawArrays(gl.TRIANGLES, 0, 6)
301
+ }
302
+
303
+ //
304
+ drawTextByLayer(item){
305
+ let _itemIndex = this.timeLabels.features.findIndex(a=>a.properties.id == item.id)
306
+ if(_itemIndex < 0){
307
+ this.timeLabels.features.push({
308
+ 'type': 'Feature',
309
+ 'properties': {
310
+ 'id':item.id,
311
+ 'label':item.text.label,
312
+ 'text-color':item.text.color?item.text.color:'#0f3ad0',
313
+ 'text-border-color':item.text.borderColor?item.text.borderColor:'#fff'
314
+ },
315
+ 'geometry': {
316
+ 'type': 'Point',
317
+ 'coordinates': transform(item?.text?.coord)
318
+ }
319
+ })
320
+ }else{
321
+ this.timeLabels.features[_itemIndex] = {
322
+ 'type': 'Feature',
323
+ 'properties': {
324
+ 'id':item.id,
325
+ 'label':item.text.label,
326
+ 'text-color':item.text?.color?item.text?.color:'#0f3ad0',
327
+ 'text-border-color':item.text?.borderColor?item.text?.borderColor:'#fff'
328
+ },
329
+ 'geometry': {
330
+ 'type': 'Point',
331
+ 'coordinates': transform(item?.text?.coord)
332
+ }
333
+ }
334
+ }
335
+ }
336
+
337
+ removeText(item){
338
+ let _itemIndex = this.timeLabels.features.findIndex(a=>a.properties.id == item.id)
339
+ if(_itemIndex >=0){
340
+ this.timeLabels.features = this.timeLabels.features.filter(a=>a.properties.id != item.id)
341
+ }
342
+ }
343
+
344
+ drawArrayItem(item){
345
+ if(!item?.image){
346
+ return;
347
+ }
348
+ // if(!item?.text){
349
+ // this.removeText(item)
350
+ // }
351
+ // if(item?.text?.type == 'layer'){
352
+ // this.drawTextByLayer(item)
353
+ // }
354
+ // if(item?.text){
355
+ // this.drawText(item)
356
+ // }
357
+ let gl = this.gl;
358
+ if(!item.texture){
359
+ item.texture = gl.createTexture()
360
+ }
361
+
362
+ gl.bindTexture(gl.TEXTURE_2D,item.texture)
363
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true)
364
+ // 上载数据
365
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, item.image)
366
+ item.buffer = gl.createBuffer()
367
+ gl.bindBuffer(gl.ARRAY_BUFFER, item.buffer)
368
+ let p1 = mapboxgl.MercatorCoordinate.fromLngLat({
369
+ lng: item.coords[0][0],
370
+ lat: item.coords[0][1]
371
+ }, 10)
372
+ let p2 = mapboxgl.MercatorCoordinate.fromLngLat({
373
+ lng: item.coords[1][0],
374
+ lat: item.coords[1][1]
375
+ }, 10)
376
+ let p3 = mapboxgl.MercatorCoordinate.fromLngLat({
377
+ lng: item.coords[2][0],
378
+ lat: item.coords[2][1]
379
+ }, 10)
380
+ let p4 = mapboxgl.MercatorCoordinate.fromLngLat({
381
+ lng: item.coords[3][0],
382
+ lat: item.coords[3][1]
383
+ }, 10)
384
+ gl.bufferData(
385
+ gl.ARRAY_BUFFER,
386
+ new Float32Array([
387
+ // position, uv
388
+ p1.x, p1.y, p1.z, 0, 0,
389
+ p2.x, p2.y, p2.z, 1, 0,
390
+ p3.x, p3.y, p3.z, 1, 1,
391
+
392
+ p1.x, p1.y, p1.z, 0, 0,
393
+ p3.x, p3.y, p3.z, 1, 1,
394
+ p4.x, p4.y, p4.z, 0, 1,
395
+ ]),
396
+ gl.STATIC_DRAW
397
+ )
398
+ gl.bindTexture(gl.TEXTURE_2D, item.texture)
399
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
400
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
401
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
402
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
403
+
404
+ // 每帧都要绑定 VBO,并启用 vertexAttributes、设置 vertexAttributes 的参数
405
+ gl.bindBuffer(gl.ARRAY_BUFFER, item.buffer)
406
+ // gl.enableVertexAttribArray(this.aPos)
407
+ // gl.enableVertexAttribArray(this.aUv)
408
+ // gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 20, 0)
409
+ // gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, 20, 12)
410
+
411
+ gl.enable(gl.BLEND)
412
+ gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
413
+
414
+ // 触发绘制
415
+ gl.enableVertexAttribArray(this.aPos)
416
+ gl.enableVertexAttribArray(this.aUv)
417
+ gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 20, 0)
418
+ gl.vertexAttribPointer(this.aUv, 2, gl.FLOAT, false, 20, 12)
419
+ gl.vertexAttrib1f(this.opa,0.7)
420
+ gl.drawArrays(gl.TRIANGLES, 0, 6)
421
+ }
422
+
423
+ render(gl, matrix) {
424
+ if(this.drawArray.length == 0) return;
425
+ gl.useProgram(this.program)
426
+ // 每帧都要传递 uniform
427
+ gl.uniformMatrix4fv(
428
+ gl.getUniformLocation(this.program, 'u_matrix'),
429
+ false,
430
+ matrix
431
+ )
432
+ gl.uniform1f(gl.getUniformLocation(this.program, 'opa'),this.opacity)
433
+ this.map.getSource('timeLabels').setData(this.timeLabels)
434
+ this.draw()
435
+
436
+ // gl.useProgram(this.program)
437
+ // // 每帧都要传递 uniform
438
+ // gl.uniformMatrix4fv(
439
+ // gl.getUniformLocation(this.program, 'u_matrix'),
440
+ // false,
441
+ // matrix
442
+ // )
443
+ // // 每帧都要绑定纹理参数
444
+ // gl.bindTexture(gl.TEXTURE_2D, this.texture)
445
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
446
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
447
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST)
448
+ // gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST)
449
+
450
+ // // 每帧都要绑定 VBO,并启用 vertexAttributes、设置 vertexAttributes 的参数
451
+ // gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer)
452
+
453
+
454
+ // 如果你用不着透明度,可以不执行这两行
455
+ // gl.enable(gl.BLEND)
456
+ // gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
457
+
458
+ // 触发绘制
459
+ //gl.drawArrays(gl.TRIANGLES, 0, 6)
460
+ // 每帧都要指定用哪个着色器程序
461
+ if(this.renderBack!=null) {
462
+ if(this.renderBack) this.renderBack()
463
+ }
464
+ //this.map.triggerRepaint();
465
+ }
466
+ }
467
+
468
+