@naivemap/mapbox-gl-image-layer 0.4.2 → 0.5.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/README.md CHANGED
@@ -31,14 +31,26 @@ export default class ImageLayer implements mapboxgl.CustomLayerInterface
31
31
  | **option.coordinates** <br />(`Array<Array<number>>`) | Corners of image specified in longitude, latitude pairs: top left, top right, bottom right, bottom left. ref: [coordinates](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#image-coordinates) |
32
32
  | **option.resampling** <br />(Optional `enum`. One of `"linear"`, `"nearest"`. Defaults to `"linear"`) | The resampling/interpolation method to use for overscaling, also known as texture magnification filter. ref: [raster-resampling](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#paint-raster-raster-resampling) |
33
33
  | **option.opacity** <br />(Optional `number` between 0 and 1 inclusive. Defaults to 1. | The opacity at which the image will be drawn. |
34
- | **options.crossOrigin** <br />(`string`) | The crossOrigin attribute is a string which specifies the Cross-Origin Resource Sharing ([CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS)) setting to use when retrieving the image. |
34
+ | **option.crossOrigin** <br />(`string`) | The crossOrigin attribute is a string which specifies the Cross-Origin Resource Sharing ([CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS)) setting to use when retrieving the image. |
35
+ | **option.mask** <br />(`MaskProperty`) | The polygonal mask or multipolygonal mask for the image. |
35
36
 
36
37
  ```ts
37
38
  export type ImageOption = {
38
39
  url: string
39
40
  projection: string
40
41
  coordinates: Coordinates
41
- resampling: 'linear' | 'nearest'
42
+ resampling?: 'linear' | 'nearest'
43
+ opacity?: number
44
+ crossOrigin?: string
45
+ mask?: MaskProperty
46
+ }
47
+
48
+ // top left, top right, bottom right, bottom left.
49
+ export type Coordinates = [[number, number], [number, number], [number, number], [number, number]]
50
+
51
+ export type MaskProperty = {
52
+ type?: 'in' | 'out' // default: in
53
+ data: GeoJSON.Polygon | GeoJSON.MultiPolygon
42
54
  }
43
55
  ```
44
56
 
@@ -46,17 +58,26 @@ export type ImageOption = {
46
58
 
47
59
  #### updateImage
48
60
 
49
- Updates the image URL and, optionally, the projection, the coordinates and the resampling.
61
+ Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
50
62
 
51
63
  ```ts
52
64
  updateImage(option: {
53
- url: string
65
+ url?: string
54
66
  projection?: string
55
67
  coordinates?: Coordinates
68
+ opacity?: number
56
69
  resampling?: 'linear' | 'nearest'
57
70
  }): this
58
71
  ```
59
72
 
73
+ #### updateMask
74
+
75
+ Updates the mask property.
76
+
77
+ ```ts
78
+ updateMask(mask: Partial<MaskProperty>): this
79
+ ```
80
+
60
81
  ## Example
61
82
 
62
83
  ```ts
package/dist/es/index.js CHANGED
@@ -1,132 +1,228 @@
1
- import { loadImage } from './utils/image';
2
- import { createProgram } from './utils/webgl';
1
+ import { satisfies } from 'compare-versions';
2
+ import earcut from 'earcut';
3
+ import mapboxgl from 'mapbox-gl';
4
+ import * as twgl from 'twgl.js';
5
+ import fs from './shaders/image.fragment.glsl';
6
+ import vs from './shaders/image.vertex.glsl';
7
+ import maskfs from './shaders/mask.fragment.glsl';
8
+ import maskvs from './shaders/mask.vertex.glsl';
3
9
  import { initArrugator } from './utils/arrugator';
4
10
  var ImageLayer = /** @class */ (function () {
5
11
  function ImageLayer(id, option) {
6
- this.id = id;
7
12
  this.type = 'custom';
8
13
  this.renderingMode = '2d';
9
- this._option = option;
10
- this._loaded = false;
14
+ // mask
15
+ this.stencilChecked = true; // resetStencilClippingMasks 版本检查
16
+ this.id = id;
17
+ this.option = option;
18
+ this.loaded = false;
19
+ this.maskProperty = Object.assign({ type: 'in' }, option.mask);
20
+ // 检查 stencil 是否可用
21
+ this.stencilChecked = satisfies(mapboxgl.version, '>=2.7.0');
22
+ // 如果传了 mask 边界数据,且版本不符
23
+ if (this.maskProperty.data && !this.stencilChecked) {
24
+ throw new Error("\u5982\u679C\u9700\u8981\u906E\u7F69\uFF08\u63A9\u819C\uFF09\uFF0Cmapbox-gl \u7248\u672C\u5FC5\u987B\uFF1A>=2.7.0");
25
+ }
11
26
  // 初始化 Arrugator
12
27
  var projection = option.projection, coordinates = option.coordinates;
13
- this._arrugado = initArrugator(projection, coordinates);
14
- this._map = null;
15
- this._gl = null;
16
- this._program = null;
17
- this._texture = null;
18
- this._positionBuffer = null;
19
- this._uvBuffer = null;
20
- this._verticesIndexBuffer = null;
28
+ this.arrugado = initArrugator(projection, coordinates);
29
+ // this._map = null
30
+ // this._gl = null
31
+ // this._program = null
32
+ // this._texture = null
33
+ // this._positionBuffer = null
34
+ // this._uvBuffer = null
35
+ // this._verticesIndexBuffer = null
21
36
  }
22
37
  ImageLayer.prototype.onAdd = function (map, gl) {
23
- this._map = map;
24
- this._gl = gl;
25
- this._loadImage(map, gl);
26
- var vertexSource = "\n uniform mat4 u_matrix;\n attribute vec2 a_pos;\n attribute vec2 a_uv;\n varying vec2 v_uv;\n void main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n }";
27
- var fragmentSource = "\n #ifdef GL_ES\n precision highp int;\n precision mediump float;\n #endif\n uniform sampler2D u_sampler;\n uniform float u_opacity;\n varying vec2 v_uv;\n void main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n }";
28
- this._program = createProgram(gl, vertexSource, fragmentSource);
29
- if (this._program) {
30
- this._positionBuffer = gl.createBuffer();
31
- // gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer)
32
- // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.pos), gl.STATIC_DRAW)
33
- var a_pos = gl.getAttribLocation(this._program, 'a_pos');
34
- gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
35
- gl.enableVertexAttribArray(a_pos);
36
- this._uvBuffer = gl.createBuffer();
37
- // gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer)
38
- // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.uv), gl.STATIC_DRAW)
39
- var a_uv = gl.getAttribLocation(this._program, 'a_uv');
40
- gl.vertexAttribPointer(a_uv, 2, gl.FLOAT, false, 0, 0);
41
- gl.enableVertexAttribArray(a_uv);
42
- this._verticesIndexBuffer = gl.createBuffer();
43
- // gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer)
44
- // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this._arrugado.trigs), gl.STATIC_DRAW)
45
- this._bindData(gl, this._arrugado);
38
+ this.map = map;
39
+ this.gl = gl;
40
+ // 主程序
41
+ this.programInfo = twgl.createProgramInfo(gl, [vs, fs]);
42
+ this.loadTexture(map, gl);
43
+ this.bufferInfo = twgl.createBufferInfoFromArrays(gl, {
44
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
45
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
46
+ indices: this.arrugado.trigs,
47
+ });
48
+ // 掩膜程序
49
+ if (this.maskProperty.data) {
50
+ var data = this.maskProperty.data;
51
+ if (data) {
52
+ this.maskProgramInfo = twgl.createProgramInfo(gl, [maskvs, maskfs]);
53
+ this.maskBufferInfo = this.getMaskBufferInfo(gl, data);
54
+ }
46
55
  }
47
56
  };
48
57
  ImageLayer.prototype.onRemove = function (map, gl) {
49
- gl.deleteProgram(this._program);
50
- gl.deleteTexture(this._texture);
51
- gl.deleteBuffer(this._verticesIndexBuffer);
58
+ if (this.programInfo) {
59
+ gl.deleteProgram(this.programInfo.program);
60
+ }
61
+ if (this.maskProgramInfo) {
62
+ gl.deleteProgram(this.maskProgramInfo.program);
63
+ }
64
+ if (this.texture) {
65
+ gl.deleteTexture(this.texture);
66
+ }
52
67
  };
53
68
  ImageLayer.prototype.render = function (gl, matrix) {
54
- if (this._loaded && this._program) {
55
- gl.useProgram(this._program);
56
- // matrix
57
- gl.uniformMatrix4fv(gl.getUniformLocation(this._program, 'u_matrix'), false, matrix);
58
- // pos
59
- gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
60
- gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_pos'), 2, gl.FLOAT, false, 0, 0);
61
- // uv
62
- gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
63
- gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_uv'), 2, gl.FLOAT, false, 0, 0);
64
- // index
65
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
66
- // texture
67
- gl.activeTexture(gl.TEXTURE0);
68
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
69
- gl.uniform1i(gl.getUniformLocation(this._program, 'u_sampler'), 0);
70
- // opacity
71
- gl.uniform1f(gl.getUniformLocation(this._program, 'u_opacity'), this._option.opacity || 1);
69
+ /**
70
+ * 线图层在启用 stencil 会消失,参考: https://github.com/mapbox/mapbox-gl-js/issues/12213
71
+ * 临时解决方案: map.painter.resetStencilClippingMasks()
72
+ * 该方法在 mapboxgl version >=2.7.0 才能用
73
+ */
74
+ var _a;
75
+ if (this.stencilChecked) {
76
+ // @ts-ignore
77
+ this.map.painter.resetStencilClippingMasks();
78
+ }
79
+ if (this.loaded && this.programInfo && this.bufferInfo) {
72
80
  // blend
73
81
  gl.enable(gl.BLEND);
74
82
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
75
- gl.drawElements(gl.TRIANGLES, this._arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
76
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
77
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
83
+ if (this.maskProgramInfo && this.maskBufferInfo) {
84
+ // mask program
85
+ gl.useProgram(this.maskProgramInfo.program);
86
+ // stencil test
87
+ gl.enable(gl.STENCIL_TEST);
88
+ gl.stencilFunc(gl.ALWAYS, 1, 0xff);
89
+ gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
90
+ gl.stencilMask(0xff);
91
+ gl.clear(gl.STENCIL_BUFFER_BIT);
92
+ // matrix
93
+ twgl.setUniforms(this.maskProgramInfo, { u_matrix: matrix });
94
+ // pos & indices
95
+ twgl.setBuffersAndAttributes(gl, this.maskProgramInfo, this.maskBufferInfo);
96
+ // draw
97
+ var elementType = gl.UNSIGNED_SHORT;
98
+ if (this.maskBufferInfo.numElements / 3 > 65535) {
99
+ // 使 drawElements 支持 UNSIGNED_INT 类型
100
+ gl.getExtension('OES_element_index_uint');
101
+ elementType = gl.UNSIGNED_INT;
102
+ }
103
+ gl.drawElements(gl.TRIANGLES, this.maskBufferInfo.numElements, elementType, 0);
104
+ }
105
+ // texture program
106
+ gl.useProgram(this.programInfo.program);
107
+ if ((_a = this.maskProgramInfo) === null || _a === void 0 ? void 0 : _a.program) {
108
+ // stencil test
109
+ var ref = this.maskProperty.type === 'out' ? 0 : 1;
110
+ gl.stencilFunc(gl.EQUAL, ref, 0xff);
111
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
112
+ }
113
+ // uniforms
114
+ twgl.setUniforms(this.programInfo, {
115
+ u_matrix: matrix,
116
+ u_opacity: this.option.opacity || 1,
117
+ u_sampler: this.texture,
118
+ });
119
+ // pos, uv & indices
120
+ twgl.setBuffersAndAttributes(gl, this.programInfo, this.bufferInfo);
121
+ // draw
122
+ gl.drawElements(gl.TRIANGLES, this.arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
123
+ gl.clear(gl.STENCIL_BUFFER_BIT);
124
+ gl.disable(gl.STENCIL_TEST);
78
125
  }
79
126
  };
80
127
  /**
81
- * Updates the image URL and, optionally, the projection, the coordinates and the resampling.
128
+ * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
82
129
  * @param {Object} option Options object.
83
- * @param {string} [option.url] Required image URL.
130
+ * @param {string} [option.url] Image URL.
84
131
  * @param {string} [option.projection] Projection with EPSG code that points to the image..
85
132
  * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
133
+ * @param {number} [option.opacity] opacity of the image.
86
134
  * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
87
135
  */
88
136
  ImageLayer.prototype.updateImage = function (option) {
89
- var _a, _b, _c;
90
- this._loaded = false;
91
- this._option.url = option.url;
92
- if (this._gl && this._map) {
137
+ var _a, _b, _c, _d, _e;
138
+ if (this.gl && this.map) {
139
+ this.option.opacity = (_a = option.opacity) !== null && _a !== void 0 ? _a : this.option.opacity;
93
140
  if (option.projection || option.coordinates) {
94
- this._option.projection = (_a = option.projection) !== null && _a !== void 0 ? _a : this._option.projection;
95
- this._option.coordinates = (_b = option.coordinates) !== null && _b !== void 0 ? _b : this._option.coordinates;
141
+ this.option.projection = (_b = option.projection) !== null && _b !== void 0 ? _b : this.option.projection;
142
+ this.option.coordinates = (_c = option.coordinates) !== null && _c !== void 0 ? _c : this.option.coordinates;
96
143
  // reinit arrugator
97
- this._arrugado = initArrugator(this._option.projection, this._option.coordinates);
98
- this._bindData(this._gl, this._arrugado);
144
+ this.arrugado = initArrugator(this.option.projection, this.option.coordinates);
145
+ this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, {
146
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
147
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
148
+ indices: this.arrugado.trigs,
149
+ });
150
+ }
151
+ if (option.url || option.resampling) {
152
+ this.loaded = false;
153
+ this.option.url = (_d = option.url) !== null && _d !== void 0 ? _d : this.option.url;
154
+ this.option.resampling = (_e = option.resampling) !== null && _e !== void 0 ? _e : this.option.resampling;
155
+ // reload image
156
+ this.loadTexture(this.map, this.gl);
157
+ }
158
+ else {
159
+ this.map.triggerRepaint();
99
160
  }
100
- this._option.resampling = (_c = option.resampling) !== null && _c !== void 0 ? _c : this._option.resampling;
101
- // reload image
102
- this._loadImage(this._map, this._gl);
103
161
  }
104
162
  return this;
105
163
  };
106
- ImageLayer.prototype._bindData = function (gl, arrugado) {
107
- gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
108
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.pos), gl.STATIC_DRAW);
109
- gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
110
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.uv), gl.STATIC_DRAW);
111
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
112
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(arrugado.trigs), gl.STATIC_DRAW);
164
+ /**
165
+ * Updates the mask property
166
+ * @param {MaskProperty} mask The mask property.
167
+ */
168
+ ImageLayer.prototype.updateMask = function (mask) {
169
+ if (this.gl && this.map && this.maskProgramInfo) {
170
+ this.maskProperty = Object.assign(this.maskProperty, mask);
171
+ this.maskBufferInfo = this.getMaskBufferInfo(this.gl, this.maskProperty.data);
172
+ this.map.triggerRepaint();
173
+ }
174
+ return this;
113
175
  };
114
- ImageLayer.prototype._loadImage = function (map, gl) {
176
+ ImageLayer.prototype.loadTexture = function (map, gl) {
115
177
  var _this = this;
116
- loadImage(this._option.url, this._option.crossOrigin).then(function (img) {
117
- _this._loaded = true;
118
- // 创建纹理
119
- _this._texture = gl.createTexture();
120
- gl.bindTexture(gl.TEXTURE_2D, _this._texture);
121
- var textureFilter = _this._option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
122
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureFilter);
123
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureFilter);
124
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
125
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
126
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
178
+ // 创建纹理
179
+ var filter = this.option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
180
+ this.texture = twgl.createTexture(gl, {
181
+ src: this.option.url,
182
+ crossOrigin: this.option.crossOrigin,
183
+ minMag: filter,
184
+ flipY: 0,
185
+ }, function () {
186
+ _this.loaded = true;
127
187
  map.triggerRepaint();
128
188
  });
129
189
  };
190
+ ImageLayer.prototype.getMaskBufferInfo = function (gl, data) {
191
+ var positions = [];
192
+ var triangles = [];
193
+ if (data.type === 'MultiPolygon') {
194
+ // type: 'MultiPolygon'
195
+ var polyCount = data.coordinates.length;
196
+ var triangleStartIndex_1 = 0;
197
+ for (var i = 0; i < polyCount; i++) {
198
+ var coordinates = data.coordinates[i];
199
+ var flatten = earcut.flatten(coordinates);
200
+ var vertices = flatten.vertices, holes = flatten.holes, dimensions = flatten.dimensions;
201
+ var triangle = earcut(vertices, holes, dimensions);
202
+ var triangleNew = triangle.map(function (item) { return item + triangleStartIndex_1; });
203
+ triangleStartIndex_1 += vertices.length / 2;
204
+ // positions.push(...vertices)
205
+ // triangles.push(...triangleNew)
206
+ for (var m = 0; m < vertices.length; m++) {
207
+ positions.push(vertices[m]);
208
+ }
209
+ for (var n = 0; n < triangleNew.length; n++) {
210
+ triangles.push(triangleNew[n]);
211
+ }
212
+ }
213
+ }
214
+ else {
215
+ // type: 'Polygon'
216
+ var flatten = earcut.flatten(data.coordinates);
217
+ var vertices = flatten.vertices, holes = flatten.holes, dimensions = flatten.dimensions;
218
+ positions = vertices;
219
+ triangles = earcut(vertices, holes, dimensions);
220
+ }
221
+ return twgl.createBufferInfoFromArrays(gl, {
222
+ a_pos: { numComponents: 2, data: positions },
223
+ indices: triangles.length / 3 > 65535 ? new Uint32Array(triangles) : new Uint16Array(triangles),
224
+ });
225
+ };
130
226
  return ImageLayer;
131
227
  }());
132
228
  export default ImageLayer;
@@ -0,0 +1 @@
1
+ export default "\n#ifdef GL_ES\n precision highp int;\n precision mediump float;\n#endif\nuniform sampler2D u_sampler;\nuniform float u_opacity;\nvarying vec2 v_uv;\nvoid main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n}\n";
@@ -0,0 +1 @@
1
+ export default "\nuniform mat4 u_matrix;\nattribute vec2 a_pos;\nattribute vec2 a_uv;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n}\n";
@@ -0,0 +1 @@
1
+ export default "\n#ifdef GL_ES\nprecision highp int;\nprecision mediump float;\n#endif\n\nvoid main() {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n}\n";
@@ -0,0 +1 @@
1
+ export default "\nuniform mat4 u_matrix;\nuniform float u_alt;\nattribute vec2 a_pos;\n\nconst float PI = 3.1415926536;\nconst float earthRadius = 6371008.8;\nconst float earthCircumference = 2.0 * PI * earthRadius; // meters\n\nfloat circumferenceAtLatitude(float latitude) {\n return earthCircumference * cos(latitude * PI / 180.0);\n}\n\nfloat mercatorXfromLng(float lng) {\n return (180.0 + lng) / 360.0;\n}\n\nfloat mercatorYfromLat(float lat) {\n return (180.0 - (180.0 / PI * log(tan(PI / 4.0 + lat * PI / 360.0)))) / 360.0;\n}\n\nfloat mercatorZfromAltitude(float altitude, float lat) {\n return altitude / circumferenceAtLatitude(lat);\n}\n\nvec3 mercatorfromLngLat(vec2 lnglat, float alt) {\n return vec3(mercatorXfromLng(lnglat.x), mercatorYfromLat(lnglat.y), mercatorZfromAltitude(alt, lnglat.y));\n}\n\nvoid main() {\n vec3 mercator = mercatorfromLngLat(a_pos, 0.0);\n gl_Position = u_matrix * vec4(mercator, 1.0);\n // gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n}\n";
@@ -1,5 +1,10 @@
1
- /// <reference types="mapbox-gl" />
1
+ import mapboxgl from 'mapbox-gl';
2
2
  import type { Coordinates } from './utils/arrugator';
3
+ export type { Coordinates } from './utils/arrugator';
4
+ export declare type MaskProperty = {
5
+ type?: 'in' | 'out';
6
+ data: GeoJSON.Polygon | GeoJSON.MultiPolygon;
7
+ };
3
8
  export declare type ImageOption = {
4
9
  url: string;
5
10
  projection: string;
@@ -7,39 +12,49 @@ export declare type ImageOption = {
7
12
  resampling?: 'linear' | 'nearest';
8
13
  opacity?: number;
9
14
  crossOrigin?: string;
15
+ mask?: MaskProperty;
10
16
  };
11
17
  export default class ImageLayer implements mapboxgl.CustomLayerInterface {
12
18
  id: string;
13
19
  type: 'custom';
14
20
  renderingMode?: '2d' | '3d' | undefined;
15
- private _option;
16
- private _loaded;
17
- private _arrugado;
18
- private _map;
19
- private _gl;
20
- private _program;
21
- private _texture;
22
- private _positionBuffer;
23
- private _uvBuffer;
24
- private _verticesIndexBuffer;
21
+ private option;
22
+ private map?;
23
+ private gl?;
24
+ private loaded;
25
+ private arrugado;
26
+ private programInfo?;
27
+ private bufferInfo?;
28
+ private texture?;
29
+ private stencilChecked;
30
+ private maskProperty;
31
+ private maskProgramInfo?;
32
+ private maskBufferInfo?;
25
33
  constructor(id: string, option: ImageOption);
26
34
  onAdd(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
27
35
  onRemove(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
28
36
  render(gl: WebGLRenderingContext, matrix: number[]): void;
29
37
  /**
30
- * Updates the image URL and, optionally, the projection, the coordinates and the resampling.
38
+ * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
31
39
  * @param {Object} option Options object.
32
- * @param {string} [option.url] Required image URL.
40
+ * @param {string} [option.url] Image URL.
33
41
  * @param {string} [option.projection] Projection with EPSG code that points to the image..
34
42
  * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
43
+ * @param {number} [option.opacity] opacity of the image.
35
44
  * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
36
45
  */
37
46
  updateImage(option: {
38
- url: string;
47
+ url?: string;
39
48
  projection?: string;
40
49
  coordinates?: Coordinates;
50
+ opacity?: number;
41
51
  resampling?: 'linear' | 'nearest';
42
52
  }): this;
43
- private _bindData;
44
- private _loadImage;
53
+ /**
54
+ * Updates the mask property
55
+ * @param {MaskProperty} mask The mask property.
56
+ */
57
+ updateMask(mask: Partial<MaskProperty>): this;
58
+ private loadTexture;
59
+ private getMaskBufferInfo;
45
60
  }
package/dist/js/index.js CHANGED
@@ -1,134 +1,256 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
2
28
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var image_1 = require("./utils/image");
4
- var webgl_1 = require("./utils/webgl");
29
+ var compare_versions_1 = require("compare-versions");
30
+ var earcut_1 = __importDefault(require("earcut"));
31
+ var mapbox_gl_1 = __importDefault(require("mapbox-gl"));
32
+ var twgl = __importStar(require("twgl.js"));
33
+ var image_fragment_glsl_1 = __importDefault(require("./shaders/image.fragment.glsl"));
34
+ var image_vertex_glsl_1 = __importDefault(require("./shaders/image.vertex.glsl"));
35
+ var mask_fragment_glsl_1 = __importDefault(require("./shaders/mask.fragment.glsl"));
36
+ var mask_vertex_glsl_1 = __importDefault(require("./shaders/mask.vertex.glsl"));
5
37
  var arrugator_1 = require("./utils/arrugator");
6
38
  var ImageLayer = /** @class */ (function () {
7
39
  function ImageLayer(id, option) {
8
- this.id = id;
9
40
  this.type = 'custom';
10
41
  this.renderingMode = '2d';
11
- this._option = option;
12
- this._loaded = false;
42
+ // mask
43
+ this.stencilChecked = true; // resetStencilClippingMasks 版本检查
44
+ this.id = id;
45
+ this.option = option;
46
+ this.loaded = false;
47
+ this.maskProperty = Object.assign({ type: 'in' }, option.mask);
48
+ // 检查 stencil 是否可用
49
+ this.stencilChecked = (0, compare_versions_1.satisfies)(mapbox_gl_1.default.version, '>=2.7.0');
50
+ // 如果传了 mask 边界数据,且版本不符
51
+ if (this.maskProperty.data && !this.stencilChecked) {
52
+ throw new Error("\u5982\u679C\u9700\u8981\u906E\u7F69\uFF08\u63A9\u819C\uFF09\uFF0Cmapbox-gl \u7248\u672C\u5FC5\u987B\uFF1A>=2.7.0");
53
+ }
13
54
  // 初始化 Arrugator
14
55
  var projection = option.projection, coordinates = option.coordinates;
15
- this._arrugado = (0, arrugator_1.initArrugator)(projection, coordinates);
16
- this._map = null;
17
- this._gl = null;
18
- this._program = null;
19
- this._texture = null;
20
- this._positionBuffer = null;
21
- this._uvBuffer = null;
22
- this._verticesIndexBuffer = null;
56
+ this.arrugado = (0, arrugator_1.initArrugator)(projection, coordinates);
57
+ // this._map = null
58
+ // this._gl = null
59
+ // this._program = null
60
+ // this._texture = null
61
+ // this._positionBuffer = null
62
+ // this._uvBuffer = null
63
+ // this._verticesIndexBuffer = null
23
64
  }
24
65
  ImageLayer.prototype.onAdd = function (map, gl) {
25
- this._map = map;
26
- this._gl = gl;
27
- this._loadImage(map, gl);
28
- var vertexSource = "\n uniform mat4 u_matrix;\n attribute vec2 a_pos;\n attribute vec2 a_uv;\n varying vec2 v_uv;\n void main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n }";
29
- var fragmentSource = "\n #ifdef GL_ES\n precision highp int;\n precision mediump float;\n #endif\n uniform sampler2D u_sampler;\n uniform float u_opacity;\n varying vec2 v_uv;\n void main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n }";
30
- this._program = (0, webgl_1.createProgram)(gl, vertexSource, fragmentSource);
31
- if (this._program) {
32
- this._positionBuffer = gl.createBuffer();
33
- // gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer)
34
- // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.pos), gl.STATIC_DRAW)
35
- var a_pos = gl.getAttribLocation(this._program, 'a_pos');
36
- gl.vertexAttribPointer(a_pos, 2, gl.FLOAT, false, 0, 0);
37
- gl.enableVertexAttribArray(a_pos);
38
- this._uvBuffer = gl.createBuffer();
39
- // gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer)
40
- // gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this._arrugado.uv), gl.STATIC_DRAW)
41
- var a_uv = gl.getAttribLocation(this._program, 'a_uv');
42
- gl.vertexAttribPointer(a_uv, 2, gl.FLOAT, false, 0, 0);
43
- gl.enableVertexAttribArray(a_uv);
44
- this._verticesIndexBuffer = gl.createBuffer();
45
- // gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer)
46
- // gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this._arrugado.trigs), gl.STATIC_DRAW)
47
- this._bindData(gl, this._arrugado);
66
+ this.map = map;
67
+ this.gl = gl;
68
+ // 主程序
69
+ this.programInfo = twgl.createProgramInfo(gl, [image_vertex_glsl_1.default, image_fragment_glsl_1.default]);
70
+ this.loadTexture(map, gl);
71
+ this.bufferInfo = twgl.createBufferInfoFromArrays(gl, {
72
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
73
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
74
+ indices: this.arrugado.trigs,
75
+ });
76
+ // 掩膜程序
77
+ if (this.maskProperty.data) {
78
+ var data = this.maskProperty.data;
79
+ if (data) {
80
+ this.maskProgramInfo = twgl.createProgramInfo(gl, [mask_vertex_glsl_1.default, mask_fragment_glsl_1.default]);
81
+ this.maskBufferInfo = this.getMaskBufferInfo(gl, data);
82
+ }
48
83
  }
49
84
  };
50
85
  ImageLayer.prototype.onRemove = function (map, gl) {
51
- gl.deleteProgram(this._program);
52
- gl.deleteTexture(this._texture);
53
- gl.deleteBuffer(this._verticesIndexBuffer);
86
+ if (this.programInfo) {
87
+ gl.deleteProgram(this.programInfo.program);
88
+ }
89
+ if (this.maskProgramInfo) {
90
+ gl.deleteProgram(this.maskProgramInfo.program);
91
+ }
92
+ if (this.texture) {
93
+ gl.deleteTexture(this.texture);
94
+ }
54
95
  };
55
96
  ImageLayer.prototype.render = function (gl, matrix) {
56
- if (this._loaded && this._program) {
57
- gl.useProgram(this._program);
58
- // matrix
59
- gl.uniformMatrix4fv(gl.getUniformLocation(this._program, 'u_matrix'), false, matrix);
60
- // pos
61
- gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
62
- gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_pos'), 2, gl.FLOAT, false, 0, 0);
63
- // uv
64
- gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
65
- gl.vertexAttribPointer(gl.getAttribLocation(this._program, 'a_uv'), 2, gl.FLOAT, false, 0, 0);
66
- // index
67
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
68
- // texture
69
- gl.activeTexture(gl.TEXTURE0);
70
- gl.bindTexture(gl.TEXTURE_2D, this._texture);
71
- gl.uniform1i(gl.getUniformLocation(this._program, 'u_sampler'), 0);
72
- // opacity
73
- gl.uniform1f(gl.getUniformLocation(this._program, 'u_opacity'), this._option.opacity || 1);
97
+ /**
98
+ * 线图层在启用 stencil 会消失,参考: https://github.com/mapbox/mapbox-gl-js/issues/12213
99
+ * 临时解决方案: map.painter.resetStencilClippingMasks()
100
+ * 该方法在 mapboxgl version >=2.7.0 才能用
101
+ */
102
+ var _a;
103
+ if (this.stencilChecked) {
104
+ // @ts-ignore
105
+ this.map.painter.resetStencilClippingMasks();
106
+ }
107
+ if (this.loaded && this.programInfo && this.bufferInfo) {
74
108
  // blend
75
109
  gl.enable(gl.BLEND);
76
110
  gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
77
- gl.drawElements(gl.TRIANGLES, this._arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
78
- gl.bindBuffer(gl.ARRAY_BUFFER, null);
79
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
111
+ if (this.maskProgramInfo && this.maskBufferInfo) {
112
+ // mask program
113
+ gl.useProgram(this.maskProgramInfo.program);
114
+ // stencil test
115
+ gl.enable(gl.STENCIL_TEST);
116
+ gl.stencilFunc(gl.ALWAYS, 1, 0xff);
117
+ gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
118
+ gl.stencilMask(0xff);
119
+ gl.clear(gl.STENCIL_BUFFER_BIT);
120
+ // matrix
121
+ twgl.setUniforms(this.maskProgramInfo, { u_matrix: matrix });
122
+ // pos & indices
123
+ twgl.setBuffersAndAttributes(gl, this.maskProgramInfo, this.maskBufferInfo);
124
+ // draw
125
+ var elementType = gl.UNSIGNED_SHORT;
126
+ if (this.maskBufferInfo.numElements / 3 > 65535) {
127
+ // 使 drawElements 支持 UNSIGNED_INT 类型
128
+ gl.getExtension('OES_element_index_uint');
129
+ elementType = gl.UNSIGNED_INT;
130
+ }
131
+ gl.drawElements(gl.TRIANGLES, this.maskBufferInfo.numElements, elementType, 0);
132
+ }
133
+ // texture program
134
+ gl.useProgram(this.programInfo.program);
135
+ if ((_a = this.maskProgramInfo) === null || _a === void 0 ? void 0 : _a.program) {
136
+ // stencil test
137
+ var ref = this.maskProperty.type === 'out' ? 0 : 1;
138
+ gl.stencilFunc(gl.EQUAL, ref, 0xff);
139
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
140
+ }
141
+ // uniforms
142
+ twgl.setUniforms(this.programInfo, {
143
+ u_matrix: matrix,
144
+ u_opacity: this.option.opacity || 1,
145
+ u_sampler: this.texture,
146
+ });
147
+ // pos, uv & indices
148
+ twgl.setBuffersAndAttributes(gl, this.programInfo, this.bufferInfo);
149
+ // draw
150
+ gl.drawElements(gl.TRIANGLES, this.arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
151
+ gl.clear(gl.STENCIL_BUFFER_BIT);
152
+ gl.disable(gl.STENCIL_TEST);
80
153
  }
81
154
  };
82
155
  /**
83
- * Updates the image URL and, optionally, the projection, the coordinates and the resampling.
156
+ * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
84
157
  * @param {Object} option Options object.
85
- * @param {string} [option.url] Required image URL.
158
+ * @param {string} [option.url] Image URL.
86
159
  * @param {string} [option.projection] Projection with EPSG code that points to the image..
87
160
  * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
161
+ * @param {number} [option.opacity] opacity of the image.
88
162
  * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
89
163
  */
90
164
  ImageLayer.prototype.updateImage = function (option) {
91
- var _a, _b, _c;
92
- this._loaded = false;
93
- this._option.url = option.url;
94
- if (this._gl && this._map) {
165
+ var _a, _b, _c, _d, _e;
166
+ if (this.gl && this.map) {
167
+ this.option.opacity = (_a = option.opacity) !== null && _a !== void 0 ? _a : this.option.opacity;
95
168
  if (option.projection || option.coordinates) {
96
- this._option.projection = (_a = option.projection) !== null && _a !== void 0 ? _a : this._option.projection;
97
- this._option.coordinates = (_b = option.coordinates) !== null && _b !== void 0 ? _b : this._option.coordinates;
169
+ this.option.projection = (_b = option.projection) !== null && _b !== void 0 ? _b : this.option.projection;
170
+ this.option.coordinates = (_c = option.coordinates) !== null && _c !== void 0 ? _c : this.option.coordinates;
98
171
  // reinit arrugator
99
- this._arrugado = (0, arrugator_1.initArrugator)(this._option.projection, this._option.coordinates);
100
- this._bindData(this._gl, this._arrugado);
172
+ this.arrugado = (0, arrugator_1.initArrugator)(this.option.projection, this.option.coordinates);
173
+ this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, {
174
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
175
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
176
+ indices: this.arrugado.trigs,
177
+ });
178
+ }
179
+ if (option.url || option.resampling) {
180
+ this.loaded = false;
181
+ this.option.url = (_d = option.url) !== null && _d !== void 0 ? _d : this.option.url;
182
+ this.option.resampling = (_e = option.resampling) !== null && _e !== void 0 ? _e : this.option.resampling;
183
+ // reload image
184
+ this.loadTexture(this.map, this.gl);
185
+ }
186
+ else {
187
+ this.map.triggerRepaint();
101
188
  }
102
- this._option.resampling = (_c = option.resampling) !== null && _c !== void 0 ? _c : this._option.resampling;
103
- // reload image
104
- this._loadImage(this._map, this._gl);
105
189
  }
106
190
  return this;
107
191
  };
108
- ImageLayer.prototype._bindData = function (gl, arrugado) {
109
- gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
110
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.pos), gl.STATIC_DRAW);
111
- gl.bindBuffer(gl.ARRAY_BUFFER, this._uvBuffer);
112
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(arrugado.uv), gl.STATIC_DRAW);
113
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this._verticesIndexBuffer);
114
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(arrugado.trigs), gl.STATIC_DRAW);
192
+ /**
193
+ * Updates the mask property
194
+ * @param {MaskProperty} mask The mask property.
195
+ */
196
+ ImageLayer.prototype.updateMask = function (mask) {
197
+ if (this.gl && this.map && this.maskProgramInfo) {
198
+ this.maskProperty = Object.assign(this.maskProperty, mask);
199
+ this.maskBufferInfo = this.getMaskBufferInfo(this.gl, this.maskProperty.data);
200
+ this.map.triggerRepaint();
201
+ }
202
+ return this;
115
203
  };
116
- ImageLayer.prototype._loadImage = function (map, gl) {
204
+ ImageLayer.prototype.loadTexture = function (map, gl) {
117
205
  var _this = this;
118
- (0, image_1.loadImage)(this._option.url, this._option.crossOrigin).then(function (img) {
119
- _this._loaded = true;
120
- // 创建纹理
121
- _this._texture = gl.createTexture();
122
- gl.bindTexture(gl.TEXTURE_2D, _this._texture);
123
- var textureFilter = _this._option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
124
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, textureFilter);
125
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, textureFilter);
126
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
127
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
128
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
206
+ // 创建纹理
207
+ var filter = this.option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
208
+ this.texture = twgl.createTexture(gl, {
209
+ src: this.option.url,
210
+ crossOrigin: this.option.crossOrigin,
211
+ minMag: filter,
212
+ flipY: 0,
213
+ }, function () {
214
+ _this.loaded = true;
129
215
  map.triggerRepaint();
130
216
  });
131
217
  };
218
+ ImageLayer.prototype.getMaskBufferInfo = function (gl, data) {
219
+ var positions = [];
220
+ var triangles = [];
221
+ if (data.type === 'MultiPolygon') {
222
+ // type: 'MultiPolygon'
223
+ var polyCount = data.coordinates.length;
224
+ var triangleStartIndex_1 = 0;
225
+ for (var i = 0; i < polyCount; i++) {
226
+ var coordinates = data.coordinates[i];
227
+ var flatten = earcut_1.default.flatten(coordinates);
228
+ var vertices = flatten.vertices, holes = flatten.holes, dimensions = flatten.dimensions;
229
+ var triangle = (0, earcut_1.default)(vertices, holes, dimensions);
230
+ var triangleNew = triangle.map(function (item) { return item + triangleStartIndex_1; });
231
+ triangleStartIndex_1 += vertices.length / 2;
232
+ // positions.push(...vertices)
233
+ // triangles.push(...triangleNew)
234
+ for (var m = 0; m < vertices.length; m++) {
235
+ positions.push(vertices[m]);
236
+ }
237
+ for (var n = 0; n < triangleNew.length; n++) {
238
+ triangles.push(triangleNew[n]);
239
+ }
240
+ }
241
+ }
242
+ else {
243
+ // type: 'Polygon'
244
+ var flatten = earcut_1.default.flatten(data.coordinates);
245
+ var vertices = flatten.vertices, holes = flatten.holes, dimensions = flatten.dimensions;
246
+ positions = vertices;
247
+ triangles = (0, earcut_1.default)(vertices, holes, dimensions);
248
+ }
249
+ return twgl.createBufferInfoFromArrays(gl, {
250
+ a_pos: { numComponents: 2, data: positions },
251
+ indices: triangles.length / 3 > 65535 ? new Uint32Array(triangles) : new Uint16Array(triangles),
252
+ });
253
+ };
132
254
  return ImageLayer;
133
255
  }());
134
256
  exports.default = ImageLayer;
@@ -0,0 +1,2 @@
1
+ declare const _default: "\n#ifdef GL_ES\n precision highp int;\n precision mediump float;\n#endif\nuniform sampler2D u_sampler;\nuniform float u_opacity;\nvarying vec2 v_uv;\nvoid main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n}\n";
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "\n#ifdef GL_ES\n precision highp int;\n precision mediump float;\n#endif\nuniform sampler2D u_sampler;\nuniform float u_opacity;\nvarying vec2 v_uv;\nvoid main() {\n vec4 color = texture2D(u_sampler, v_uv);\n gl_FragColor = color * u_opacity;\n}\n";
@@ -0,0 +1,2 @@
1
+ declare const _default: "\nuniform mat4 u_matrix;\nattribute vec2 a_pos;\nattribute vec2 a_uv;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n}\n";
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "\nuniform mat4 u_matrix;\nattribute vec2 a_pos;\nattribute vec2 a_uv;\nvarying vec2 v_uv;\nvoid main() {\n gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n v_uv = a_uv;\n}\n";
@@ -0,0 +1,2 @@
1
+ declare const _default: "\n#ifdef GL_ES\nprecision highp int;\nprecision mediump float;\n#endif\n\nvoid main() {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n}\n";
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "\n#ifdef GL_ES\nprecision highp int;\nprecision mediump float;\n#endif\n\nvoid main() {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n}\n";
@@ -0,0 +1,2 @@
1
+ declare const _default: "\nuniform mat4 u_matrix;\nuniform float u_alt;\nattribute vec2 a_pos;\n\nconst float PI = 3.1415926536;\nconst float earthRadius = 6371008.8;\nconst float earthCircumference = 2.0 * PI * earthRadius; // meters\n\nfloat circumferenceAtLatitude(float latitude) {\n return earthCircumference * cos(latitude * PI / 180.0);\n}\n\nfloat mercatorXfromLng(float lng) {\n return (180.0 + lng) / 360.0;\n}\n\nfloat mercatorYfromLat(float lat) {\n return (180.0 - (180.0 / PI * log(tan(PI / 4.0 + lat * PI / 360.0)))) / 360.0;\n}\n\nfloat mercatorZfromAltitude(float altitude, float lat) {\n return altitude / circumferenceAtLatitude(lat);\n}\n\nvec3 mercatorfromLngLat(vec2 lnglat, float alt) {\n return vec3(mercatorXfromLng(lnglat.x), mercatorYfromLat(lnglat.y), mercatorZfromAltitude(alt, lnglat.y));\n}\n\nvoid main() {\n vec3 mercator = mercatorfromLngLat(a_pos, 0.0);\n gl_Position = u_matrix * vec4(mercator, 1.0);\n // gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n}\n";
2
+ export default _default;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = "\nuniform mat4 u_matrix;\nuniform float u_alt;\nattribute vec2 a_pos;\n\nconst float PI = 3.1415926536;\nconst float earthRadius = 6371008.8;\nconst float earthCircumference = 2.0 * PI * earthRadius; // meters\n\nfloat circumferenceAtLatitude(float latitude) {\n return earthCircumference * cos(latitude * PI / 180.0);\n}\n\nfloat mercatorXfromLng(float lng) {\n return (180.0 + lng) / 360.0;\n}\n\nfloat mercatorYfromLat(float lat) {\n return (180.0 - (180.0 / PI * log(tan(PI / 4.0 + lat * PI / 360.0)))) / 360.0;\n}\n\nfloat mercatorZfromAltitude(float altitude, float lat) {\n return altitude / circumferenceAtLatitude(lat);\n}\n\nvec3 mercatorfromLngLat(vec2 lnglat, float alt) {\n return vec3(mercatorXfromLng(lnglat.x), mercatorYfromLat(lnglat.y), mercatorZfromAltitude(alt, lnglat.y));\n}\n\nvoid main() {\n vec3 mercator = mercatorfromLngLat(a_pos, 0.0);\n gl_Position = u_matrix * vec4(mercator, 1.0);\n // gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);\n}\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naivemap/mapbox-gl-image-layer",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "Load a static image of any projection via Arrugator and Proj4js.",
5
5
  "author": "huanglii <li.huangli@qq.com>",
6
6
  "homepage": "https://github.com/naivemap/mapbox-gl-layers#readme",
@@ -45,13 +45,17 @@
45
45
  "proj4": "^2.8.0"
46
46
  },
47
47
  "dependencies": {
48
- "arrugator": "^1.0.1"
48
+ "arrugator": "^1.0.1",
49
+ "compare-versions": "^6.0.0-rc.1",
50
+ "earcut": "^2.2.4",
51
+ "twgl.js": "^5.3.1"
49
52
  },
50
53
  "devDependencies": {
54
+ "@types/earcut": "^2.1.1",
51
55
  "@types/mapbox-gl": "^2.7.2",
52
56
  "@types/node": "^17.0.36",
53
57
  "@types/proj4": "^2.5.2",
54
58
  "npm-run-all": "^4.1.5"
55
59
  },
56
- "gitHead": "5fc47667682399fe76c56d6808a44098bbd46636"
60
+ "gitHead": "3a2fa3bab4a8e676df592ea4f674fbf9b9e9b221"
57
61
  }