gridviz 3.0.19 → 3.0.21
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/README.md +128 -128
- package/dist/gridviz.js +7875 -7857
- package/dist/gridviz.min.js +1 -1
- package/package.json +74 -74
- package/src/button/ZoomButtons.js +101 -101
- package/src/core/Dataset.js +154 -154
- package/src/core/Drawable.js +78 -60
- package/src/core/GeoCanvas.js +430 -430
- package/src/core/Layer.js +23 -23
- package/src/core/Legend.js +108 -108
- package/src/core/Map.js +516 -516
- package/src/core/MultiResolutionDataset.js +93 -93
- package/src/core/Style.js +98 -98
- package/src/dataset/CSVGrid.js +112 -112
- package/src/dataset/GeoTIFF.js +122 -122
- package/src/dataset/JSGrid.js +55 -55
- package/src/dataset/TiledGrid.js +302 -302
- package/src/dataset/worker.js +18 -18
- package/src/index.js +77 -77
- package/src/layer/BackgroundLayer.js +162 -162
- package/src/layer/BackgroundLayerImage.js +81 -81
- package/src/layer/BackgroundLayerWMS.js +104 -104
- package/src/layer/GeoJSONLayer.js +214 -214
- package/src/layer/GridLayer.js +148 -148
- package/src/layer/LabelLayer.js +194 -194
- package/src/legend/ColorCategoryLegend.js +109 -109
- package/src/legend/ColorDiscreteLegend.js +100 -100
- package/src/legend/ColorLegend.js +115 -115
- package/src/legend/OrientationLegend.js +89 -89
- package/src/legend/SizeLegend.js +224 -224
- package/src/legend/TernaryLegend.js +302 -302
- package/src/style/CompositionStyle.js +291 -291
- package/src/style/DotDensityStyle.js +133 -133
- package/src/style/ImageStyle.js +100 -100
- package/src/style/IsoFenceStyle.js +217 -217
- package/src/style/JoyPlotStyle.js +127 -127
- package/src/style/LegoStyle.js +110 -110
- package/src/style/MosaicStyle.js +99 -99
- package/src/style/NinjaStarStyle.js +102 -102
- package/src/style/PillarStyle.js +207 -207
- package/src/style/SegmentStyle.js +105 -105
- package/src/style/ShapeColorSizeStyle.js +147 -147
- package/src/style/SideCategoryStyle.js +112 -112
- package/src/style/SideStyle.js +212 -212
- package/src/style/SquareColorCategoryWebGLStyle.js +107 -107
- package/src/style/SquareColorWebGLStyle.js +126 -126
- package/src/style/StrokeStyle.js +135 -135
- package/src/style/TanakaStyle.js +69 -69
- package/src/style/TextStyle.js +110 -110
- package/src/style/TimeSeriesStyle.js +222 -222
- package/src/utils/scale.js +218 -218
- package/src/utils/stretching.js +120 -120
- package/src/utils/ternary.js +208 -208
- package/src/utils/utils.js +58 -58
- package/src/utils/webGLUtils.js +72 -72
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { Style } from '../core/Style.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @module style
|
|
8
|
-
* @author Julien Gaffuri
|
|
9
|
-
*/
|
|
10
|
-
export class JoyPlotStyle extends Style {
|
|
11
|
-
/** @param {object} opts */
|
|
12
|
-
constructor(opts) {
|
|
13
|
-
super(opts)
|
|
14
|
-
opts = opts || {}
|
|
15
|
-
|
|
16
|
-
/** A function returning the height of a cell in geographical unit.
|
|
17
|
-
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
18
|
-
this.height = opts.height || ((c, r) => r * Math.random()) //(c,r,z,vs) => {}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @type {function(number,{min:number, max:number},number,number):string} */
|
|
22
|
-
this.lineColor = opts.lineColor || ((y, ys, r, z) => '#BBB')
|
|
23
|
-
/**
|
|
24
|
-
* @type {function(number,{min:number, max:number},number,number):number} */
|
|
25
|
-
this.lineWidth = opts.lineWidth || ((y, ys, r, z) => z)
|
|
26
|
-
/**
|
|
27
|
-
* @type {function(number,{min:number, max:number},number,number):string} */
|
|
28
|
-
this.fillColor = opts.fillColor || ((y, ys, r, z) => '#c08c5968')
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
33
|
-
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
34
|
-
* @param {number} resolution
|
|
35
|
-
* @override
|
|
36
|
-
*/
|
|
37
|
-
draw(cells, geoCanvas, resolution) {
|
|
38
|
-
//filter
|
|
39
|
-
if (this.filter) cells = cells.filter(this.filter)
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
const z = geoCanvas.view.z
|
|
43
|
-
const ctx = geoCanvas.offscreenCtx
|
|
44
|
-
|
|
45
|
-
//get view scale
|
|
46
|
-
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
47
|
-
|
|
48
|
-
//index cells by y and x
|
|
49
|
-
/** @type {object} */
|
|
50
|
-
const ind = {}
|
|
51
|
-
for (const cell of cells) {
|
|
52
|
-
let row = ind[cell.y]
|
|
53
|
-
if (!row) {
|
|
54
|
-
row = {}
|
|
55
|
-
ind[cell.y] = row
|
|
56
|
-
}
|
|
57
|
-
row[cell.x] = this.height(cell, resolution, z, viewScale)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
//compute extent
|
|
61
|
-
const e = geoCanvas.extGeo
|
|
62
|
-
if (!e) return
|
|
63
|
-
const xMin = Math.floor(e.xMin / resolution) * resolution
|
|
64
|
-
const xMax = Math.floor(e.xMax / resolution) * resolution
|
|
65
|
-
const yMin = Math.floor(e.yMin / resolution) * resolution
|
|
66
|
-
const yMax = Math.floor(e.yMax / resolution) * resolution
|
|
67
|
-
|
|
68
|
-
/** @type {{min:number, max:number}} */
|
|
69
|
-
const ys = { min: yMin, max: yMax }
|
|
70
|
-
|
|
71
|
-
//draw lines, row by row, stating from the top
|
|
72
|
-
ctx.lineJoin = 'round'
|
|
73
|
-
for (let y = yMax; y >= yMin; y -= resolution) {
|
|
74
|
-
//get row
|
|
75
|
-
const row = ind[y]
|
|
76
|
-
|
|
77
|
-
//no row
|
|
78
|
-
if (!row) continue
|
|
79
|
-
|
|
80
|
-
//place first point
|
|
81
|
-
ctx.beginPath()
|
|
82
|
-
ctx.moveTo(xMin - resolution / 2, y)
|
|
83
|
-
|
|
84
|
-
//store the previous height
|
|
85
|
-
/** @type {number|undefined} */
|
|
86
|
-
let hG_
|
|
87
|
-
|
|
88
|
-
//go through the line cells
|
|
89
|
-
for (let x = xMin; x <= xMax; x += resolution) {
|
|
90
|
-
//get column value
|
|
91
|
-
/** @type {number} */
|
|
92
|
-
let hG = row[x]
|
|
93
|
-
if (!hG) hG = 0
|
|
94
|
-
|
|
95
|
-
if (hG || hG_) {
|
|
96
|
-
//draw line only when at least one of both values is non-null
|
|
97
|
-
//TODO test bezierCurveTo
|
|
98
|
-
ctx.lineTo(x + resolution / 2, y + hG)
|
|
99
|
-
} else {
|
|
100
|
-
//else move the point
|
|
101
|
-
ctx.moveTo(x + resolution / 2, y)
|
|
102
|
-
}
|
|
103
|
-
//store the previous value
|
|
104
|
-
hG_ = hG
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
//last point
|
|
108
|
-
if (hG_) ctx.lineTo(xMax + resolution / 2, y)
|
|
109
|
-
|
|
110
|
-
//draw fill
|
|
111
|
-
const fc = this.fillColor(y, ys, resolution, z)
|
|
112
|
-
if (fc && fc != 'none') {
|
|
113
|
-
ctx.fillStyle = fc
|
|
114
|
-
ctx.fill()
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
//draw line
|
|
118
|
-
const lc = this.lineColor(y, ys, resolution, z)
|
|
119
|
-
const lw = this.lineWidth(y, ys, resolution, z)
|
|
120
|
-
if (lc && lc != 'none' && lw > 0) {
|
|
121
|
-
ctx.strokeStyle = lc
|
|
122
|
-
ctx.lineWidth = lw
|
|
123
|
-
ctx.stroke()
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { Style } from '../core/Style.js'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @module style
|
|
8
|
+
* @author Julien Gaffuri
|
|
9
|
+
*/
|
|
10
|
+
export class JoyPlotStyle extends Style {
|
|
11
|
+
/** @param {object} opts */
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
super(opts)
|
|
14
|
+
opts = opts || {}
|
|
15
|
+
|
|
16
|
+
/** A function returning the height of a cell in geographical unit.
|
|
17
|
+
* @type {function(import('../core/Dataset.js').Cell, number, number, object):number} */
|
|
18
|
+
this.height = opts.height || ((c, r) => r * Math.random()) //(c,r,z,vs) => {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @type {function(number,{min:number, max:number},number,number):string} */
|
|
22
|
+
this.lineColor = opts.lineColor || ((y, ys, r, z) => '#BBB')
|
|
23
|
+
/**
|
|
24
|
+
* @type {function(number,{min:number, max:number},number,number):number} */
|
|
25
|
+
this.lineWidth = opts.lineWidth || ((y, ys, r, z) => z)
|
|
26
|
+
/**
|
|
27
|
+
* @type {function(number,{min:number, max:number},number,number):string} */
|
|
28
|
+
this.fillColor = opts.fillColor || ((y, ys, r, z) => '#c08c5968')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {Array.<import("../core/Dataset.js").Cell>} cells
|
|
33
|
+
* @param {import("../core/GeoCanvas.js").GeoCanvas} geoCanvas
|
|
34
|
+
* @param {number} resolution
|
|
35
|
+
* @override
|
|
36
|
+
*/
|
|
37
|
+
draw(cells, geoCanvas, resolution) {
|
|
38
|
+
//filter
|
|
39
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
40
|
+
|
|
41
|
+
//
|
|
42
|
+
const z = geoCanvas.view.z
|
|
43
|
+
const ctx = geoCanvas.offscreenCtx
|
|
44
|
+
|
|
45
|
+
//get view scale
|
|
46
|
+
const viewScale = this.viewScale ? this.viewScale(cells, resolution, z) : undefined
|
|
47
|
+
|
|
48
|
+
//index cells by y and x
|
|
49
|
+
/** @type {object} */
|
|
50
|
+
const ind = {}
|
|
51
|
+
for (const cell of cells) {
|
|
52
|
+
let row = ind[cell.y]
|
|
53
|
+
if (!row) {
|
|
54
|
+
row = {}
|
|
55
|
+
ind[cell.y] = row
|
|
56
|
+
}
|
|
57
|
+
row[cell.x] = this.height(cell, resolution, z, viewScale)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//compute extent
|
|
61
|
+
const e = geoCanvas.extGeo
|
|
62
|
+
if (!e) return
|
|
63
|
+
const xMin = Math.floor(e.xMin / resolution) * resolution
|
|
64
|
+
const xMax = Math.floor(e.xMax / resolution) * resolution
|
|
65
|
+
const yMin = Math.floor(e.yMin / resolution) * resolution
|
|
66
|
+
const yMax = Math.floor(e.yMax / resolution) * resolution
|
|
67
|
+
|
|
68
|
+
/** @type {{min:number, max:number}} */
|
|
69
|
+
const ys = { min: yMin, max: yMax }
|
|
70
|
+
|
|
71
|
+
//draw lines, row by row, stating from the top
|
|
72
|
+
ctx.lineJoin = 'round'
|
|
73
|
+
for (let y = yMax; y >= yMin; y -= resolution) {
|
|
74
|
+
//get row
|
|
75
|
+
const row = ind[y]
|
|
76
|
+
|
|
77
|
+
//no row
|
|
78
|
+
if (!row) continue
|
|
79
|
+
|
|
80
|
+
//place first point
|
|
81
|
+
ctx.beginPath()
|
|
82
|
+
ctx.moveTo(xMin - resolution / 2, y)
|
|
83
|
+
|
|
84
|
+
//store the previous height
|
|
85
|
+
/** @type {number|undefined} */
|
|
86
|
+
let hG_
|
|
87
|
+
|
|
88
|
+
//go through the line cells
|
|
89
|
+
for (let x = xMin; x <= xMax; x += resolution) {
|
|
90
|
+
//get column value
|
|
91
|
+
/** @type {number} */
|
|
92
|
+
let hG = row[x]
|
|
93
|
+
if (!hG) hG = 0
|
|
94
|
+
|
|
95
|
+
if (hG || hG_) {
|
|
96
|
+
//draw line only when at least one of both values is non-null
|
|
97
|
+
//TODO test bezierCurveTo
|
|
98
|
+
ctx.lineTo(x + resolution / 2, y + hG)
|
|
99
|
+
} else {
|
|
100
|
+
//else move the point
|
|
101
|
+
ctx.moveTo(x + resolution / 2, y)
|
|
102
|
+
}
|
|
103
|
+
//store the previous value
|
|
104
|
+
hG_ = hG
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
//last point
|
|
108
|
+
if (hG_) ctx.lineTo(xMax + resolution / 2, y)
|
|
109
|
+
|
|
110
|
+
//draw fill
|
|
111
|
+
const fc = this.fillColor(y, ys, resolution, z)
|
|
112
|
+
if (fc && fc != 'none') {
|
|
113
|
+
ctx.fillStyle = fc
|
|
114
|
+
ctx.fill()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//draw line
|
|
118
|
+
const lc = this.lineColor(y, ys, resolution, z)
|
|
119
|
+
const lw = this.lineWidth(y, ys, resolution, z)
|
|
120
|
+
if (lc && lc != 'none' && lw > 0) {
|
|
121
|
+
ctx.strokeStyle = lc
|
|
122
|
+
ctx.lineWidth = lw
|
|
123
|
+
ctx.stroke()
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
package/src/style/LegoStyle.js
CHANGED
|
@@ -1,110 +1,110 @@
|
|
|
1
|
-
//@ts-check
|
|
2
|
-
'use strict'
|
|
3
|
-
|
|
4
|
-
import { TanakaStyle } from './TanakaStyle.js'
|
|
5
|
-
import { StrokeStyle } from './StrokeStyle.js'
|
|
6
|
-
import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
|
|
7
|
-
import { Style } from '../core/Style.js'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @module style
|
|
11
|
-
* @author Julien Gaffuri
|
|
12
|
-
*/
|
|
13
|
-
export class LegoStyle {
|
|
14
|
-
static get(value, breaks, colors, opts = {}) {
|
|
15
|
-
opts = opts || {}
|
|
16
|
-
|
|
17
|
-
//the colors
|
|
18
|
-
//http://www.jennyscrayoncollection.com/2021/06/all-current-lego-colors.html
|
|
19
|
-
//https://leonawicz.github.io/legocolors/reference/figures/README-plot-1.png
|
|
20
|
-
/*opts.colors = opts.colors || [
|
|
21
|
-
'#00852b', //darker green
|
|
22
|
-
'#afd246', //light green
|
|
23
|
-
'#fac80a', //dark yellow
|
|
24
|
-
'#bb805a', //brown
|
|
25
|
-
'#d67923', //mostard
|
|
26
|
-
'#cb4e29', //redish
|
|
27
|
-
'#b40000', //red
|
|
28
|
-
'#720012', //dark red
|
|
29
|
-
//"purple",
|
|
30
|
-
//"#eee" //whithe
|
|
31
|
-
]*/
|
|
32
|
-
|
|
33
|
-
opts.colDark = opts.colDark || '#333'
|
|
34
|
-
opts.colBright = opts.colBright || '#aaa'
|
|
35
|
-
opts.widthFactor = opts.widthFactor || 0.12
|
|
36
|
-
|
|
37
|
-
//reuse tanaka as basis
|
|
38
|
-
const ts = TanakaStyle.get(value, breaks, colors, opts)
|
|
39
|
-
//style to show limits between pieces
|
|
40
|
-
const sst = new StrokeStyle({
|
|
41
|
-
strokeColor: () => '#666',
|
|
42
|
-
strokeWidth: (c, r, z) => 0.2 * z,
|
|
43
|
-
filter: opts.filter,
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
return [
|
|
47
|
-
ts[0],
|
|
48
|
-
sst,
|
|
49
|
-
ts[1],
|
|
50
|
-
new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright, filter: opts.filter }),
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* @param {function(import('../core/Dataset.js').Cell):string} code
|
|
56
|
-
* @param {object} color
|
|
57
|
-
* @param {object} opts
|
|
58
|
-
* @returns {Array.<Style>}
|
|
59
|
-
*/
|
|
60
|
-
static getCategory(code, color, opts) {
|
|
61
|
-
opts = opts || {}
|
|
62
|
-
|
|
63
|
-
opts.colDark = opts.colDark || '#333'
|
|
64
|
-
opts.colBright = opts.colBright || '#aaa'
|
|
65
|
-
|
|
66
|
-
//
|
|
67
|
-
const s = new SquareColorCategoryWebGLStyle({ code: code, color: color })
|
|
68
|
-
//style to show limits between pieces
|
|
69
|
-
const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (c, r, z) => 0.2 * z })
|
|
70
|
-
|
|
71
|
-
return [s, sst, new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright })]
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* A style to draw top circle of lego bricks.
|
|
77
|
-
*/
|
|
78
|
-
class LegoTopStyle extends Style {
|
|
79
|
-
/** @param {object|undefined} opts */
|
|
80
|
-
constructor(opts) {
|
|
81
|
-
super(opts)
|
|
82
|
-
opts = opts || {}
|
|
83
|
-
this.colDark = opts.colDark || '#333'
|
|
84
|
-
this.colBright = opts.colBright || '#aaa'
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
draw(cells, geoCanvas, r) {
|
|
88
|
-
//filter
|
|
89
|
-
if (this.filter) cells = cells.filter(this.filter)
|
|
90
|
-
const ctx = geoCanvas.offscreenCtx
|
|
91
|
-
|
|
92
|
-
ctx.lineWidth = 0.6 * geoCanvas.view.z
|
|
93
|
-
|
|
94
|
-
//dark part
|
|
95
|
-
ctx.strokeStyle = this.colDark
|
|
96
|
-
for (let c of cells) {
|
|
97
|
-
ctx.beginPath()
|
|
98
|
-
ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), true)
|
|
99
|
-
ctx.stroke()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
//bright part
|
|
103
|
-
ctx.strokeStyle = this.colBright
|
|
104
|
-
for (let c of cells) {
|
|
105
|
-
ctx.beginPath()
|
|
106
|
-
ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), false)
|
|
107
|
-
ctx.stroke()
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
1
|
+
//@ts-check
|
|
2
|
+
'use strict'
|
|
3
|
+
|
|
4
|
+
import { TanakaStyle } from './TanakaStyle.js'
|
|
5
|
+
import { StrokeStyle } from './StrokeStyle.js'
|
|
6
|
+
import { SquareColorCategoryWebGLStyle } from './SquareColorCategoryWebGLStyle.js'
|
|
7
|
+
import { Style } from '../core/Style.js'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @module style
|
|
11
|
+
* @author Julien Gaffuri
|
|
12
|
+
*/
|
|
13
|
+
export class LegoStyle {
|
|
14
|
+
static get(value, breaks, colors, opts = {}) {
|
|
15
|
+
opts = opts || {}
|
|
16
|
+
|
|
17
|
+
//the colors
|
|
18
|
+
//http://www.jennyscrayoncollection.com/2021/06/all-current-lego-colors.html
|
|
19
|
+
//https://leonawicz.github.io/legocolors/reference/figures/README-plot-1.png
|
|
20
|
+
/*opts.colors = opts.colors || [
|
|
21
|
+
'#00852b', //darker green
|
|
22
|
+
'#afd246', //light green
|
|
23
|
+
'#fac80a', //dark yellow
|
|
24
|
+
'#bb805a', //brown
|
|
25
|
+
'#d67923', //mostard
|
|
26
|
+
'#cb4e29', //redish
|
|
27
|
+
'#b40000', //red
|
|
28
|
+
'#720012', //dark red
|
|
29
|
+
//"purple",
|
|
30
|
+
//"#eee" //whithe
|
|
31
|
+
]*/
|
|
32
|
+
|
|
33
|
+
opts.colDark = opts.colDark || '#333'
|
|
34
|
+
opts.colBright = opts.colBright || '#aaa'
|
|
35
|
+
opts.widthFactor = opts.widthFactor || 0.12
|
|
36
|
+
|
|
37
|
+
//reuse tanaka as basis
|
|
38
|
+
const ts = TanakaStyle.get(value, breaks, colors, opts)
|
|
39
|
+
//style to show limits between pieces
|
|
40
|
+
const sst = new StrokeStyle({
|
|
41
|
+
strokeColor: () => '#666',
|
|
42
|
+
strokeWidth: (c, r, z) => 0.2 * z,
|
|
43
|
+
filter: opts.filter,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
return [
|
|
47
|
+
ts[0],
|
|
48
|
+
sst,
|
|
49
|
+
ts[1],
|
|
50
|
+
new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright, filter: opts.filter }),
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {function(import('../core/Dataset.js').Cell):string} code
|
|
56
|
+
* @param {object} color
|
|
57
|
+
* @param {object} opts
|
|
58
|
+
* @returns {Array.<Style>}
|
|
59
|
+
*/
|
|
60
|
+
static getCategory(code, color, opts) {
|
|
61
|
+
opts = opts || {}
|
|
62
|
+
|
|
63
|
+
opts.colDark = opts.colDark || '#333'
|
|
64
|
+
opts.colBright = opts.colBright || '#aaa'
|
|
65
|
+
|
|
66
|
+
//
|
|
67
|
+
const s = new SquareColorCategoryWebGLStyle({ code: code, color: color })
|
|
68
|
+
//style to show limits between pieces
|
|
69
|
+
const sst = new StrokeStyle({ strokeColor: () => '#666', strokeWidth: (c, r, z) => 0.2 * z })
|
|
70
|
+
|
|
71
|
+
return [s, sst, new LegoTopStyle({ colDark: opts.colDark, colBright: opts.colBright })]
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A style to draw top circle of lego bricks.
|
|
77
|
+
*/
|
|
78
|
+
class LegoTopStyle extends Style {
|
|
79
|
+
/** @param {object|undefined} opts */
|
|
80
|
+
constructor(opts) {
|
|
81
|
+
super(opts)
|
|
82
|
+
opts = opts || {}
|
|
83
|
+
this.colDark = opts.colDark || '#333'
|
|
84
|
+
this.colBright = opts.colBright || '#aaa'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
draw(cells, geoCanvas, r) {
|
|
88
|
+
//filter
|
|
89
|
+
if (this.filter) cells = cells.filter(this.filter)
|
|
90
|
+
const ctx = geoCanvas.offscreenCtx
|
|
91
|
+
|
|
92
|
+
ctx.lineWidth = 0.6 * geoCanvas.view.z
|
|
93
|
+
|
|
94
|
+
//dark part
|
|
95
|
+
ctx.strokeStyle = this.colDark
|
|
96
|
+
for (let c of cells) {
|
|
97
|
+
ctx.beginPath()
|
|
98
|
+
ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), true)
|
|
99
|
+
ctx.stroke()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//bright part
|
|
103
|
+
ctx.strokeStyle = this.colBright
|
|
104
|
+
for (let c of cells) {
|
|
105
|
+
ctx.beginPath()
|
|
106
|
+
ctx.arc(c.x + r * 0.5, c.y + r * 0.5, r * 0.55 * 0.5, Math.PI / 4, -Math.PI * (3 / 4), false)
|
|
107
|
+
ctx.stroke()
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|