gridviz 3.0.39 → 3.0.41
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/dist/gridviz.js +78 -4
- package/dist/gridviz.min.js +1 -1
- package/package.json +1 -1
- package/src/core/Map.js +5 -1
- package/src/dataset/TiledGrid.js +62 -0
- package/src/layer/GridLayer.js +10 -2
package/package.json
CHANGED
package/src/core/Map.js
CHANGED
|
@@ -245,7 +245,11 @@ export class Map {
|
|
|
245
245
|
//remove legend elements: the legends themselves only, not what is inside them
|
|
246
246
|
//(a legend keeps its content while one of its swatches is hovered, see Style.updateLegends)
|
|
247
247
|
//except the one being hovered, which would lose its mouseleave (see Legend.highlight)
|
|
248
|
-
if (this.legend)
|
|
248
|
+
if (this.legend) {
|
|
249
|
+
this.legend.selectAll(':scope > *:not([data-gridviz-hovered])').remove()
|
|
250
|
+
// the legends of this draw are placed one after the other (see GridLayer.addLegends)
|
|
251
|
+
this.legend.node()._gridvizLegendCursor = null
|
|
252
|
+
}
|
|
249
253
|
|
|
250
254
|
//clear
|
|
251
255
|
this.geoCanvas.initCanvasTransform()
|
package/src/dataset/TiledGrid.js
CHANGED
|
@@ -10,6 +10,17 @@ import { Dataset } from '../core/Dataset.js'
|
|
|
10
10
|
// external
|
|
11
11
|
import { json, csv } from 'd3-fetch'
|
|
12
12
|
|
|
13
|
+
// The tiles that are loaded are kept, so that going back to a place needs no new request. They are kept as lists of cell objects, which
|
|
14
|
+
// take a lot of memory (the education grid of the Statistical Atlas reached 1.5 GB after some minutes of panning and zooming), so the
|
|
15
|
+
// number of cells kept by all the TiledGrid together is limited (TiledGrid.maxCachedCells): when there are more, the tiles that were used
|
|
16
|
+
// the longest time ago are dropped, and loaded again if the map needs them. The tiles of the view on the screen, and those used in the
|
|
17
|
+
// last KEEP_MS ms, are never dropped.
|
|
18
|
+
const KEEP_MS = 3000
|
|
19
|
+
/** All the tiles kept, of every dataset. */
|
|
20
|
+
const keptTiles = new Set()
|
|
21
|
+
let keptCells = 0
|
|
22
|
+
const now = () => (typeof performance !== 'undefined' ? performance.now() : Date.now())
|
|
23
|
+
|
|
13
24
|
/**
|
|
14
25
|
* A tiled dataset, composed of CSV tiles.
|
|
15
26
|
*
|
|
@@ -152,6 +163,8 @@ export class TiledGrid extends Dataset {
|
|
|
152
163
|
|
|
153
164
|
// Skip already loaded tiles or retry failed ones
|
|
154
165
|
if (this.cache[xT][yT] && this.cache[xT][yT] !== 'failed') {
|
|
166
|
+
// in the view: not to be dropped
|
|
167
|
+
if (typeof this.cache[xT][yT] === 'object') this.cache[xT][yT].lastUsed = now()
|
|
155
168
|
++processedTiles
|
|
156
169
|
continue
|
|
157
170
|
}
|
|
@@ -163,6 +176,7 @@ export class TiledGrid extends Dataset {
|
|
|
163
176
|
this.loadTile(xT, yT, signal)
|
|
164
177
|
.then((tile) => {
|
|
165
178
|
this.cache[xT][yT] = tile
|
|
179
|
+
this._keep(tile)
|
|
166
180
|
|
|
167
181
|
// Check if this is the last tile
|
|
168
182
|
const isLastTile = ++processedTiles === totalTiles
|
|
@@ -235,6 +249,45 @@ export class TiledGrid extends Dataset {
|
|
|
235
249
|
}
|
|
236
250
|
}
|
|
237
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Counts a tile that was loaded in the cells kept, and drops the tiles used the longest time ago when there are too many.
|
|
254
|
+
*
|
|
255
|
+
* @param {any} tile
|
|
256
|
+
* @private
|
|
257
|
+
*/
|
|
258
|
+
_keep(tile) {
|
|
259
|
+
// a failed tile is the string 'failed', not a tile
|
|
260
|
+
if (!tile || typeof tile !== 'object' || !tile.cells) return
|
|
261
|
+
tile.lastUsed = now()
|
|
262
|
+
tile.owner = this
|
|
263
|
+
keptTiles.add(tile)
|
|
264
|
+
keptCells += tile.cells.length
|
|
265
|
+
if (keptCells <= TiledGrid.maxCachedCells) return
|
|
266
|
+
const limit = now() - KEEP_MS
|
|
267
|
+
const unused = [...keptTiles].filter((t) => t.lastUsed < limit).sort((a, b) => a.lastUsed - b.lastUsed)
|
|
268
|
+
for (const t of unused) {
|
|
269
|
+
if (keptCells <= TiledGrid.maxCachedCells) break
|
|
270
|
+
t.owner._drop(t)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Forgets a tile: it is loaded again when the map needs it.
|
|
276
|
+
*
|
|
277
|
+
* @param {any} tile
|
|
278
|
+
* @private
|
|
279
|
+
*/
|
|
280
|
+
_drop(tile) {
|
|
281
|
+
const column = this.cache[tile.x]
|
|
282
|
+
if (column && column[tile.y] === tile) {
|
|
283
|
+
delete column[tile.y]
|
|
284
|
+
if (!Object.keys(column).length) delete this.cache[tile.x]
|
|
285
|
+
}
|
|
286
|
+
if (keptTiles.delete(tile)) keptCells -= tile.cells.length
|
|
287
|
+
tile.owner = undefined
|
|
288
|
+
tile.cells = []
|
|
289
|
+
}
|
|
290
|
+
|
|
238
291
|
/**
|
|
239
292
|
* Fill the view cache with all cells which are within a geographical envelope.
|
|
240
293
|
* @abstract
|
|
@@ -264,6 +317,7 @@ export class TiledGrid extends Dataset {
|
|
|
264
317
|
/** @type {object} */
|
|
265
318
|
const tile = this.cache[xT][yT]
|
|
266
319
|
if (!tile || typeof tile === 'string') continue
|
|
320
|
+
tile.lastUsed = now()
|
|
267
321
|
|
|
268
322
|
//get cells
|
|
269
323
|
//this.cellsViewCache = this.cellsViewCache.concat(tile.cells)
|
|
@@ -280,6 +334,14 @@ export class TiledGrid extends Dataset {
|
|
|
280
334
|
}
|
|
281
335
|
}
|
|
282
336
|
|
|
337
|
+
/**
|
|
338
|
+
* The most cells kept in memory by the tiles of all the TiledGrid together (a cell is an object of the values of a place, some hundred
|
|
339
|
+
* bytes: about 250 MB for a million). It can be changed at any time.
|
|
340
|
+
*
|
|
341
|
+
* @type {number}
|
|
342
|
+
*/
|
|
343
|
+
TiledGrid.maxCachedCells = 1500000
|
|
344
|
+
|
|
283
345
|
function getGridTile(cells, xT, yT, gridInfo) {
|
|
284
346
|
const tile = {}
|
|
285
347
|
|
package/src/layer/GridLayer.js
CHANGED
|
@@ -137,8 +137,16 @@ export class GridLayer extends Layer {
|
|
|
137
137
|
// so that hovering a swatch can highlight the cells of the style on the map
|
|
138
138
|
lg.style_ = style
|
|
139
139
|
lg.redraw = () => (geoCanvas.redraw ? geoCanvas.redraw() : undefined)
|
|
140
|
-
//
|
|
141
|
-
|
|
140
|
+
// The legends go in the order they are drawn, after the one placed before them. A hovered legend is
|
|
141
|
+
// still in the container (see Map.redrawNow) and is left where it is: moving it would lose its mouseleave,
|
|
142
|
+
// and appending the others after it would put it above the legends that come before it.
|
|
143
|
+
const container = legendComp.node()
|
|
144
|
+
const el = lg.div.node()
|
|
145
|
+
const previous = container._gridvizLegendCursor
|
|
146
|
+
if (previous) {
|
|
147
|
+
if (el.previousSibling !== previous) previous.after(el)
|
|
148
|
+
} else if (container.firstChild !== el) container.prepend(el)
|
|
149
|
+
container._gridvizLegendCursor = el
|
|
142
150
|
}
|
|
143
151
|
}
|
|
144
152
|
|