From 20cdc837af04b8bbac602c98699c7f70cb9ec20b Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 5 Oct 2023 15:14:28 +0200 Subject: [PATCH 1/5] Use toFixed instead of toPrecision in Range input toPrecision returns an exponential notation for example for: const x = 100 x.toPrecision(2) --- umap/static/umap/js/umap.forms.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index 0d983e67..bf9dcdf7 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -854,10 +854,10 @@ L.FormBuilder.Range = L.FormBuilder.Input.extend({ datalist.id = `range-${this.options.label || this.name}` this.input.setAttribute('list', datalist.id) let options = '' + const step = this.options.step || 1, + digits = step < 1 ? 2 : 0 for (let i = this.options.min; i <= this.options.max; i += this.options.step) { - options += `` + options += `` } datalist.innerHTML = options }, From a5c7214533494e5d7ebb9b303b47c7a852b8dcd7 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 5 Oct 2023 17:32:27 +0200 Subject: [PATCH 2/5] Add back helpText on Range input --- umap/static/umap/js/umap.forms.js | 1 + 1 file changed, 1 insertion(+) diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index bf9dcdf7..0d522ff5 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -860,6 +860,7 @@ L.FormBuilder.Range = L.FormBuilder.Input.extend({ options += `` } datalist.innerHTML = options + L.FormBuilder.Input.prototype.buildHelpText.call(this) }, }) From 3e54310c8dd80d4aa02c2d563d0b23e21c15b4b8 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 5 Oct 2023 17:36:07 +0200 Subject: [PATCH 3/5] Add Range input for heatmap radius --- umap/static/umap/js/umap.layer.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index 7f0b03fc..4f45b859 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -161,8 +161,11 @@ L.U.Layer.Heat = L.HeatLayer.extend({ [ 'options.heat.radius', { - handler: 'BlurIntInput', - placeholder: L._('Heatmap radius'), + handler: 'Range', + min: 10, + max: 100, + step: 5, + label: L._('Heatmap radius'), helpText: L._('Override heatmap radius (default 25)'), }, ], From ca7257658c87a01d32c647d76997382590e5e258 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 5 Oct 2023 18:15:21 +0200 Subject: [PATCH 4/5] Make that Range inherit from FloatInput Otherwise we store a string --- umap/static/umap/js/umap.forms.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/umap/static/umap/js/umap.forms.js b/umap/static/umap/js/umap.forms.js index 0d522ff5..6faf6531 100644 --- a/umap/static/umap/js/umap.forms.js +++ b/umap/static/umap/js/umap.forms.js @@ -836,13 +836,13 @@ L.FormBuilder.OutlinkTarget = L.FormBuilder.MultiChoice.extend({ ], }) -L.FormBuilder.Range = L.FormBuilder.Input.extend({ +L.FormBuilder.Range = L.FormBuilder.FloatInput.extend({ type: function () { return 'range' }, value: function () { - return L.DomUtil.hasClass(this.wrapper, 'undefined') ? undefined : this.input.value + return L.DomUtil.hasClass(this.wrapper, 'undefined') ? undefined : L.FormBuilder.FloatInput.prototype.value.call(this) }, buildHelpText: function () { From 5bfa2fce385bbcd05dcadb2e765c185ced4c452c Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Thu, 5 Oct 2023 18:15:59 +0200 Subject: [PATCH 5/5] Patch HeatLayer for better rendering Patch comes from https://github.com/Leaflet/Leaflet.heat/pull/78 We'll remove it when this PR get merged and released. --- umap/static/umap/js/umap.layer.js | 86 ++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/umap/static/umap/js/umap.layer.js b/umap/static/umap/js/umap.layer.js index 4f45b859..2a261c54 100644 --- a/umap/static/umap/js/umap.layer.js +++ b/umap/static/umap/js/umap.layer.js @@ -137,14 +137,6 @@ L.U.Layer.Heat = L.HeatLayer.extend({ this.setLatLngs([]) }, - redraw: function () { - // setlalngs call _redraw through setAnimFrame, thus async, so this - // can ends with race condition if we remove the layer very faslty after. - // Remove me when https://github.com/Leaflet/Leaflet.heat/pull/53 is released. - if (!this._map) return - L.HeatLayer.prototype.redraw.call(this) - }, - getFeatures: function () { return {} }, @@ -190,6 +182,84 @@ L.U.Layer.Heat = L.HeatLayer.extend({ } this._updateOptions() }, + + _redraw: function () { + // Import patch from https://github.com/Leaflet/Leaflet.heat/pull/78 + // Remove me when this get merged and released. + if (!this._map) { + return + } + var data = [], + r = this._heat._r, + size = this._map.getSize(), + bounds = new L.Bounds(L.point([-r, -r]), size.add([r, r])), + cellSize = r / 2, + grid = [], + panePos = this._map._getMapPanePos(), + offsetX = panePos.x % cellSize, + offsetY = panePos.y % cellSize, + i, + len, + p, + cell, + x, + y, + j, + len2 + + this._max = 1 + + for (i = 0, len = this._latlngs.length; i < len; i++) { + p = this._map.latLngToContainerPoint(this._latlngs[i]) + x = Math.floor((p.x - offsetX) / cellSize) + 2 + y = Math.floor((p.y - offsetY) / cellSize) + 2 + + var alt = + this._latlngs[i].alt !== undefined + ? this._latlngs[i].alt + : this._latlngs[i][2] !== undefined + ? +this._latlngs[i][2] + : 1 + + grid[y] = grid[y] || [] + cell = grid[y][x] + + if (!cell) { + cell = grid[y][x] = [p.x, p.y, alt] + cell.p = p + } else { + cell[0] = (cell[0] * cell[2] + p.x * alt) / (cell[2] + alt) // x + cell[1] = (cell[1] * cell[2] + p.y * alt) / (cell[2] + alt) // y + cell[2] += alt // cumulated intensity value + } + + // Set the max for the current zoom level + if (cell[2] > this._max) { + this._max = cell[2] + } + } + + this._heat.max(this._max) + + for (i = 0, len = grid.length; i < len; i++) { + if (grid[i]) { + for (j = 0, len2 = grid[i].length; j < len2; j++) { + cell = grid[i][j] + if (cell && bounds.contains(cell.p)) { + data.push([ + Math.round(cell[0]), + Math.round(cell[1]), + Math.min(cell[2], this._max), + ]) + } + } + } + } + + this._heat.data(data).draw(this.options.minOpacity) + + this._frame = null + }, }) L.U.DataLayer = L.Evented.extend({