@naivemap/mapbox-gl-image-layer 0.5.0 → 0.6.0-beta.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.
Files changed (33) hide show
  1. package/dist/es/ImageLayer.js +232 -0
  2. package/dist/es/arrugator/Arrugator.js +270 -0
  3. package/dist/es/{utils/arrugator.js → arrugator/index.js} +43 -39
  4. package/dist/es/index.js +2 -228
  5. package/dist/es/shaders/image.fragment.glsl.js +1 -1
  6. package/dist/es/shaders/image.vertex.glsl.js +1 -1
  7. package/dist/es/shaders/mask.fragment.glsl.js +1 -1
  8. package/dist/es/shaders/mask.vertex.glsl.js +1 -1
  9. package/dist/js/ImageLayer.d.ts +62 -0
  10. package/dist/js/ImageLayer.js +270 -0
  11. package/dist/js/arrugator/Arrugator.d.ts +18 -0
  12. package/dist/js/arrugator/Arrugator.js +275 -0
  13. package/dist/js/arrugator/index.d.ts +7 -0
  14. package/dist/js/{utils/arrugator.js → arrugator/index.js} +49 -46
  15. package/dist/js/index.d.ts +4 -60
  16. package/dist/js/index.js +7 -256
  17. package/dist/js/shaders/image.fragment.glsl.d.ts +2 -2
  18. package/dist/js/shaders/image.fragment.glsl.js +3 -3
  19. package/dist/js/shaders/image.vertex.glsl.d.ts +2 -2
  20. package/dist/js/shaders/image.vertex.glsl.js +3 -3
  21. package/dist/js/shaders/mask.fragment.glsl.d.ts +2 -2
  22. package/dist/js/shaders/mask.fragment.glsl.js +3 -3
  23. package/dist/js/shaders/mask.vertex.glsl.d.ts +2 -2
  24. package/dist/js/shaders/mask.vertex.glsl.js +3 -3
  25. package/package.json +8 -9
  26. package/LICENSE +0 -21
  27. package/dist/es/utils/image.js +0 -19
  28. package/dist/es/utils/webgl.js +0 -64
  29. package/dist/js/utils/arrugator.d.ts +0 -7
  30. package/dist/js/utils/image.d.ts +0 -7
  31. package/dist/js/utils/image.js +0 -23
  32. package/dist/js/utils/webgl.d.ts +0 -8
  33. package/dist/js/utils/webgl.js +0 -68
package/dist/es/index.js CHANGED
@@ -1,228 +1,2 @@
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';
9
- import { initArrugator } from './utils/arrugator';
10
- var ImageLayer = /** @class */ (function () {
11
- function ImageLayer(id, option) {
12
- this.type = 'custom';
13
- this.renderingMode = '2d';
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
- }
26
- // 初始化 Arrugator
27
- var projection = option.projection, coordinates = option.coordinates;
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
36
- }
37
- ImageLayer.prototype.onAdd = function (map, gl) {
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
- }
55
- }
56
- };
57
- ImageLayer.prototype.onRemove = function (map, gl) {
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
- }
67
- };
68
- ImageLayer.prototype.render = function (gl, matrix) {
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) {
80
- // blend
81
- gl.enable(gl.BLEND);
82
- gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
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);
125
- }
126
- };
127
- /**
128
- * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
129
- * @param {Object} option Options object.
130
- * @param {string} [option.url] Image URL.
131
- * @param {string} [option.projection] Projection with EPSG code that points to the image..
132
- * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
133
- * @param {number} [option.opacity] opacity of the image.
134
- * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
135
- */
136
- ImageLayer.prototype.updateImage = function (option) {
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;
140
- if (option.projection || 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;
143
- // reinit arrugator
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();
160
- }
161
- }
162
- return this;
163
- };
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;
175
- };
176
- ImageLayer.prototype.loadTexture = function (map, gl) {
177
- var _this = this;
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;
187
- map.triggerRepaint();
188
- });
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
- };
226
- return ImageLayer;
227
- }());
228
- export default ImageLayer;
1
+ import ImageLayer from './ImageLayer';
2
+ export default ImageLayer;
@@ -1 +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";
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";
@@ -1 +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";
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";
@@ -1 +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";
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";
@@ -1 +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
+ 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";
@@ -0,0 +1,62 @@
1
+ import mapboxgl from 'mapbox-gl';
2
+ import type { Coordinates } from './arrugator';
3
+ export type MaskProperty = {
4
+ type?: 'in' | 'out';
5
+ data: GeoJSON.Polygon | GeoJSON.MultiPolygon;
6
+ };
7
+ export type ImageOption = {
8
+ url: string;
9
+ projection: string;
10
+ coordinates: Coordinates;
11
+ resampling?: 'linear' | 'nearest';
12
+ opacity?: number;
13
+ crossOrigin?: string;
14
+ arrugatorStep?: number;
15
+ mask?: MaskProperty;
16
+ metadata?: any;
17
+ };
18
+ export default class ImageLayer implements mapboxgl.CustomLayerInterface {
19
+ id: string;
20
+ type: 'custom';
21
+ renderingMode?: '2d' | '3d' | undefined;
22
+ metadata?: any;
23
+ private option;
24
+ private map?;
25
+ private gl?;
26
+ private loaded;
27
+ private arrugado;
28
+ private programInfo?;
29
+ private bufferInfo?;
30
+ private texture?;
31
+ private stencilChecked;
32
+ private maskProperty;
33
+ private maskProgramInfo?;
34
+ private maskBufferInfo?;
35
+ constructor(id: string, option: ImageOption);
36
+ onAdd(map: mapboxgl.Map, gl: WebGLRenderingContext): void;
37
+ onRemove(_: mapboxgl.Map, gl: WebGLRenderingContext): void;
38
+ render(gl: WebGLRenderingContext, matrix: number[]): void;
39
+ /**
40
+ * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
41
+ * @param {Object} option Options object.
42
+ * @param {string} [option.url] Image URL.
43
+ * @param {string} [option.projection] Projection with EPSG code that points to the image..
44
+ * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
45
+ * @param {number} [option.opacity] opacity of the image.
46
+ * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
47
+ */
48
+ updateImage(option: {
49
+ url?: string;
50
+ projection?: string;
51
+ coordinates?: Coordinates;
52
+ opacity?: number;
53
+ resampling?: 'linear' | 'nearest';
54
+ }): this;
55
+ /**
56
+ * Updates the mask property
57
+ * @param {MaskProperty} mask The mask property.
58
+ */
59
+ updateMask(mask: Partial<MaskProperty>): this;
60
+ private loadTexture;
61
+ private getMaskBufferInfo;
62
+ }
@@ -0,0 +1,270 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ var compare_versions_1 = require("compare-versions");
40
+ var earcut_1 = __importStar(require("earcut"));
41
+ var mapbox_gl_1 = __importDefault(require("mapbox-gl"));
42
+ var twgl = __importStar(require("twgl.js"));
43
+ var arrugator_1 = require("./arrugator");
44
+ var image_fragment_glsl_1 = __importDefault(require("./shaders/image.fragment.glsl"));
45
+ var image_vertex_glsl_1 = __importDefault(require("./shaders/image.vertex.glsl"));
46
+ var mask_fragment_glsl_1 = __importDefault(require("./shaders/mask.fragment.glsl"));
47
+ var mask_vertex_glsl_1 = __importDefault(require("./shaders/mask.vertex.glsl"));
48
+ var ImageLayer = /** @class */ (function () {
49
+ function ImageLayer(id, option) {
50
+ this.type = 'custom';
51
+ this.renderingMode = '2d';
52
+ // mask
53
+ this.stencilChecked = true; // resetStencilClippingMasks 版本检查
54
+ this.id = id;
55
+ this.option = option;
56
+ this.loaded = false;
57
+ this.maskProperty = Object.assign({ type: 'in' }, option.mask);
58
+ this.metadata = option.metadata;
59
+ // 检查 stencil 是否可用
60
+ this.stencilChecked = (0, compare_versions_1.satisfies)(mapbox_gl_1.default.version, '>=2.7.0');
61
+ // 如果传了 mask 边界数据,且版本不符
62
+ if (this.maskProperty.data && !this.stencilChecked) {
63
+ throw new Error("\u5982\u679C\u9700\u8981\u906E\u7F69\uFF08\u63A9\u819C\uFF09\uFF0Cmapbox-gl \u7248\u672C\u5FC5\u987B\uFF1A>=2.7.0");
64
+ }
65
+ // 初始化 Arrugator
66
+ var projection = option.projection, coordinates = option.coordinates;
67
+ this.arrugado = (0, arrugator_1.initArrugator)(projection, coordinates, option.arrugatorStep);
68
+ }
69
+ ImageLayer.prototype.onAdd = function (map, gl) {
70
+ this.map = map;
71
+ this.gl = gl;
72
+ // 主程序
73
+ this.programInfo = twgl.createProgramInfo(gl, [image_vertex_glsl_1.default, image_fragment_glsl_1.default]);
74
+ this.loadTexture(map, gl);
75
+ this.bufferInfo = twgl.createBufferInfoFromArrays(gl, {
76
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
77
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
78
+ indices: this.arrugado.trigs,
79
+ });
80
+ // 掩膜程序
81
+ if (this.maskProperty.data) {
82
+ var data = this.maskProperty.data;
83
+ if (data) {
84
+ this.maskProgramInfo = twgl.createProgramInfo(gl, [mask_vertex_glsl_1.default, mask_fragment_glsl_1.default]);
85
+ this.maskBufferInfo = this.getMaskBufferInfo(gl, data);
86
+ }
87
+ }
88
+ };
89
+ ImageLayer.prototype.onRemove = function (_, gl) {
90
+ if (this.programInfo) {
91
+ gl.deleteProgram(this.programInfo.program);
92
+ }
93
+ if (this.maskProgramInfo) {
94
+ gl.deleteProgram(this.maskProgramInfo.program);
95
+ }
96
+ if (this.texture) {
97
+ gl.deleteTexture(this.texture);
98
+ }
99
+ };
100
+ ImageLayer.prototype.render = function (gl, matrix) {
101
+ /**
102
+ * 线图层在启用 stencil 会消失,参考: https://github.com/mapbox/mapbox-gl-js/issues/12213
103
+ * 临时解决方案: map.painter.resetStencilClippingMasks()
104
+ * 该方法在 mapboxgl version >=2.7.0 才能用
105
+ */
106
+ var _a, _b;
107
+ if (this.stencilChecked) {
108
+ // @ts-ignore
109
+ this.map.painter.resetStencilClippingMasks();
110
+ }
111
+ if (this.loaded && this.programInfo && this.bufferInfo) {
112
+ // blend
113
+ gl.enable(gl.BLEND);
114
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
115
+ if (this.maskProgramInfo && this.maskBufferInfo) {
116
+ // mask program
117
+ gl.useProgram(this.maskProgramInfo.program);
118
+ // stencil test
119
+ gl.enable(gl.STENCIL_TEST);
120
+ gl.stencilFunc(gl.ALWAYS, 1, 0xff);
121
+ gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
122
+ gl.stencilMask(0xff);
123
+ gl.clear(gl.STENCIL_BUFFER_BIT);
124
+ // matrix
125
+ twgl.setUniforms(this.maskProgramInfo, { u_matrix: matrix });
126
+ // pos & indices
127
+ twgl.setBuffersAndAttributes(gl, this.maskProgramInfo, this.maskBufferInfo);
128
+ // draw
129
+ var elementType = gl.UNSIGNED_SHORT;
130
+ if (this.maskBufferInfo.numElements / 3 > 65535) {
131
+ // 使 drawElements 支持 UNSIGNED_INT 类型
132
+ gl.getExtension('OES_element_index_uint');
133
+ elementType = gl.UNSIGNED_INT;
134
+ }
135
+ gl.drawElements(gl.TRIANGLES, this.maskBufferInfo.numElements, elementType, 0);
136
+ }
137
+ // texture program
138
+ gl.useProgram(this.programInfo.program);
139
+ if ((_a = this.maskProgramInfo) === null || _a === void 0 ? void 0 : _a.program) {
140
+ // stencil test
141
+ var ref = this.maskProperty.type === 'out' ? 0 : 1;
142
+ gl.stencilFunc(gl.EQUAL, ref, 0xff);
143
+ gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
144
+ }
145
+ // uniforms
146
+ twgl.setUniforms(this.programInfo, {
147
+ u_matrix: matrix,
148
+ u_opacity: (_b = this.option.opacity) !== null && _b !== void 0 ? _b : 1,
149
+ u_sampler: this.texture,
150
+ });
151
+ // pos, uv & indices
152
+ twgl.setBuffersAndAttributes(gl, this.programInfo, this.bufferInfo);
153
+ // draw
154
+ gl.drawElements(gl.TRIANGLES, this.arrugado.trigs.length, gl.UNSIGNED_SHORT, 0);
155
+ gl.clear(gl.STENCIL_BUFFER_BIT);
156
+ gl.disable(gl.STENCIL_TEST);
157
+ }
158
+ };
159
+ /**
160
+ * Updates the URL, the projection, the coordinates, the opacity or the resampling of the image.
161
+ * @param {Object} option Options object.
162
+ * @param {string} [option.url] Image URL.
163
+ * @param {string} [option.projection] Projection with EPSG code that points to the image..
164
+ * @param {Array<Array<number>>} [option.coordinates] Four geographical coordinates,
165
+ * @param {number} [option.opacity] opacity of the image.
166
+ * @param {string} [option.resampling] The resampling/interpolation method to use for overscaling.
167
+ */
168
+ ImageLayer.prototype.updateImage = function (option) {
169
+ var _a, _b, _c, _d, _e;
170
+ if (this.gl && this.map) {
171
+ this.option.opacity = (_a = option.opacity) !== null && _a !== void 0 ? _a : this.option.opacity;
172
+ if (option.projection || option.coordinates) {
173
+ this.option.projection = (_b = option.projection) !== null && _b !== void 0 ? _b : this.option.projection;
174
+ this.option.coordinates = (_c = option.coordinates) !== null && _c !== void 0 ? _c : this.option.coordinates;
175
+ // reinit arrugator
176
+ this.arrugado = (0, arrugator_1.initArrugator)(this.option.projection, this.option.coordinates, this.option.arrugatorStep);
177
+ this.bufferInfo = twgl.createBufferInfoFromArrays(this.gl, {
178
+ a_pos: { numComponents: 2, data: this.arrugado.pos },
179
+ a_uv: { numComponents: 2, data: this.arrugado.uv },
180
+ indices: this.arrugado.trigs,
181
+ });
182
+ }
183
+ if (option.url || option.resampling) {
184
+ this.loaded = false;
185
+ this.option.url = (_d = option.url) !== null && _d !== void 0 ? _d : this.option.url;
186
+ this.option.resampling = (_e = option.resampling) !== null && _e !== void 0 ? _e : this.option.resampling;
187
+ // reload image
188
+ this.loadTexture(this.map, this.gl);
189
+ }
190
+ else {
191
+ this.map.triggerRepaint();
192
+ }
193
+ }
194
+ return this;
195
+ };
196
+ /**
197
+ * Updates the mask property
198
+ * @param {MaskProperty} mask The mask property.
199
+ */
200
+ ImageLayer.prototype.updateMask = function (mask) {
201
+ if (this.gl && this.map) {
202
+ if (mask.data) {
203
+ if (!this.maskProgramInfo) {
204
+ this.maskProgramInfo = twgl.createProgramInfo(this.gl, [mask_vertex_glsl_1.default, mask_fragment_glsl_1.default]);
205
+ }
206
+ this.maskProperty = Object.assign(this.maskProperty, mask);
207
+ this.maskBufferInfo = this.getMaskBufferInfo(this.gl, this.maskProperty.data);
208
+ }
209
+ else {
210
+ this.maskProgramInfo && this.gl.deleteProgram(this.maskProgramInfo.program);
211
+ this.maskProgramInfo = undefined;
212
+ this.maskBufferInfo = undefined;
213
+ }
214
+ this.map.triggerRepaint();
215
+ }
216
+ return this;
217
+ };
218
+ ImageLayer.prototype.loadTexture = function (map, gl) {
219
+ var _this = this;
220
+ // 创建纹理
221
+ var filter = this.option.resampling === 'nearest' ? gl.NEAREST : gl.LINEAR;
222
+ this.texture = twgl.createTexture(gl, {
223
+ src: this.option.url,
224
+ crossOrigin: this.option.crossOrigin,
225
+ minMag: filter,
226
+ flipY: 0,
227
+ }, function () {
228
+ _this.loaded = true;
229
+ map.triggerRepaint();
230
+ });
231
+ };
232
+ ImageLayer.prototype.getMaskBufferInfo = function (gl, data) {
233
+ var positions = [];
234
+ var triangles = [];
235
+ if (data.type === 'MultiPolygon') {
236
+ // type: 'MultiPolygon'
237
+ var polyCount = data.coordinates.length;
238
+ var triangleStartIndex_1 = 0;
239
+ for (var i = 0; i < polyCount; i++) {
240
+ var coordinates = data.coordinates[i];
241
+ var flattened = (0, earcut_1.flatten)(coordinates);
242
+ var vertices = flattened.vertices, holes = flattened.holes, dimensions = flattened.dimensions;
243
+ var triangle = (0, earcut_1.default)(vertices, holes, dimensions);
244
+ var triangleNew = triangle.map(function (item) { return item + triangleStartIndex_1; });
245
+ triangleStartIndex_1 += vertices.length / 2;
246
+ // positions.push(...vertices)
247
+ // triangles.push(...triangleNew)
248
+ for (var m = 0; m < vertices.length; m++) {
249
+ positions.push(vertices[m]);
250
+ }
251
+ for (var n = 0; n < triangleNew.length; n++) {
252
+ triangles.push(triangleNew[n]);
253
+ }
254
+ }
255
+ }
256
+ else {
257
+ // type: 'Polygon'
258
+ var flattened = (0, earcut_1.flatten)(data.coordinates);
259
+ var vertices = flattened.vertices, holes = flattened.holes, dimensions = flattened.dimensions;
260
+ positions = vertices;
261
+ triangles = (0, earcut_1.default)(vertices, holes, dimensions);
262
+ }
263
+ return twgl.createBufferInfoFromArrays(gl, {
264
+ a_pos: { numComponents: 2, data: positions },
265
+ indices: triangles.length / 3 > 65535 ? new Uint32Array(triangles) : new Uint16Array(triangles),
266
+ });
267
+ };
268
+ return ImageLayer;
269
+ }());
270
+ exports.default = ImageLayer;
@@ -0,0 +1,18 @@
1
+ export default class Arrugator {
2
+ constructor(projector: any, verts: any, uv: any, trigs: any);
3
+ _segment(v1: any, v2: any, t: any, maxEpsilon?: number): any;
4
+ output(): {
5
+ unprojected: unknown[];
6
+ projected: unknown[];
7
+ uv: unknown[];
8
+ trigs: unknown[];
9
+ };
10
+ private _stepsWithSameEpsilon;
11
+ lowerEpsilon(targetEpsilon: any): void;
12
+ get epsilon(): any;
13
+ set epsilon(ep: any);
14
+ step(): void;
15
+ force(): void;
16
+ private _splitSegment;
17
+ private _splitTriangle;
18
+ }