28 |
29 | All portals
30 |
31 |
32 | Visited portals
33 |
34 |
35 | Captured portals
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/static/index.js:
--------------------------------------------------------------------------------
1 | const vertexShaderSrc = `
2 | attribute vec2 position;
3 | uniform vec2 panning;
4 | uniform vec2 canvasSize;
5 | uniform float zoom;
6 | uniform vec4 color;
7 |
8 | varying vec4 vColor;
9 |
10 | void main() {
11 | float divideFactor = exp2(18.0 - zoom);
12 | vec2 xy = ((position - panning) / canvasSize / vec2(divideFactor)) - vec2(0.5);
13 | gl_Position = vec4(xy * vec2(2.0, -2.0), 0.0, 1.0);
14 | gl_PointSize = max(3.2, 0.00055 * pow(zoom, 3.5));
15 |
16 | vColor = color;
17 | }`;
18 |
19 | const fragmentShaderSrc = `
20 | precision mediump float;
21 |
22 | varying vec4 vColor;
23 |
24 | void main() {
25 | gl_FragColor = vColor;
26 | }`;
27 |
28 | var leafletMap;
29 | var customLayer;
30 | var gl;
31 | var appProgramInfo;
32 | var appProgramData;
33 | var data;
34 |
35 | class CustomLayer extends L.CanvasLayer {
36 |
37 | constructor() {
38 | super();
39 | this.supported = true;
40 | }
41 |
42 | initContext() {
43 | var canvas = this._canvas;
44 | gl = canvas.getContext('webgl');
45 | if (!gl) {
46 | this.supported = false;
47 | return false;
48 | }
49 | return true;
50 | }
51 |
52 | onLayerDidMount() {
53 | if (!gl && (!this.supported || !this.initContext()))
54 | return;
55 | if (!appProgramInfo) {
56 | // Create shaders and program
57 | var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSrc);
58 | var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSrc);
59 | var program = createProgram(gl, vertexShader, fragmentShader);
60 |
61 | appProgramInfo = {
62 | program: program,
63 | attribLocations: {
64 | position: gl.getAttribLocation(program, 'position'),
65 | },
66 | uniformLocations: {
67 | panning: gl.getUniformLocation(program, 'panning'),
68 | canvasSize: gl.getUniformLocation(program, 'canvasSize'),
69 | zoom: gl.getUniformLocation(program, 'zoom'),
70 | color: gl.getUniformLocation(program, 'color'),
71 | },
72 | };
73 |
74 | // Use program
75 | gl.useProgram(appProgramInfo.program);
76 |
77 | if (!data)
78 | return;
79 |
80 | // Crate data buffers
81 | appProgramData = {
82 | portalsBuffer: gl.createBuffer(),
83 | portalsSize: data.portals.length,
84 | drawPortals: true,
85 | visitsBuffer: gl.createBuffer(),
86 | visitsSize: data.visits.length,
87 | drawVisits: true,
88 | capturesBuffer: gl.createBuffer(),
89 | capturesSize: data.captures.length,
90 | drawCaptures: true,
91 | };
92 |
93 | // Bind data
94 | this.bindData();
95 | }
96 | }
97 |
98 | onLayerWillUnmount() {
99 | gl = undefined;
100 | appProgramInfo = undefined;
101 | appProgramData = undefined;
102 | }
103 |
104 | bindData() {
105 | var map = this._map;
106 | if (!appProgramData)
107 | return;
108 |
109 | function bindBuffer(buffer, bufferData) {
110 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
111 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(
112 | // Project LatLong data onto WebMercator canvas
113 | bufferData.map(x => map.project(L.latLng(x), 18)._round().toArray()).flat()
114 | ), gl.STATIC_DRAW);
115 | return buffer;
116 | }
117 |
118 | bindBuffer(appProgramData.portalsBuffer, data.portals);
119 | bindBuffer(appProgramData.visitsBuffer, data.visits);
120 | bindBuffer(appProgramData.capturesBuffer, data.captures);
121 | }
122 |
123 | onDrawLayer(_info) {
124 | var map = this._map;
125 | if (!appProgramInfo || !appProgramData)
126 | return;
127 |
128 | // Clear buffer
129 | gl.clear(gl.COLOR_BUFFER_BIT);
130 |
131 | // Fix canvas size
132 | this.resize();
133 |
134 | // Set map uniforms
135 | updateMapUniforms(map);
136 |
137 | function draw(buffer, size, color) {
138 | // Bind buffer to vertex shader attribute
139 | gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
140 | gl.vertexAttribPointer(appProgramInfo.attribLocations.position, 2, gl.FLOAT, false, 0, 0);
141 | gl.enableVertexAttribArray(appProgramInfo.attribLocations.position);
142 |
143 | // Set color uniform
144 | gl.uniform4fv(appProgramInfo.uniformLocations.color, color);
145 |
146 | // Draw!
147 | gl.drawArrays(gl.POINTS, 0, size);
148 | }
149 |
150 | if (appProgramData.portalsSize > 0 && appProgramData.drawPortals)
151 | draw(appProgramData.portalsBuffer, appProgramData.portalsSize, [0.72, 0.11, 0.11, 1.0]);
152 | if (appProgramData.drawVisits)
153 | draw(appProgramData.visitsBuffer, appProgramData.visitsSize, [1.0, 0.92, 0.23, 1.0]);
154 | if (appProgramData.drawCaptures)
155 | draw(appProgramData.capturesBuffer, appProgramData.capturesSize, [0.22, 0.56, 0.24, 1.0]);
156 | }
157 |
158 | _onLayerDidMove() {
159 | super._onLayerDidMove();
160 | }
161 |
162 | resize() {
163 | // Get current map size
164 | var size = this._map.getSize();
165 |
166 | if (gl.canvas.width != size.x || gl.canvas.height != size.y) {
167 | // Make the canvas the same size
168 | gl.canvas.width = size.x;
169 | gl.canvas.height = size.y;
170 |
171 | // Update viewport
172 | gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
173 | }
174 | }
175 | }
176 |
177 | function updateMapUniforms(map) {
178 | var origin = map.project(map.containerPointToLatLng([0, 0]), 18)._round().toArray();
179 | gl.uniform2fv(appProgramInfo.uniformLocations.canvasSize, map.getSize().toArray());
180 | gl.uniform2fv(appProgramInfo.uniformLocations.panning, origin);
181 | gl.uniform1f(appProgramInfo.uniformLocations.zoom, map._zoom);
182 | }
183 |
184 | // INIT
185 | leafletMap = L.map('map').setView([51.0, 10.2], 7);
186 | L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?{param}', { param: '' }).addTo(leafletMap);
187 |
188 | // Load data
189 | fetchJSON("/data.json", (result, error) => {
190 | if (result) {
191 | data = result;
192 |
193 | // Create and add WebGL layer
194 | customLayer = new CustomLayer();
195 | customLayer.addTo(leafletMap);
196 | } else if (error) {
197 | console.log(error);
198 | }
199 | });
200 |
201 | [...document.getElementsByClassName("line-item")].forEach(function (x) {
202 | x.addEventListener("click", function (e) {
203 | var classes = e.target.classList;
204 | var draw;
205 |
206 | if (draw = classes.contains("disabled"))
207 | classes.remove("disabled");
208 | else classes.add("disabled");
209 |
210 | if (classes.contains("all") && appProgramData) {
211 | appProgramData.drawPortals = draw;
212 | } else if (classes.contains("visited") && appProgramData) {
213 | appProgramData.drawVisits = draw;
214 | } else if (classes.contains("captured") && appProgramData) {
215 | appProgramData.drawCaptures = draw;
216 | }
217 |
218 | customLayer.onDrawLayer();
219 | })
220 | });
--------------------------------------------------------------------------------
/static/polyfills.js:
--------------------------------------------------------------------------------
1 | Object.defineProperty(Array.prototype, 'flat', {
2 | value: function (depth = 1) {
3 | return this.reduce(function (flat, toFlatten) {
4 | return flat.concat((Array.isArray(toFlatten) && (depth - 1)) ? toFlatten.flat(depth - 1) : toFlatten);
5 | }, []);
6 | }
7 | });
--------------------------------------------------------------------------------
/static/styles.css:
--------------------------------------------------------------------------------
1 | html, body, #map {
2 | margin: 0;
3 | padding: 0;
4 | height: 100%;
5 | }
6 |
7 | #controls {
8 | position: absolute;
9 | right: 0;
10 | bottom: 0;
11 | padding: 12px 0px 16px;
12 | max-width: 480px;
13 | background-color: white;
14 | z-index: 999;
15 | }
16 |
17 | .line-item {
18 | margin: 0;
19 | padding: 8px 0px;
20 | padding-left: 48px;
21 | padding-right: 16px;
22 | font-family: Roboto, Arial, Helvetica, sans-serif;
23 | user-select: none;
24 | }
25 |
26 | .line-item:hover {
27 | background-color: rgba(0, 0, 0, 0.04);
28 | }
29 |
30 | .line-item:active {
31 | background-color: rgba(0, 0, 0, 0.12);
32 | }
33 |
34 | .line-item > i.indicator {
35 | position: absolute;
36 | left: 16px;
37 | width: 1.2em;
38 | height: 1.2em;
39 | }
40 |
41 | .line-item.all > i.indicator {
42 | background-color: rgb(183.6, 28.05, 28.05);
43 | }
44 |
45 | .line-item.visited > i.indicator {
46 | background-color: rgb(255, 234.6, 58.65);
47 | }
48 |
49 | .line-item.captured > i.indicator {
50 | background-color: rgb(56.1, 142.8, 61.2);
51 | }
52 |
53 | .line-item.disabled > i.indicator {
54 | background-color: rgb(128, 128, 128);
55 | }
--------------------------------------------------------------------------------
/static/utils.js:
--------------------------------------------------------------------------------
1 | function fetchJSON(file, callback) {
2 | fetch(file)
3 | .then(response => response.json())
4 | .then(json => callback(json), null)
5 | .catch(error => callback(null, error))
6 | }
7 |
8 | function createProgram(gl, vertexShader, fragmentShader) {
9 | var program = gl.createProgram();
10 |
11 | gl.attachShader(program, vertexShader);
12 | gl.attachShader(program, fragmentShader);
13 |
14 | gl.linkProgram(program);
15 |
16 | if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
17 | alert('Unable to initialize the shader program: ' + gl.getProgramInfoLog(program));
18 | return null;
19 | }
20 | return program;
21 | }
22 |
23 | function createShader(gl, type, src) {
24 | var shader = gl.createShader(type);
25 | gl.shaderSource(shader, src);
26 | gl.compileShader(shader);
27 |
28 | if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
29 | alert('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader));
30 | gl.deleteShader(shader);
31 | return null;
32 | }
33 | return shader;
34 | }
35 |
36 | Object.defineProperty(L.Point.prototype, 'toArray', {
37 | value: function () {
38 | return [this.x, this.y];
39 | }
40 | });
--------------------------------------------------------------------------------
/translations/README_es.md:
--------------------------------------------------------------------------------
1 | ### Como pedir los datos
2 | Mandas un mail a `privacy@nianticlabs.com`:
3 |
4 | > Dear Sir or Madam,
5 | > I'd like to request a dump of the raw data Niantic stores about my Ingress account @