gridviz 2.1.10 → 2.1.12
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 +76 -49
- package/dist/gridviz.min.js +1 -1
- package/package.json +1 -1
- package/src/style/IsoFenceStyle.js +46 -46
- package/src/style/ShapeColorSizeStyle.js +28 -2
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@ export class IsoFenceStyle extends Style {
|
|
|
28
28
|
* @type {function(number,number,import("../Style").Stat|undefined,number):number} */
|
|
29
29
|
this.height = opts.height || ((v, r, s, zf) => r * 0.4)
|
|
30
30
|
|
|
31
|
-
/** The perspective angle.
|
|
31
|
+
/** The perspective angle, in degree, within [-180,180], from [O,x] axis.
|
|
32
32
|
* @type {number} */
|
|
33
33
|
this.angle = opts.angle != undefined ? opts.angle : 50
|
|
34
34
|
|
|
@@ -76,9 +76,6 @@ export class IsoFenceStyle extends Style {
|
|
|
76
76
|
//nb categories - used for radar and agepyramid
|
|
77
77
|
const cats = Object.keys(this.color)
|
|
78
78
|
|
|
79
|
-
//draw in geo coordinates
|
|
80
|
-
cg.setCanvasTransform()
|
|
81
|
-
|
|
82
79
|
//half resolution
|
|
83
80
|
const r2 = r / 2
|
|
84
81
|
|
|
@@ -146,32 +143,46 @@ export class IsoFenceStyle extends Style {
|
|
|
146
143
|
//angle in radians
|
|
147
144
|
const aRad = this.angle * Math.PI / 180, cos = Math.cos(aRad), sin = Math.sin(aRad)
|
|
148
145
|
|
|
146
|
+
//sort sides so that the back ones are drawn first. This depends on the angle.
|
|
147
|
+
//depending on distance to the reference corner point
|
|
148
|
+
const xCorner = Math.abs(this.angle) < 90 ? cg.extGeo.xMin : cg.extGeo.xMax
|
|
149
|
+
const yCorner = this.angle < 0 ? cg.extGeo.yMax : cg.extGeo.yMin
|
|
150
|
+
sides.sort((s1, s2) => (Math.hypot(s2.x - xCorner, s2.y - yCorner) - Math.hypot(s1.x - xCorner, s1.y - yCorner)))
|
|
151
|
+
|
|
152
|
+
//prepare function to draw corner line for a cell *c*
|
|
153
|
+
const drawCornerLine = (c) => {
|
|
154
|
+
|
|
155
|
+
if (!c) return
|
|
156
|
+
//line style
|
|
157
|
+
const lw = this.cornerLineWidth ? this.cornerLineWidth(c, r, zf, this.angle) : 0.8 * zf
|
|
158
|
+
if (lw == 0) return
|
|
159
|
+
cg.ctx.strokeStyle = this.cornerLineStrokeColor ? this.cornerLineStrokeColor(c, r, zf, this.angle) : "#333"
|
|
160
|
+
cg.ctx.lineWidth = lw
|
|
161
|
+
|
|
162
|
+
//height - in geo
|
|
163
|
+
const hG = h_(c[this.heightCol], r, stat, zf)
|
|
164
|
+
|
|
165
|
+
//draw line
|
|
166
|
+
cg.ctx.beginPath()
|
|
167
|
+
cg.ctx.moveTo(c.x + r2 + dx, c.y + r2 + dy)
|
|
168
|
+
cg.ctx.lineTo(c.x + r2 + hG * cos + dx, c.y + r2 + hG * sin + dy)
|
|
169
|
+
cg.ctx.stroke()
|
|
170
|
+
}
|
|
171
|
+
|
|
149
172
|
//draw in geo coordinates
|
|
150
173
|
cg.setCanvasTransform()
|
|
151
174
|
|
|
152
|
-
//sort sides so that the back ones are drawn first. This depends on the angle
|
|
153
|
-
if (Math.abs(this.angle) <= 90)
|
|
154
|
-
//north east ones are drown first
|
|
155
|
-
sides.sort((s1, s2) => (Math.hypot(s2.x, s2.y) - Math.hypot(s1.x, s1.y)))
|
|
156
|
-
else if (this.angle > 90)
|
|
157
|
-
//north west ones are drown first
|
|
158
|
-
sides.sort((s1, s2) => (Math.hypot(s2.x - cg.extGeo.xMax, s2.y) - Math.hypot(s1.x - cg.extGeo.xMax, s1.y)))
|
|
159
|
-
else if (this.angle < 90)
|
|
160
|
-
//south west ones are drown first
|
|
161
|
-
sides.sort((s1, s2) => (Math.hypot(s2.x - cg.extGeo.xMax, s2.y - cg.extGeo.yMax) - Math.hypot(s1.x - cg.extGeo.xMax, s1.y - cg.extGeo.yMax)))
|
|
162
|
-
|
|
163
175
|
//draw sides
|
|
176
|
+
cg.ctx.lineCap = "round";
|
|
164
177
|
for (let s of sides) {
|
|
165
178
|
|
|
166
179
|
//heights - in geo
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
/** @type {number} */
|
|
170
|
-
const hG2 = s.c2 ? h_(s.c2[this.heightCol], r, stat, zf) : 0
|
|
180
|
+
const hG1 = s.c1 ? h_(s.c1[this.heightCol], r, stat, zf) : 0,
|
|
181
|
+
hG2 = s.c2 ? h_(s.c2[this.heightCol], r, stat, zf) : 0
|
|
171
182
|
|
|
172
183
|
//compute totals for both cells
|
|
173
|
-
const total1 = computeTotal(s.c1, cats)
|
|
174
|
-
|
|
184
|
+
const total1 = computeTotal(s.c1, cats),
|
|
185
|
+
total2 = computeTotal(s.c2, cats)
|
|
175
186
|
if (total1 == 0 && total2 == 0) continue
|
|
176
187
|
|
|
177
188
|
let cumul1 = 0, cumul2 = 0
|
|
@@ -184,10 +195,10 @@ export class IsoFenceStyle extends Style {
|
|
|
184
195
|
if (v1 == 0 && v2 == 0) continue
|
|
185
196
|
|
|
186
197
|
//compute heights
|
|
187
|
-
const h1 =
|
|
188
|
-
const h1n =
|
|
189
|
-
const h2 =
|
|
190
|
-
const h2n =
|
|
198
|
+
const h1 = hG1 * cumul1 / total1 || 0
|
|
199
|
+
const h1n = hG1 * (cumul1 + v1) / total1 || 0
|
|
200
|
+
const h2 = hG2 * cumul2 / total2 || 0
|
|
201
|
+
const h2n = hG2 * (cumul2 + v2) / total2 || 0
|
|
191
202
|
|
|
192
203
|
//make path
|
|
193
204
|
cg.ctx.beginPath()
|
|
@@ -212,7 +223,7 @@ export class IsoFenceStyle extends Style {
|
|
|
212
223
|
//top left
|
|
213
224
|
cg.ctx.lineTo(s.x - r2 + h1n * cos + dx, s.y + h1n * sin + dy)
|
|
214
225
|
}
|
|
215
|
-
cg.ctx.closePath()
|
|
226
|
+
//cg.ctx.closePath()
|
|
216
227
|
|
|
217
228
|
//fill
|
|
218
229
|
cg.ctx.fillStyle = color
|
|
@@ -220,27 +231,16 @@ export class IsoFenceStyle extends Style {
|
|
|
220
231
|
|
|
221
232
|
cumul1 += v1
|
|
222
233
|
cumul2 += v2
|
|
223
|
-
//break
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
//draw corner lines
|
|
228
|
-
for (let c of cells) {
|
|
229
|
-
|
|
230
|
-
//line style
|
|
231
|
-
const lw = this.cornerLineWidth ? this.cornerLineWidth(c, r, zf, this.angle) : 0.8 * zf
|
|
232
|
-
if (lw == 0) continue
|
|
233
|
-
cg.ctx.strokeStyle = this.cornerLineStrokeColor ? this.cornerLineStrokeColor(c, r, zf, this.angle) : "#333"
|
|
234
|
-
cg.ctx.lineWidth = lw
|
|
235
234
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
235
|
+
//TODO draw only one line
|
|
236
|
+
//draw corner line
|
|
237
|
+
//if (s.or == "h") {
|
|
238
|
+
drawCornerLine(s.c1)
|
|
239
|
+
drawCornerLine(s.c2)
|
|
240
|
+
//if (this.angle > 0 && s.or == "h") drawCornerLine(s.c2)
|
|
241
|
+
//else drawCornerLine(s.c2)
|
|
242
|
+
//}
|
|
243
|
+
}
|
|
244
244
|
}
|
|
245
245
|
|
|
246
246
|
//update legends
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
'use strict'
|
|
3
3
|
|
|
4
4
|
import { Style } from '../Style.js'
|
|
5
|
+
import { color } from 'd3-color'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* A very generic style that shows grid cells with specific color, size and shape.
|
|
@@ -34,6 +35,14 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
34
35
|
/** A function returning the shape of a cell.
|
|
35
36
|
* @type {function(import("../Dataset").Cell):import("../Style").Shape} */
|
|
36
37
|
this.shape = opts.shape || (() => 'square')
|
|
38
|
+
|
|
39
|
+
/** The name of the column/attribute of the tabular data where to retrieve the variable for color alpha.
|
|
40
|
+
* @type {string} */
|
|
41
|
+
this.alphaCol = opts.alphaCol
|
|
42
|
+
|
|
43
|
+
/** A function returning the color alpha of the cell.
|
|
44
|
+
* @type {function(number,number,import("../Style").Stat|undefined,number):number} */
|
|
45
|
+
this.alphaF = opts.alphaF
|
|
37
46
|
}
|
|
38
47
|
|
|
39
48
|
/**
|
|
@@ -64,6 +73,12 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
64
73
|
statColor = Style.getStatistics(cells, (c) => c[this.colorCol], true)
|
|
65
74
|
}
|
|
66
75
|
|
|
76
|
+
let statAlpha
|
|
77
|
+
if (this.alphaCol) {
|
|
78
|
+
//compute color alpha variable statistics
|
|
79
|
+
statAlpha = Style.getStatistics(cells, (c) => c[this.alphaCol], true)
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
//draw with HTML canvas
|
|
68
83
|
//in geo coordinates
|
|
69
84
|
cg.setCanvasTransform()
|
|
@@ -71,9 +86,19 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
71
86
|
const r2 = r * 0.5
|
|
72
87
|
for (let cell of cells) {
|
|
73
88
|
//color
|
|
74
|
-
|
|
89
|
+
let col = this.color ? this.color(cell[this.colorCol], r, statColor, zf) : undefined
|
|
75
90
|
if (!col || col === 'none') continue
|
|
76
|
-
|
|
91
|
+
|
|
92
|
+
//alpha
|
|
93
|
+
if (this.alphaCol && this.alphaF) {
|
|
94
|
+
//get alpha
|
|
95
|
+
const alpha = this.alphaF(cell[this.alphaCol], r, statAlpha, zf)
|
|
96
|
+
if (alpha == 0) continue
|
|
97
|
+
//apply alpha to color col
|
|
98
|
+
const col_ = color(col);
|
|
99
|
+
if (col_) col = `rgba(${col_.r}, ${col_.g}, ${col_.b}, ${alpha})`;
|
|
100
|
+
else console.warn("Could not decode color " + col + " in ShapeColorSizeStyle")
|
|
101
|
+
}
|
|
77
102
|
|
|
78
103
|
//shape
|
|
79
104
|
const shape = this.shape ? this.shape(cell) : 'square'
|
|
@@ -88,6 +113,7 @@ export class ShapeColorSizeStyle extends Style {
|
|
|
88
113
|
//get offset
|
|
89
114
|
const offset = this.offset(cell, r, zf)
|
|
90
115
|
|
|
116
|
+
cg.ctx.fillStyle = col
|
|
91
117
|
if (shape === 'square') {
|
|
92
118
|
//draw square
|
|
93
119
|
const d = r * (1 - sG / r) * 0.5
|