gridviz 2.1.17 → 3.0.1

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 (67) hide show
  1. package/README.md +2 -3
  2. package/dist/gridviz.js +8659 -9294
  3. package/dist/gridviz.min.js +1 -1
  4. package/package.json +3 -2
  5. package/src/button/Button.js +14 -15
  6. package/src/button/FullscreenButton.js +14 -14
  7. package/src/button/ZoomButtons.js +2 -2
  8. package/src/{DatasetComponent.js → core/Dataset.js} +33 -13
  9. package/src/core/Drawable.js +60 -0
  10. package/src/{GeoCanvas.js → core/GeoCanvas.js} +65 -155
  11. package/src/core/Layer.js +24 -0
  12. package/src/{Legend.js → core/Legend.js} +24 -1
  13. package/src/core/Map.js +474 -0
  14. package/src/core/MultiResolutionDataset.js +96 -0
  15. package/src/core/Style.js +84 -0
  16. package/src/dataset/COGeo.js +5 -5
  17. package/src/dataset/CSVGrid.js +43 -41
  18. package/src/dataset/GeoTIFF.js +9 -14
  19. package/src/dataset/{LGrid.js → JSGrid.js} +9 -11
  20. package/src/dataset/TiledGrid.js +68 -45
  21. package/src/index.js +22 -29
  22. package/src/{BackgroundLayer.js → layer/BackgroundLayer.js} +27 -52
  23. package/src/{BackgroundLayerWMS.js → layer/BackgroundLayerWMS.js} +21 -45
  24. package/src/{LineLayer.js → layer/GeoJSONLayer.js} +22 -23
  25. package/src/layer/GridLayer.js +160 -0
  26. package/src/{LabelLayer.js → layer/LabelLayer.js} +25 -23
  27. package/src/legend/ColorCategoryLegend.js +9 -24
  28. package/src/legend/ColorDiscreteLegend.js +20 -24
  29. package/src/legend/ColorLegend.js +21 -33
  30. package/src/legend/OrientationLegend.js +90 -0
  31. package/src/legend/SizeLegend.js +153 -72
  32. package/src/style/CompositionStyle.js +71 -84
  33. package/src/style/ContourStyle.js +2 -36
  34. package/src/style/DotDensityStyle.js +50 -73
  35. package/src/style/IsoFenceStyle.js +59 -70
  36. package/src/style/JoyPlotStyle.js +41 -48
  37. package/src/style/LegoStyle.js +4 -4
  38. package/src/style/MosaicStyle.js +30 -39
  39. package/src/style/NinjaStarStyle.js +45 -68
  40. package/src/style/PillarStyle.js +70 -93
  41. package/src/style/SegmentStyle.js +37 -75
  42. package/src/style/ShapeColorSizeStyle.js +49 -98
  43. package/src/style/SideCategoryStyle.js +112 -0
  44. package/src/style/SideStyle.js +99 -133
  45. package/src/style/{SquareColorCatWGLStyle.js → SquareColorCategoryWebGLStyle.js} +28 -41
  46. package/src/style/{SquareColorWGLStyle.js → SquareColorWebGLStyle.js} +28 -49
  47. package/src/style/StrokeStyle.js +43 -70
  48. package/src/style/TanakaStyle.js +34 -132
  49. package/src/style/TextStyle.js +43 -64
  50. package/src/style/TimeSeriesStyle.js +44 -75
  51. package/src/utils/WebGLSquareColoringAdvanced.js +4 -4
  52. package/src/utils/scale.js +217 -0
  53. package/src/utils/stretching.js +86 -129
  54. package/src/utils/{Utils.js → utils.js} +15 -0
  55. package/src/utils/webGLUtils.js +4 -5
  56. package/src/utils/zoomUtils.js +30 -30
  57. package/src/App.js +0 -760
  58. package/src/Dataset.js +0 -76
  59. package/src/Layer.js +0 -103
  60. package/src/Style.js +0 -131
  61. package/src/dataset/GridTile.js +0 -41
  62. package/src/legend/SegmentOrientationLegend.js +0 -87
  63. package/src/legend/SegmentWidthLegend.js +0 -101
  64. package/src/style/CompositionStyle_.js +0 -293
  65. package/src/style/ShapeColorSizeStyle_.js +0 -108
  66. package/src/style/SideCatStyle.js +0 -172
  67. /package/src/{Tooltip.js → core/Tooltip.js} +0 -0
@@ -1,6 +1,7 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
+ import { Layer } from '../core/Layer.js'
4
5
  import { csv } from 'd3-fetch'
5
6
 
6
7
  /** A label. The name is the text to show. (x,y) are the coordinates in the same CRS as the grid.
@@ -14,11 +15,12 @@ import { csv } from 'd3-fetch'
14
15
  *
15
16
  * @author Joseph Davies, Julien Gaffuri
16
17
  */
17
- export class LabelLayer {
18
+ export class LabelLayer extends Layer {
18
19
  /**
19
20
  * @param {object} opts
20
21
  */
21
22
  constructor(opts) {
23
+ super(opts)
22
24
  opts = opts || {}
23
25
 
24
26
  /**
@@ -82,60 +84,60 @@ export class LabelLayer {
82
84
  /**
83
85
  * Draw the label layer.
84
86
  *
85
- * @param {import("./GeoCanvas").GeoCanvas} cg The canvas where to draw the layer.
87
+ * @param {import("../core/GeoCanvas").GeoCanvas} geoCanvas The canvas where to draw the layer.
86
88
  * @returns {void}
87
89
  */
88
- draw(cg) {
90
+ draw(geoCanvas) {
89
91
  //load labels, if not done yet.
90
92
  if (!this.labels) {
91
- this.load(cg.redraw)
93
+ this.load(geoCanvas.redraw)
92
94
  return
93
95
  }
94
96
 
95
- //zoom factor
96
- const zf = cg.getZf()
97
+ //
98
+ const z = geoCanvas.view.z
97
99
 
98
100
  //text align
99
- cg.ctx.textAlign = this.textAlign || 'start'
101
+ geoCanvas.ctx.textAlign = this.textAlign || 'start'
100
102
 
101
103
  //line join and cap
102
- cg.ctx.lineJoin = 'bevel' //|| "round" || "miter";
103
- cg.ctx.lineCap = 'butt' //|| "round" || "square";
104
+ geoCanvas.ctx.lineJoin = 'bevel' //|| "round" || "miter";
105
+ geoCanvas.ctx.lineCap = 'butt' //|| "round" || "square";
104
106
 
105
107
  //draw in pix coordinates
106
- cg.initCanvasTransform()
108
+ geoCanvas.initCanvasTransform()
107
109
 
108
110
  //draw labels, one by one
109
111
  for (const lb of this.labels) {
110
112
  //get label style
111
- const st = this.style(lb, zf)
113
+ const st = this.style(lb, z)
112
114
  if (!st) continue
113
- cg.ctx.font = st
115
+ geoCanvas.ctx.font = st
114
116
 
115
117
  //check label within the view, to be drawn
116
- if (!cg.toDraw(lb)) continue
118
+ if (!geoCanvas.toDraw(lb)) continue
117
119
 
118
120
  //position
119
- const xP = cg.geoToPixX(lb.x) + this.offsetPix[0]
120
- const yP = cg.geoToPixY(lb.y) - this.offsetPix[1]
121
+ const xP = geoCanvas.geoToPixX(lb.x) + this.offsetPix[0]
122
+ const yP = geoCanvas.geoToPixY(lb.y) - this.offsetPix[1]
121
123
 
122
124
  //label stroke, for the halo
123
125
  if (this.haloColor && this.haloWidth) {
124
- const hc = this.haloColor(lb, zf)
125
- const hw = this.haloWidth(lb, zf)
126
+ const hc = this.haloColor(lb, z)
127
+ const hw = this.haloWidth(lb, z)
126
128
  if (hc && hw && hw > 0) {
127
- cg.ctx.strokeStyle = hc
128
- cg.ctx.lineWidth = hw
129
- cg.ctx.strokeText(lb.name, xP, yP)
129
+ geoCanvas.ctx.strokeStyle = hc
130
+ geoCanvas.ctx.lineWidth = hw
131
+ geoCanvas.ctx.strokeText(lb.name, xP, yP)
130
132
  }
131
133
  }
132
134
 
133
135
  //label fill
134
136
  if (this.color) {
135
- const col = this.color(lb, zf)
137
+ const col = this.color(lb, z)
136
138
  if (col) {
137
- cg.ctx.fillStyle = col
138
- cg.ctx.fillText(lb.name, xP, yP)
139
+ geoCanvas.ctx.fillStyle = col
140
+ geoCanvas.ctx.fillText(lb.name, xP, yP)
139
141
  }
140
142
  }
141
143
  }
@@ -1,7 +1,7 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
- import { Legend } from '../Legend.js'
4
+ import { Legend } from '../core/Legend.js'
5
5
 
6
6
  /**
7
7
  * A legend element for color categrories.
@@ -17,49 +17,34 @@ export class ColorCategoryLegend extends Legend {
17
17
  //col/categories array, in display order
18
18
  /**
19
19
  * @private
20
- * @type {Array.<Array.<string>>} */
21
- this.colCat = opts.colCat || [['gray', '-']]
20
+ * @type {Array.<[string,string]>} */
21
+ this.colorLabel = opts.colorLabel || [['gray', '-']]
22
22
 
23
23
  /**
24
24
  * @private
25
- * @type {import("../Style").Shape} */
25
+ * @type {import("../core/Style.js").Shape} */
26
26
  this.shape = opts.shape || 'circle'
27
27
  this.dimension = opts.dimension || { r: 8 }
28
28
  this.strokeColor = opts.strokeColor || 'gray'
29
29
  this.strokeWidth = opts.strokeWidth || 1
30
-
31
- this.title = opts.title
32
- this.titleFontSize = opts.titleFontSize || '0.8em'
33
- this.titleFontWeight = opts.titleFontWeight || 'bold'
34
-
35
- //label
36
- this.labelFontSize = opts.labelFontSize || '0.8em'
37
30
  }
38
31
 
39
32
  /**
40
- * @param {{ style: import("../Style").Style, r: number, zf: number, sSize: import("../Style").Stat, sColor: import("../Style").Stat }} opts
41
33
  */
42
- update(opts) {
34
+ update() {
35
+
43
36
  //clear
44
37
  this.div.selectAll('*').remove()
45
38
 
46
- //build
47
-
48
39
  //title
49
- if (this.title)
50
- this.div
51
- .append('div')
52
- .style('font-size', this.titleFontSize)
53
- .style('font-weight', this.titleFontWeight)
54
- .style('margin-bottom', '7px')
55
- .text(this.title)
40
+ this.makeTitle()
56
41
 
57
42
  //categories
58
- const nb = this.colCat.length
43
+ const nb = this.colorLabel.length
59
44
  if (nb == 0) return
60
45
 
61
46
  for (let i = 0; i < nb; i++) {
62
- const cat = this.colCat[i]
47
+ const cat = this.colorLabel[i]
63
48
 
64
49
  //make div for category
65
50
  const d = this.div.append('div')
@@ -1,7 +1,7 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
- import { Legend } from '../Legend.js'
4
+ import { Legend } from '../core/Legend.js'
5
5
 
6
6
  /**
7
7
  * A legend element for discrete color style.
@@ -15,45 +15,37 @@ export class ColorDiscreteLegend extends Legend {
15
15
  super(opts)
16
16
  opts = opts || {}
17
17
 
18
- /** @private @type {Array.<Array.<string>>} */
18
+ /** @private @type {function(import('../core/Style').ViewScale):Array.<string>} */
19
19
  this.colors = opts.colors
20
- /** @private @type {Array.<Array.<string>>} */
21
- this.breaksText = opts.breaksText
20
+ /** @private @type {function(import('../core/Style').ViewScale):Array.<number>} */
21
+ this.breaks = opts.breaks
22
22
 
23
23
  this.width = opts.width || 300
24
24
  this.height = opts.height || 15
25
25
 
26
- this.title = opts.title
27
- this.titleFontSize = opts.titleFontSize || '0.8em'
28
- this.titleFontWeight = opts.titleFontWeight || 'bold'
29
-
30
26
  this.tickSize = opts.tickSize || 3
31
27
 
32
28
  //label
33
- this.labelFontSize = opts.labelFontSize || '0.8em'
34
29
  this.invert = opts.invert
35
30
  }
36
31
 
37
32
  /**
38
- * @param {{ style: import("../Style").Style, r: number, zf: number, sSize: import("../Style").Stat, sColor: import("../Style").Stat }} opts
33
+ * @param {{viewScale:import('../core/Style').ViewScale} } opts
39
34
  */
40
35
  update(opts) {
36
+
41
37
  //clear
42
38
  this.div.selectAll('*').remove()
43
39
 
44
- //build
45
-
46
40
  //title
47
- if (this.title)
48
- this.div
49
- .append('div')
50
- .style('font-size', this.titleFontSize)
51
- .style('font-weight', this.titleFontWeight)
52
- .style('margin-bottom', '7px')
53
- .text(this.title)
41
+ this.makeTitle()
42
+
43
+ //get colors and breaks
44
+ const colors = this.colors(opts.viewScale)
45
+ const breaks = this.breaks(opts.viewScale)
54
46
 
55
47
  //classes
56
- const nb = this.colors.length
48
+ const nb = colors.length
57
49
  if (nb == 0) return
58
50
  const w = this.width / nb
59
51
 
@@ -70,7 +62,7 @@ export class ColorDiscreteLegend extends Legend {
70
62
  .attr('y', 0)
71
63
  .attr('width', w)
72
64
  .attr('height', this.height)
73
- .style('fill', this.colors[i])
65
+ .style('fill', colors[i])
74
66
  }
75
67
 
76
68
  //tick line
@@ -85,7 +77,11 @@ export class ColorDiscreteLegend extends Legend {
85
77
 
86
78
  //labels
87
79
  for (let i = 1; i < nb; i++) {
88
- //prepare label
80
+
81
+ let label = breaks[i - 1]
82
+ if (isNaN(label) || label == undefined) continue
83
+
84
+ //label
89
85
  svg.append('text')
90
86
  .attr('id', 'ticklabel_' + i)
91
87
  .attr('x', w * i)
@@ -93,11 +89,11 @@ export class ColorDiscreteLegend extends Legend {
93
89
  .style('font-size', this.labelFontSize)
94
90
  //.style("font-weight", "bold")
95
91
  //.style("font-family", "Arial")
96
- .style('text-anchor', i == 0 ? 'start' : i == this.ticks - 1 ? 'end' : 'middle')
92
+ .style('text-anchor', 'middle')
97
93
  .style('alignment-baseline', 'top')
98
94
  .style('dominant-baseline', 'hanging')
99
95
  .style('pointer-events', 'none')
100
- .text(this.breaksText[i - 1])
96
+ .text(label)
101
97
  }
102
98
  }
103
99
  }
@@ -1,8 +1,7 @@
1
1
  //@ts-check
2
2
  'use strict'
3
3
 
4
- import { Legend } from '../Legend.js'
5
- import { format } from 'd3-format'
4
+ import { Legend } from '../core/Legend.js'
6
5
 
7
6
  /**
8
7
  * A legend element for continuous color style.
@@ -16,58 +15,47 @@ export class ColorLegend extends Legend {
16
15
  super(opts)
17
16
  opts = opts || {}
18
17
 
19
- this.colorRamp = opts.colorRamp
18
+ //a function [0,1]->color for continuous colors
19
+ //or array of colors for discrete colors
20
+ this.colorScale = opts.colorScale
20
21
 
21
- //function (t[0,1], r, s) -> v (for label text)
22
- this.fun = opts.fun
22
+ //function (t[0,1]) -> value (for label text)
23
+ this.textScale = opts.textScale || (t => t)
23
24
 
24
- this.title = opts.title
25
- this.tickSize = opts.tickSize || 6
26
- this.width = opts.width || 300
27
- this.height = opts.height || 15
28
25
  this.margin = opts.margin || 5
26
+
27
+ //replace with labels ?
28
+ this.tickSize = opts.tickSize || 6
29
29
  this.ticks = opts.ticks || Math.floor(this.width / 50)
30
- this.tickFormat = opts.tickFormat || ',.0f'
30
+ this.tickFormat = opts.tickFormat
31
31
  this.tickUnit = opts.tickUnit
32
32
 
33
33
  this.fontSize = opts.fontSize || '0.8em'
34
34
  this.invert = opts.invert
35
35
 
36
- //to be used as opts => opts.sAlpha to show legend on alpha channel
37
- this.getStats = opts.getStats || (opts => opts.sColor)
36
+ this.width = opts.width || 300
37
+ this.height = opts.height || 15
38
38
  }
39
39
 
40
40
  /**
41
- * @param {{ style: import("../Style").Style, r: number, zf: number, sSize: import("../Style").Stat, sColor: import("../Style").Stat, sAlpha: import("../Style").Stat }} opts
41
+ * @param {{viewScale:import('../core/Style').ViewScale} } opts
42
42
  */
43
43
  update(opts) {
44
- //could happen when data is still loading
45
- if (!opts.sColor) return
46
44
 
47
45
  //clear
48
46
  this.div.selectAll('*').remove()
49
47
 
50
- const titleHeight = 12
48
+ //title
49
+ this.makeTitle()
51
50
 
52
51
  const svgW = this.width + 2 * this.margin
53
- const svgH = this.height + 3 * this.margin + titleHeight + this.tickSize + 10
52
+ const svgH = this.height + this.margin + this.tickSize + 10
54
53
  const svg = this.div.append('svg').attr('width', svgW).attr('height', svgH)
55
54
  // <rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
56
55
 
57
- //title
58
- svg.append('text')
59
- .attr('x', this.margin)
60
- .attr('y', this.margin)
61
- .style('font-size', '0.8em')
62
- .style('font-weight', 'bold')
63
- .style('alignment-baseline', 'top')
64
- .style('dominant-baseline', 'hanging')
65
- .style('pointer-events', 'none')
66
- .text(this.title)
67
-
68
56
  const g = svg
69
57
  .append('g')
70
- .attr('transform', 'translate(' + this.margin + ' ' + (2 * this.margin + titleHeight) + ')')
58
+ .attr('transform', 'translate(' + this.margin + ' ' + 0 + ')')
71
59
 
72
60
  //draw color bar
73
61
  const w = this.width,
@@ -81,7 +69,7 @@ export class ColorLegend extends Legend {
81
69
  .attr('y', 0)
82
70
  .attr('width', step)
83
71
  .attr('height', h)
84
- .style('fill', this.colorRamp(t))
72
+ .style('fill', this.colorScale(t, opts.viewScale))
85
73
  }
86
74
 
87
75
  for (let i = 0; i < this.ticks; i++) {
@@ -113,13 +101,13 @@ export class ColorLegend extends Legend {
113
101
  //update tick labels
114
102
 
115
103
  //label text format
116
- const f = this.tickFormat && this.tickFormat != 'text' ? format(this.tickFormat) : (v) => v
117
- const stat = this.getStats(opts)
104
+ const f = this.tickFormat && this.tickFormat != 'text' ? this.tickFormat : (v) => v
118
105
  for (let i = 0; i < this.ticks; i++) {
119
106
  let t = i / (this.ticks - 1)
120
107
 
121
- const v = this.fun(t, opts.r, stat)
108
+ const v = this.textScale(t, opts.viewScale)
122
109
  const text = (v ? f(v) : '0') + (this.tickUnit ? this.tickUnit : '')
110
+ if (text == undefined) continue
123
111
 
124
112
  //tick label
125
113
  this.div.select('#' + 'ticklabel_' + i).text(text)
@@ -0,0 +1,90 @@
1
+ //@ts-check
2
+ 'use strict'
3
+
4
+ import { Legend } from '../core/Legend.js'
5
+
6
+ /**
7
+ * A legend element for segment orientation.
8
+ *
9
+ * @author Joseph Davies, Julien Gaffuri
10
+ */
11
+ export class OrientationLegend extends Legend {
12
+ /** @param {Object} opts */
13
+ constructor(opts) {
14
+ super(opts)
15
+ opts = opts || {}
16
+
17
+ //orientation
18
+ this.orientation = opts.orientation || 0
19
+ //color
20
+ this.color = opts.color || ((resolution, z, viewScale) => 'gray')
21
+ //width
22
+ this.width = opts.width || ((resolution, z, viewScale) => 3 * z)
23
+ //length
24
+ this.length = opts.length || ((resolution, z, viewScale) => resolution)
25
+
26
+ //label
27
+ this.label = opts.label || "-"
28
+ }
29
+
30
+ /**
31
+ * @param {{ style: import("../style/SegmentStyle.js").SegmentStyle, resolution: number, z: number, viewScale:object }} opts
32
+ */
33
+ update(opts) {
34
+
35
+ //clear
36
+ this.div.selectAll('*').remove()
37
+
38
+ //title
39
+ this.makeTitle()
40
+
41
+ const d = this.div.append('div')
42
+
43
+ //compute segment color, width and length
44
+ const color = this.color(opts.resolution, opts.z, opts.viewScale)
45
+ const widthPix = this.width(opts.resolution, opts.z, opts.viewScale) / opts.z
46
+ const lengthPix = this.length(opts.resolution, opts.z, opts.viewScale) / opts.z
47
+
48
+ //draw SVG segment
49
+ const svgS = Math.max(lengthPix, widthPix)
50
+ const svg = d.append('svg').attr('width', svgS).attr('height', svgS).style('', 'inline-block')
51
+
52
+ const cos = Math.cos((-this.orientation * Math.PI) / 180)
53
+ const sin = Math.sin((-this.orientation * Math.PI) / 180)
54
+ const dc = svgS * 0.5,
55
+ l2 = lengthPix * 0.5
56
+ svg.append('line')
57
+ .attr('x1', dc - cos * l2)
58
+ .attr('y1', dc - sin * l2)
59
+ .attr('x2', dc + cos * l2)
60
+ .attr('y2', dc + sin * l2)
61
+ .style('stroke', color)
62
+ .style('stroke-width', widthPix)
63
+
64
+
65
+ //label
66
+ d.append('div')
67
+ .style('display', 'inline')
68
+ .style('padding-left', '5px')
69
+ .style('font-size', this.labelFontSize)
70
+ .text(this.label + (this.labelUnitText ? ' ' : '') + this.labelUnitText)
71
+ }
72
+ }
73
+
74
+ /**
75
+ *
76
+ * @param {Array.<number>} orientations
77
+ * @param {Array.<string>} labels
78
+ * @param {object} opts
79
+ * @returns { Array.<OrientationLegend> }
80
+ */
81
+ export function orientationLegend(orientations, labels, opts = {}) {
82
+ const legends = []
83
+ for (let i = 0; i < orientations.length; i++) {
84
+ opts.title = i == 0 ? opts.title : undefined;
85
+ opts.orientation = orientations[i]
86
+ opts.label = labels[i]
87
+ legends.push(new OrientationLegend(opts))
88
+ }
89
+ return legends
90
+ }