-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
Copy pathstyle_image.js
137 lines (126 loc) · 4.09 KB
/
style_image.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// @flow
import {RGBAImage} from '../util/image';
import type Map from '../ui/map';
export type StyleImageData = {
data: RGBAImage,
version: number,
hasRenderCallback?: boolean,
userImage?: StyleImageInterface
};
export type StyleImageMetadata = {
pixelRatio: number,
sdf: boolean,
stretchX?: Array<[number, number]>,
stretchY?: Array<[number, number]>,
content?: [number, number, number, number]
};
export type StyleImage = StyleImageData & StyleImageMetadata;
export type StyleImageInterface = {
width: number,
height: number,
data: Uint8Array | Uint8ClampedArray,
render?: () => void,
onAdd?: (map: Map, id: string) => void,
onRemove?: () => void
};
export function renderStyleImage(image: StyleImage) {
const {userImage} = image;
if (userImage && userImage.render) {
const updated = userImage.render();
if (updated) {
image.data.replace(new Uint8Array(userImage.data.buffer));
return true;
}
}
return false;
}
/**
* Interface for dynamically generated style images. This is a specification for
* implementers to model: it is not an exported method or class.
*
* Images implementing this interface can be redrawn for every frame. They can be used to animate
* icons and patterns or make them respond to user input. Style images can implement a
* {@link StyleImageInterface#render} method. The method is called every frame and
* can be used to update the image.
*
* @interface StyleImageInterface
* @property {number} width
* @property {number} height
* @property {Uint8Array | Uint8ClampedArray} data
*
* @see [Add an animated icon to the map.](https://docs.mapbox.com/mapbox-gl-js/example/add-image-animated/)
*
* @example
* var flashingSquare = {
* width: 64,
* height: 64,
* data: new Uint8Array(64 * 64 * 4),
*
* onAdd: function(map) {
* this.map = map;
* },
*
* render: function() {
* // keep repainting while the icon is on the map
* this.map.triggerRepaint();
*
* // alternate between black and white based on the time
* var value = Math.round(Date.now() / 1000) % 2 === 0 ? 255 : 0;
*
* // check if image needs to be changed
* if (value !== this.previousValue) {
* this.previousValue = value;
*
* var bytesPerPixel = 4;
* for (var x = 0; x < this.width; x++) {
* for (var y = 0; y < this.height; y++) {
* var offset = (y * this.width + x) * bytesPerPixel;
* this.data[offset + 0] = value;
* this.data[offset + 1] = value;
* this.data[offset + 2] = value;
* this.data[offset + 3] = 255;
* }
* }
*
* // return true to indicate that the image changed
* return true;
* }
* }
* }
*
* map.addImage('flashing_square', flashingSquare);
*/
/**
* This method is called once before every frame where the icon will be used.
* The method can optionally update the image's `data` member with a new image.
*
* If the method updates the image it must return `true` to commit the change.
* If the method returns `false` or nothing the image is assumed to not have changed.
*
* If updates are infrequent it maybe easier to use {@link Map#updateImage} to update
* the image instead of implementing this method.
*
* @function
* @memberof StyleImageInterface
* @instance
* @name render
* @return {boolean} `true` if this method updated the image. `false` if the image was not changed.
*/
/**
* Optional method called when the layer has been added to the Map with {@link Map#addImage}.
*
* @function
* @memberof StyleImageInterface
* @instance
* @name onAdd
* @param {Map} map The Map this custom layer was just added to.
*/
/**
* Optional method called when the icon is removed from the map with {@link Map#removeImage}.
* This gives the image a chance to clean up resources and event listeners.
*
* @function
* @memberof StyleImageInterface
* @instance
* @name onRemove
*/