@hpcc-js/chart 3.6.3 → 3.6.5
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/LICENSE +43 -43
- package/README.md +93 -93
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +6 -6
- package/src/Area.md +176 -176
- package/src/Area.ts +12 -12
- package/src/Axis.css +34 -34
- package/src/Axis.ts +781 -781
- package/src/Bar.md +90 -90
- package/src/Bar.ts +9 -9
- package/src/Bubble.css +16 -16
- package/src/Bubble.md +69 -69
- package/src/Bubble.ts +196 -196
- package/src/BubbleXY.ts +14 -14
- package/src/Bullet.css +60 -60
- package/src/Bullet.md +104 -104
- package/src/Bullet.ts +176 -176
- package/src/Column.css +44 -44
- package/src/Column.md +90 -90
- package/src/Column.ts +684 -684
- package/src/Contour.md +88 -88
- package/src/Contour.ts +97 -97
- package/src/D3Cloud.ts +403 -403
- package/src/Gantt.md +119 -119
- package/src/Gantt.ts +14 -14
- package/src/Gauge.md +148 -148
- package/src/Gauge.ts +368 -368
- package/src/HalfPie.md +62 -62
- package/src/HalfPie.ts +26 -26
- package/src/Heat.md +42 -42
- package/src/Heat.ts +283 -283
- package/src/HexBin.css +9 -9
- package/src/HexBin.md +88 -88
- package/src/HexBin.ts +144 -144
- package/src/Line.css +6 -6
- package/src/Line.md +170 -170
- package/src/Line.ts +14 -14
- package/src/Pie.css +50 -50
- package/src/Pie.md +88 -88
- package/src/Pie.ts +546 -546
- package/src/QuarterPie.md +61 -61
- package/src/QuarterPie.ts +35 -35
- package/src/QuartileCandlestick.md +129 -129
- package/src/QuartileCandlestick.ts +349 -349
- package/src/Radar.css +15 -15
- package/src/Radar.md +104 -104
- package/src/Radar.ts +336 -336
- package/src/RadialBar.css +25 -25
- package/src/RadialBar.md +91 -91
- package/src/RadialBar.ts +217 -217
- package/src/Scatter.css +42 -42
- package/src/Scatter.md +163 -163
- package/src/Scatter.ts +412 -412
- package/src/StatChart.md +117 -117
- package/src/StatChart.ts +261 -261
- package/src/Step.md +163 -163
- package/src/Step.ts +12 -12
- package/src/Summary.css +56 -56
- package/src/Summary.md +219 -219
- package/src/Summary.ts +322 -322
- package/src/SummaryC.md +154 -154
- package/src/SummaryC.ts +240 -240
- package/src/WordCloud.css +3 -3
- package/src/WordCloud.md +144 -144
- package/src/WordCloud.ts +268 -268
- package/src/XYAxis.css +41 -41
- package/src/XYAxis.md +149 -149
- package/src/XYAxis.ts +809 -809
- package/src/__package__.ts +3 -3
- package/src/__tests__/heat.ts +71 -71
- package/src/__tests__/index.ts +3 -3
- package/src/__tests__/pie.ts +20 -20
- package/src/__tests__/stat.ts +16 -16
- package/src/__tests__/test3.ts +68 -68
- package/src/index.ts +28 -28
- package/src/test.ts +70 -70
- package/src/timeFormats.ts +26 -26
package/src/RadialBar.css
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
.chart_RadialBar path.arc {
|
|
2
|
-
opacity: 0.9;
|
|
3
|
-
transition: opacity 0.5s;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
.chart_RadialBar path.arc.selected {
|
|
7
|
-
stroke: red;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.chart_RadialBar path.arc:hover {
|
|
11
|
-
opacity: 0.7;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.chart_RadialBar .axis line,
|
|
15
|
-
.chart_RadialBar .axis circle {
|
|
16
|
-
stroke: #cccccc;
|
|
17
|
-
stroke-width: 1px
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
.chart_RadialBar .axis circle {
|
|
21
|
-
fill: none;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
.chart_RadialBar .r.axis text {
|
|
25
|
-
text-anchor: end
|
|
1
|
+
.chart_RadialBar path.arc {
|
|
2
|
+
opacity: 0.9;
|
|
3
|
+
transition: opacity 0.5s;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.chart_RadialBar path.arc.selected {
|
|
7
|
+
stroke: red;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.chart_RadialBar path.arc:hover {
|
|
11
|
+
opacity: 0.7;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.chart_RadialBar .axis line,
|
|
15
|
+
.chart_RadialBar .axis circle {
|
|
16
|
+
stroke: #cccccc;
|
|
17
|
+
stroke-width: 1px
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.chart_RadialBar .axis circle {
|
|
21
|
+
fill: none;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.chart_RadialBar .r.axis text {
|
|
25
|
+
text-anchor: end
|
|
26
26
|
}
|
package/src/RadialBar.md
CHANGED
|
@@ -1,91 +1,91 @@
|
|
|
1
|
-
# RadialBar
|
|
2
|
-
|
|
3
|
-
<!--meta
|
|
4
|
-
|
|
5
|
-
-->
|
|
6
|
-
|
|
7
|
-
RadialBar displays one category and one numeric value per data row.
|
|
8
|
-
|
|
9
|
-
<ClientOnly>
|
|
10
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
11
|
-
<div id="placeholder" style="height:400px">
|
|
12
|
-
</div>
|
|
13
|
-
<script type="module">
|
|
14
|
-
import { RadialBar } from "@hpcc-js/chart";
|
|
15
|
-
|
|
16
|
-
new RadialBar()
|
|
17
|
-
.target("placeholder")
|
|
18
|
-
.columns(["Category", "Value"])
|
|
19
|
-
.data([
|
|
20
|
-
["A", 144],
|
|
21
|
-
["B", 89],
|
|
22
|
-
["C", 55],
|
|
23
|
-
["D", 34]
|
|
24
|
-
])
|
|
25
|
-
.render()
|
|
26
|
-
;
|
|
27
|
-
</script>
|
|
28
|
-
</hpcc-vitepress>
|
|
29
|
-
</ClientOnly>
|
|
30
|
-
|
|
31
|
-
_valueMaxAngle_ sets the maximum angle of the largest value in the data that you provide.
|
|
32
|
-
|
|
33
|
-
_tickCount_ sets the target number of ticks to display along the circular axis. The tick count may be slightly lower or higher than the provided number as the axis attempts to place the ticks in sensible intervals.
|
|
34
|
-
|
|
35
|
-
<ClientOnly>
|
|
36
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
37
|
-
<div id="placeholder" style="height:400px">
|
|
38
|
-
</div>
|
|
39
|
-
<script type="module">
|
|
40
|
-
import { RadialBar } from "@hpcc-js/chart";
|
|
41
|
-
|
|
42
|
-
new RadialBar()
|
|
43
|
-
.target("placeholder")
|
|
44
|
-
.columns(["Category", "Value 1"])
|
|
45
|
-
.data([
|
|
46
|
-
["A", 144],
|
|
47
|
-
["B", 89],
|
|
48
|
-
["C", 55],
|
|
49
|
-
["D", 34]
|
|
50
|
-
])
|
|
51
|
-
.valueMaxAngle(90)
|
|
52
|
-
.tickCount(10)
|
|
53
|
-
.render()
|
|
54
|
-
;
|
|
55
|
-
</script>
|
|
56
|
-
</hpcc-vitepress>
|
|
57
|
-
</ClientOnly>
|
|
58
|
-
|
|
59
|
-
_domainPadding_ sets the ratio of white space to bar width.
|
|
60
|
-
|
|
61
|
-
_valueDomainHigh_ sets the maximum domain axis value.
|
|
62
|
-
|
|
63
|
-
<ClientOnly>
|
|
64
|
-
<hpcc-vitepress style="width:100%;height:600px">
|
|
65
|
-
<div id="placeholder" style="height:400px">
|
|
66
|
-
</div>
|
|
67
|
-
<script type="module">
|
|
68
|
-
import { RadialBar } from "@hpcc-js/chart";
|
|
69
|
-
|
|
70
|
-
new RadialBar()
|
|
71
|
-
.target("placeholder")
|
|
72
|
-
.columns(["Category", "Value 1"])
|
|
73
|
-
.data([
|
|
74
|
-
["A", 144],
|
|
75
|
-
["B", 89],
|
|
76
|
-
["C", 55],
|
|
77
|
-
["D", 34]
|
|
78
|
-
])
|
|
79
|
-
.domainPadding(0.62)
|
|
80
|
-
.valueDomainHigh(200)
|
|
81
|
-
.render()
|
|
82
|
-
;
|
|
83
|
-
</script>
|
|
84
|
-
</hpcc-vitepress>
|
|
85
|
-
</ClientOnly>
|
|
86
|
-
|
|
87
|
-
## API
|
|
88
|
-
|
|
89
|
-
## Published Properties
|
|
90
|
-
```@hpcc-js/chart:RadialBar
|
|
91
|
-
```
|
|
1
|
+
# RadialBar
|
|
2
|
+
|
|
3
|
+
<!--meta
|
|
4
|
+
|
|
5
|
+
-->
|
|
6
|
+
|
|
7
|
+
RadialBar displays one category and one numeric value per data row.
|
|
8
|
+
|
|
9
|
+
<ClientOnly>
|
|
10
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
11
|
+
<div id="placeholder" style="height:400px">
|
|
12
|
+
</div>
|
|
13
|
+
<script type="module">
|
|
14
|
+
import { RadialBar } from "@hpcc-js/chart";
|
|
15
|
+
|
|
16
|
+
new RadialBar()
|
|
17
|
+
.target("placeholder")
|
|
18
|
+
.columns(["Category", "Value"])
|
|
19
|
+
.data([
|
|
20
|
+
["A", 144],
|
|
21
|
+
["B", 89],
|
|
22
|
+
["C", 55],
|
|
23
|
+
["D", 34]
|
|
24
|
+
])
|
|
25
|
+
.render()
|
|
26
|
+
;
|
|
27
|
+
</script>
|
|
28
|
+
</hpcc-vitepress>
|
|
29
|
+
</ClientOnly>
|
|
30
|
+
|
|
31
|
+
_valueMaxAngle_ sets the maximum angle of the largest value in the data that you provide.
|
|
32
|
+
|
|
33
|
+
_tickCount_ sets the target number of ticks to display along the circular axis. The tick count may be slightly lower or higher than the provided number as the axis attempts to place the ticks in sensible intervals.
|
|
34
|
+
|
|
35
|
+
<ClientOnly>
|
|
36
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
37
|
+
<div id="placeholder" style="height:400px">
|
|
38
|
+
</div>
|
|
39
|
+
<script type="module">
|
|
40
|
+
import { RadialBar } from "@hpcc-js/chart";
|
|
41
|
+
|
|
42
|
+
new RadialBar()
|
|
43
|
+
.target("placeholder")
|
|
44
|
+
.columns(["Category", "Value 1"])
|
|
45
|
+
.data([
|
|
46
|
+
["A", 144],
|
|
47
|
+
["B", 89],
|
|
48
|
+
["C", 55],
|
|
49
|
+
["D", 34]
|
|
50
|
+
])
|
|
51
|
+
.valueMaxAngle(90)
|
|
52
|
+
.tickCount(10)
|
|
53
|
+
.render()
|
|
54
|
+
;
|
|
55
|
+
</script>
|
|
56
|
+
</hpcc-vitepress>
|
|
57
|
+
</ClientOnly>
|
|
58
|
+
|
|
59
|
+
_domainPadding_ sets the ratio of white space to bar width.
|
|
60
|
+
|
|
61
|
+
_valueDomainHigh_ sets the maximum domain axis value.
|
|
62
|
+
|
|
63
|
+
<ClientOnly>
|
|
64
|
+
<hpcc-vitepress style="width:100%;height:600px">
|
|
65
|
+
<div id="placeholder" style="height:400px">
|
|
66
|
+
</div>
|
|
67
|
+
<script type="module">
|
|
68
|
+
import { RadialBar } from "@hpcc-js/chart";
|
|
69
|
+
|
|
70
|
+
new RadialBar()
|
|
71
|
+
.target("placeholder")
|
|
72
|
+
.columns(["Category", "Value 1"])
|
|
73
|
+
.data([
|
|
74
|
+
["A", 144],
|
|
75
|
+
["B", 89],
|
|
76
|
+
["C", 55],
|
|
77
|
+
["D", 34]
|
|
78
|
+
])
|
|
79
|
+
.domainPadding(0.62)
|
|
80
|
+
.valueDomainHigh(200)
|
|
81
|
+
.render()
|
|
82
|
+
;
|
|
83
|
+
</script>
|
|
84
|
+
</hpcc-vitepress>
|
|
85
|
+
</ClientOnly>
|
|
86
|
+
|
|
87
|
+
## API
|
|
88
|
+
|
|
89
|
+
## Published Properties
|
|
90
|
+
```@hpcc-js/chart:RadialBar
|
|
91
|
+
```
|
package/src/RadialBar.ts
CHANGED
|
@@ -1,217 +1,217 @@
|
|
|
1
|
-
import { INDChart, ITooltip } from "@hpcc-js/api";
|
|
2
|
-
import { InputField, SVGWidget, Utility } from "@hpcc-js/common";
|
|
3
|
-
import { interpolate as d3Interpolate } from "d3-interpolate";
|
|
4
|
-
import { scaleBand as d3ScaleBand, scaleLinear as d3ScaleLinear } from "d3-scale";
|
|
5
|
-
import { arc as d3Arc } from "d3-shape";
|
|
6
|
-
|
|
7
|
-
import "../src/RadialBar.css";
|
|
8
|
-
|
|
9
|
-
export class RadialBar extends SVGWidget {
|
|
10
|
-
static __inputs: InputField[] = [{
|
|
11
|
-
id: "label",
|
|
12
|
-
type: "any"
|
|
13
|
-
}, {
|
|
14
|
-
id: "values",
|
|
15
|
-
type: "number"
|
|
16
|
-
}];
|
|
17
|
-
|
|
18
|
-
private _domainScale = d3ScaleBand();
|
|
19
|
-
private _valueScale = d3ScaleLinear();
|
|
20
|
-
private _d3Arc = d3Arc<[string, number]>()
|
|
21
|
-
.startAngle(0)
|
|
22
|
-
.endAngle((d) => this._valueScale(d[1]))
|
|
23
|
-
;
|
|
24
|
-
|
|
25
|
-
protected _arcs;
|
|
26
|
-
protected _axialAxis;
|
|
27
|
-
protected _radialAxis;
|
|
28
|
-
|
|
29
|
-
constructor() {
|
|
30
|
-
super();
|
|
31
|
-
INDChart.call(this);
|
|
32
|
-
ITooltip.call(this);
|
|
33
|
-
Utility.SimpleSelectionMixin.call(this);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
enter(domNode, element) {
|
|
37
|
-
super.enter(domNode, element);
|
|
38
|
-
this._selection.widgetElement(element);
|
|
39
|
-
this.tooltipHTML(d => {
|
|
40
|
-
return this.tooltipFormat({ label: d[0], value: d[1] });
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
this._radialAxis = element.append("g")
|
|
44
|
-
.attr("class", "r axis")
|
|
45
|
-
;
|
|
46
|
-
this._axialAxis = element.append("g")
|
|
47
|
-
.attr("class", "a axis")
|
|
48
|
-
;
|
|
49
|
-
this._arcs = element.append("g")
|
|
50
|
-
.attr("class", "data")
|
|
51
|
-
;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
update(domNode, element) {
|
|
55
|
-
super.update(domNode, element);
|
|
56
|
-
const context = this;
|
|
57
|
-
const maxValue = Math.max(this.valueDomainHigh_exists() ? this.valueDomainHigh() : 0, ...this.data().map(d => d[1]));
|
|
58
|
-
|
|
59
|
-
this._valueScale
|
|
60
|
-
.domain([0, maxValue])
|
|
61
|
-
.range([0, this.radians(this.valueMaxAngle())])
|
|
62
|
-
;
|
|
63
|
-
|
|
64
|
-
const ticks = this._valueScale.ticks(this.tickCount());
|
|
65
|
-
|
|
66
|
-
const maxTextWidth = this.textSize(ticks.map(d => "" + d), "Verdana", 12).width;
|
|
67
|
-
const chartRadius = (Math.min(this.width() - (10 + maxTextWidth) * 2, this.height() - (10 + 12) * 2) / 2);
|
|
68
|
-
|
|
69
|
-
// Domain Axis (x-axis) ---
|
|
70
|
-
const domainData = this.data().map(d => d[0]);
|
|
71
|
-
|
|
72
|
-
this._domainScale
|
|
73
|
-
.domain(domainData)
|
|
74
|
-
.range([0, chartRadius])
|
|
75
|
-
.padding(this.domainPadding())
|
|
76
|
-
;
|
|
77
|
-
const domainPadding = this._domainScale.step() * this._domainScale.padding();
|
|
78
|
-
|
|
79
|
-
const domainCircles = this._radialAxis.selectAll("circle").data(domainData);
|
|
80
|
-
domainCircles.enter().append("circle")
|
|
81
|
-
.attr("fill", "transparent")
|
|
82
|
-
.merge(domainCircles)
|
|
83
|
-
.attr("r", d => this._domainScale(d) + this._domainScale.step() - domainPadding / 2)
|
|
84
|
-
;
|
|
85
|
-
domainCircles.exit().remove();
|
|
86
|
-
|
|
87
|
-
const domainText = this._radialAxis.selectAll(".arc-text").data(domainData);
|
|
88
|
-
domainText.enter().append("text")
|
|
89
|
-
.attr("class", "arc-text")
|
|
90
|
-
.attr("x", -4)
|
|
91
|
-
.attr("alignment-baseline", "middle")
|
|
92
|
-
.attr("text-anchor", "end")
|
|
93
|
-
.merge(domainText)
|
|
94
|
-
.attr("y", d => -this._domainScale(d) - this._domainScale.bandwidth() / 2)
|
|
95
|
-
.text(d => d);
|
|
96
|
-
domainText.exit().remove();
|
|
97
|
-
|
|
98
|
-
// Value Axis (y-axis) ---
|
|
99
|
-
const valueLines = this._axialAxis.selectAll("line").data(ticks);
|
|
100
|
-
valueLines.enter().append("line")
|
|
101
|
-
.merge(valueLines)
|
|
102
|
-
.attr("x2", d => chartRadius * Math.cos(this._valueScale(d) - this.radians(90)))
|
|
103
|
-
.attr("y2", d => chartRadius * Math.sin(this._valueScale(d) - this.radians(90)))
|
|
104
|
-
;
|
|
105
|
-
valueLines.exit().remove();
|
|
106
|
-
|
|
107
|
-
const valueText = this._axialAxis.selectAll("text").data(ticks);
|
|
108
|
-
valueText.enter().append("text")
|
|
109
|
-
.style("dominant-baseline", "central")
|
|
110
|
-
.merge(valueText)
|
|
111
|
-
.attr("x", d => (chartRadius + 10) * Math.cos(this._valueScale(d) - this.radians(90)))
|
|
112
|
-
.attr("y", d => (chartRadius + 10) * Math.sin(this._valueScale(d) - this.radians(90)))
|
|
113
|
-
.style("text-anchor", d => {
|
|
114
|
-
const middleZone = 20;
|
|
115
|
-
const angle = this.degrees(this._valueScale(d));
|
|
116
|
-
if (angle >= 0 && angle <= middleZone ||
|
|
117
|
-
angle >= 180 - middleZone && angle <= 180 + middleZone ||
|
|
118
|
-
angle >= 360 - middleZone && angle <= 360
|
|
119
|
-
) {
|
|
120
|
-
return "middle";
|
|
121
|
-
} else if (angle >= 180 && angle <= 360) {
|
|
122
|
-
return "end";
|
|
123
|
-
} else {
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
.text(d => d)
|
|
128
|
-
;
|
|
129
|
-
valueText.exit().remove();
|
|
130
|
-
|
|
131
|
-
const valueColumn = this.columns().length > 1 ? this.columns()[1] : "";
|
|
132
|
-
// Data (arcs) ---
|
|
133
|
-
this._d3Arc
|
|
134
|
-
.innerRadius(d => this._domainScale(d[0]))
|
|
135
|
-
.outerRadius(d => this._domainScale(d[0]) + this._domainScale.bandwidth())
|
|
136
|
-
;
|
|
137
|
-
const arcs = this._arcs.selectAll("path").data(this.data(), d => d[0]);
|
|
138
|
-
arcs.enter().append("path")
|
|
139
|
-
.attr("class", "arc")
|
|
140
|
-
.call(this._selection.enter.bind(this._selection))
|
|
141
|
-
.on("mouseout.tooltip", this.tooltip.hide)
|
|
142
|
-
.on("mousemove.tooltip", this.tooltip.show)
|
|
143
|
-
.on("click", function (d: any, _idx) {
|
|
144
|
-
context.click(context.rowToObj(d), valueColumn, context._selection.selected(this));
|
|
145
|
-
})
|
|
146
|
-
.on("dblclick", function (d: any, _idx) {
|
|
147
|
-
context.dblclick(context.rowToObj(d), valueColumn, context._selection.selected(this));
|
|
148
|
-
})
|
|
149
|
-
.merge(arcs)
|
|
150
|
-
.style("fill", (d, i) => this.fillColor(d, d[0], d[1]))
|
|
151
|
-
.transition()
|
|
152
|
-
.delay((d, i) => i * this.transitionDelay())
|
|
153
|
-
.duration(this.transitionDuration())
|
|
154
|
-
.attrTween("d", (d, indx) => {
|
|
155
|
-
const interpolate = d3Interpolate(d._current || 0, d[1]);
|
|
156
|
-
d._current = d[1];
|
|
157
|
-
return t => this._d3Arc([d[0], interpolate(t)], indx);
|
|
158
|
-
})
|
|
159
|
-
;
|
|
160
|
-
arcs.exit().remove();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
degrees(radians) {
|
|
164
|
-
return radians * 180 / Math.PI;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
radians(degrees) {
|
|
168
|
-
return degrees * Math.PI / 180;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
RadialBar.prototype._class += " chart_RadialBar";
|
|
173
|
-
RadialBar.prototype.implements(INDChart.prototype);
|
|
174
|
-
RadialBar.prototype.implements(ITooltip.prototype);
|
|
175
|
-
RadialBar.prototype.mixin(Utility.SimpleSelectionMixin);
|
|
176
|
-
|
|
177
|
-
export interface RadialBar {
|
|
178
|
-
paletteID(): string;
|
|
179
|
-
paletteID(_: string): this;
|
|
180
|
-
tickCount(): number;
|
|
181
|
-
tickCount(_: number): this;
|
|
182
|
-
domainPadding(): number;
|
|
183
|
-
domainPadding(_: number): this;
|
|
184
|
-
valueMaxAngle(): number;
|
|
185
|
-
valueMaxAngle(_: number): this;
|
|
186
|
-
valueDomainHigh(): number;
|
|
187
|
-
valueDomainHigh(_: number): this;
|
|
188
|
-
valueDomainHigh_exists(): boolean;
|
|
189
|
-
transitionDelay(): number;
|
|
190
|
-
transitionDelay(_: number): this;
|
|
191
|
-
transitionDuration(): number;
|
|
192
|
-
transitionDuration(_: number): this;
|
|
193
|
-
|
|
194
|
-
// INDChart
|
|
195
|
-
_palette;
|
|
196
|
-
fillColor(row, column, value): string;
|
|
197
|
-
strokeColor(row, column, value): string;
|
|
198
|
-
textColor(row, column, value): string;
|
|
199
|
-
click(row, column, selected): void;
|
|
200
|
-
dblclick(row, column, selected): void;
|
|
201
|
-
|
|
202
|
-
// ITooltip
|
|
203
|
-
tooltip;
|
|
204
|
-
tooltipHTML(_): string;
|
|
205
|
-
tooltipFormat(_): string;
|
|
206
|
-
|
|
207
|
-
// SimpleSelectionMixin
|
|
208
|
-
_selection;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
RadialBar.prototype.publish("paletteID", "default", "set", "Color palette for this widget", RadialBar.prototype._palette.switch());
|
|
212
|
-
RadialBar.prototype.publish("tickCount", 10, "number", "Number of ticks to display");
|
|
213
|
-
RadialBar.prototype.publish("domainPadding", 0.25, "number", "Padding between chart edge and container edge (0..1)");
|
|
214
|
-
RadialBar.prototype.publish("valueMaxAngle", 270, "number", "Maximum angular length of a bar (degrees)");
|
|
215
|
-
RadialBar.prototype.publish("valueDomainHigh", null, "number", "Value domain high", undefined, { optional: true });
|
|
216
|
-
RadialBar.prototype.publish("transitionDelay", 100, "number", "Delay between the start of each row animation (ms)");
|
|
217
|
-
RadialBar.prototype.publish("transitionDuration", 750, "number", "Duration of a row's animation (ms)");
|
|
1
|
+
import { INDChart, ITooltip } from "@hpcc-js/api";
|
|
2
|
+
import { InputField, SVGWidget, Utility } from "@hpcc-js/common";
|
|
3
|
+
import { interpolate as d3Interpolate } from "d3-interpolate";
|
|
4
|
+
import { scaleBand as d3ScaleBand, scaleLinear as d3ScaleLinear } from "d3-scale";
|
|
5
|
+
import { arc as d3Arc } from "d3-shape";
|
|
6
|
+
|
|
7
|
+
import "../src/RadialBar.css";
|
|
8
|
+
|
|
9
|
+
export class RadialBar extends SVGWidget {
|
|
10
|
+
static __inputs: InputField[] = [{
|
|
11
|
+
id: "label",
|
|
12
|
+
type: "any"
|
|
13
|
+
}, {
|
|
14
|
+
id: "values",
|
|
15
|
+
type: "number"
|
|
16
|
+
}];
|
|
17
|
+
|
|
18
|
+
private _domainScale = d3ScaleBand();
|
|
19
|
+
private _valueScale = d3ScaleLinear();
|
|
20
|
+
private _d3Arc = d3Arc<[string, number]>()
|
|
21
|
+
.startAngle(0)
|
|
22
|
+
.endAngle((d) => this._valueScale(d[1]))
|
|
23
|
+
;
|
|
24
|
+
|
|
25
|
+
protected _arcs;
|
|
26
|
+
protected _axialAxis;
|
|
27
|
+
protected _radialAxis;
|
|
28
|
+
|
|
29
|
+
constructor() {
|
|
30
|
+
super();
|
|
31
|
+
INDChart.call(this);
|
|
32
|
+
ITooltip.call(this);
|
|
33
|
+
Utility.SimpleSelectionMixin.call(this);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
enter(domNode, element) {
|
|
37
|
+
super.enter(domNode, element);
|
|
38
|
+
this._selection.widgetElement(element);
|
|
39
|
+
this.tooltipHTML(d => {
|
|
40
|
+
return this.tooltipFormat({ label: d[0], value: d[1] });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
this._radialAxis = element.append("g")
|
|
44
|
+
.attr("class", "r axis")
|
|
45
|
+
;
|
|
46
|
+
this._axialAxis = element.append("g")
|
|
47
|
+
.attr("class", "a axis")
|
|
48
|
+
;
|
|
49
|
+
this._arcs = element.append("g")
|
|
50
|
+
.attr("class", "data")
|
|
51
|
+
;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
update(domNode, element) {
|
|
55
|
+
super.update(domNode, element);
|
|
56
|
+
const context = this;
|
|
57
|
+
const maxValue = Math.max(this.valueDomainHigh_exists() ? this.valueDomainHigh() : 0, ...this.data().map(d => d[1]));
|
|
58
|
+
|
|
59
|
+
this._valueScale
|
|
60
|
+
.domain([0, maxValue])
|
|
61
|
+
.range([0, this.radians(this.valueMaxAngle())])
|
|
62
|
+
;
|
|
63
|
+
|
|
64
|
+
const ticks = this._valueScale.ticks(this.tickCount());
|
|
65
|
+
|
|
66
|
+
const maxTextWidth = this.textSize(ticks.map(d => "" + d), "Verdana", 12).width;
|
|
67
|
+
const chartRadius = (Math.min(this.width() - (10 + maxTextWidth) * 2, this.height() - (10 + 12) * 2) / 2);
|
|
68
|
+
|
|
69
|
+
// Domain Axis (x-axis) ---
|
|
70
|
+
const domainData = this.data().map(d => d[0]);
|
|
71
|
+
|
|
72
|
+
this._domainScale
|
|
73
|
+
.domain(domainData)
|
|
74
|
+
.range([0, chartRadius])
|
|
75
|
+
.padding(this.domainPadding())
|
|
76
|
+
;
|
|
77
|
+
const domainPadding = this._domainScale.step() * this._domainScale.padding();
|
|
78
|
+
|
|
79
|
+
const domainCircles = this._radialAxis.selectAll("circle").data(domainData);
|
|
80
|
+
domainCircles.enter().append("circle")
|
|
81
|
+
.attr("fill", "transparent")
|
|
82
|
+
.merge(domainCircles)
|
|
83
|
+
.attr("r", d => this._domainScale(d) + this._domainScale.step() - domainPadding / 2)
|
|
84
|
+
;
|
|
85
|
+
domainCircles.exit().remove();
|
|
86
|
+
|
|
87
|
+
const domainText = this._radialAxis.selectAll(".arc-text").data(domainData);
|
|
88
|
+
domainText.enter().append("text")
|
|
89
|
+
.attr("class", "arc-text")
|
|
90
|
+
.attr("x", -4)
|
|
91
|
+
.attr("alignment-baseline", "middle")
|
|
92
|
+
.attr("text-anchor", "end")
|
|
93
|
+
.merge(domainText)
|
|
94
|
+
.attr("y", d => -this._domainScale(d) - this._domainScale.bandwidth() / 2)
|
|
95
|
+
.text(d => d);
|
|
96
|
+
domainText.exit().remove();
|
|
97
|
+
|
|
98
|
+
// Value Axis (y-axis) ---
|
|
99
|
+
const valueLines = this._axialAxis.selectAll("line").data(ticks);
|
|
100
|
+
valueLines.enter().append("line")
|
|
101
|
+
.merge(valueLines)
|
|
102
|
+
.attr("x2", d => chartRadius * Math.cos(this._valueScale(d) - this.radians(90)))
|
|
103
|
+
.attr("y2", d => chartRadius * Math.sin(this._valueScale(d) - this.radians(90)))
|
|
104
|
+
;
|
|
105
|
+
valueLines.exit().remove();
|
|
106
|
+
|
|
107
|
+
const valueText = this._axialAxis.selectAll("text").data(ticks);
|
|
108
|
+
valueText.enter().append("text")
|
|
109
|
+
.style("dominant-baseline", "central")
|
|
110
|
+
.merge(valueText)
|
|
111
|
+
.attr("x", d => (chartRadius + 10) * Math.cos(this._valueScale(d) - this.radians(90)))
|
|
112
|
+
.attr("y", d => (chartRadius + 10) * Math.sin(this._valueScale(d) - this.radians(90)))
|
|
113
|
+
.style("text-anchor", d => {
|
|
114
|
+
const middleZone = 20;
|
|
115
|
+
const angle = this.degrees(this._valueScale(d));
|
|
116
|
+
if (angle >= 0 && angle <= middleZone ||
|
|
117
|
+
angle >= 180 - middleZone && angle <= 180 + middleZone ||
|
|
118
|
+
angle >= 360 - middleZone && angle <= 360
|
|
119
|
+
) {
|
|
120
|
+
return "middle";
|
|
121
|
+
} else if (angle >= 180 && angle <= 360) {
|
|
122
|
+
return "end";
|
|
123
|
+
} else {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
.text(d => d)
|
|
128
|
+
;
|
|
129
|
+
valueText.exit().remove();
|
|
130
|
+
|
|
131
|
+
const valueColumn = this.columns().length > 1 ? this.columns()[1] : "";
|
|
132
|
+
// Data (arcs) ---
|
|
133
|
+
this._d3Arc
|
|
134
|
+
.innerRadius(d => this._domainScale(d[0]))
|
|
135
|
+
.outerRadius(d => this._domainScale(d[0]) + this._domainScale.bandwidth())
|
|
136
|
+
;
|
|
137
|
+
const arcs = this._arcs.selectAll("path").data(this.data(), d => d[0]);
|
|
138
|
+
arcs.enter().append("path")
|
|
139
|
+
.attr("class", "arc")
|
|
140
|
+
.call(this._selection.enter.bind(this._selection))
|
|
141
|
+
.on("mouseout.tooltip", this.tooltip.hide)
|
|
142
|
+
.on("mousemove.tooltip", this.tooltip.show)
|
|
143
|
+
.on("click", function (d: any, _idx) {
|
|
144
|
+
context.click(context.rowToObj(d), valueColumn, context._selection.selected(this));
|
|
145
|
+
})
|
|
146
|
+
.on("dblclick", function (d: any, _idx) {
|
|
147
|
+
context.dblclick(context.rowToObj(d), valueColumn, context._selection.selected(this));
|
|
148
|
+
})
|
|
149
|
+
.merge(arcs)
|
|
150
|
+
.style("fill", (d, i) => this.fillColor(d, d[0], d[1]))
|
|
151
|
+
.transition()
|
|
152
|
+
.delay((d, i) => i * this.transitionDelay())
|
|
153
|
+
.duration(this.transitionDuration())
|
|
154
|
+
.attrTween("d", (d, indx) => {
|
|
155
|
+
const interpolate = d3Interpolate(d._current || 0, d[1]);
|
|
156
|
+
d._current = d[1];
|
|
157
|
+
return t => this._d3Arc([d[0], interpolate(t)], indx);
|
|
158
|
+
})
|
|
159
|
+
;
|
|
160
|
+
arcs.exit().remove();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
degrees(radians) {
|
|
164
|
+
return radians * 180 / Math.PI;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
radians(degrees) {
|
|
168
|
+
return degrees * Math.PI / 180;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
RadialBar.prototype._class += " chart_RadialBar";
|
|
173
|
+
RadialBar.prototype.implements(INDChart.prototype);
|
|
174
|
+
RadialBar.prototype.implements(ITooltip.prototype);
|
|
175
|
+
RadialBar.prototype.mixin(Utility.SimpleSelectionMixin);
|
|
176
|
+
|
|
177
|
+
export interface RadialBar {
|
|
178
|
+
paletteID(): string;
|
|
179
|
+
paletteID(_: string): this;
|
|
180
|
+
tickCount(): number;
|
|
181
|
+
tickCount(_: number): this;
|
|
182
|
+
domainPadding(): number;
|
|
183
|
+
domainPadding(_: number): this;
|
|
184
|
+
valueMaxAngle(): number;
|
|
185
|
+
valueMaxAngle(_: number): this;
|
|
186
|
+
valueDomainHigh(): number;
|
|
187
|
+
valueDomainHigh(_: number): this;
|
|
188
|
+
valueDomainHigh_exists(): boolean;
|
|
189
|
+
transitionDelay(): number;
|
|
190
|
+
transitionDelay(_: number): this;
|
|
191
|
+
transitionDuration(): number;
|
|
192
|
+
transitionDuration(_: number): this;
|
|
193
|
+
|
|
194
|
+
// INDChart
|
|
195
|
+
_palette;
|
|
196
|
+
fillColor(row, column, value): string;
|
|
197
|
+
strokeColor(row, column, value): string;
|
|
198
|
+
textColor(row, column, value): string;
|
|
199
|
+
click(row, column, selected): void;
|
|
200
|
+
dblclick(row, column, selected): void;
|
|
201
|
+
|
|
202
|
+
// ITooltip
|
|
203
|
+
tooltip;
|
|
204
|
+
tooltipHTML(_): string;
|
|
205
|
+
tooltipFormat(_): string;
|
|
206
|
+
|
|
207
|
+
// SimpleSelectionMixin
|
|
208
|
+
_selection;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
RadialBar.prototype.publish("paletteID", "default", "set", "Color palette for this widget", RadialBar.prototype._palette.switch());
|
|
212
|
+
RadialBar.prototype.publish("tickCount", 10, "number", "Number of ticks to display");
|
|
213
|
+
RadialBar.prototype.publish("domainPadding", 0.25, "number", "Padding between chart edge and container edge (0..1)");
|
|
214
|
+
RadialBar.prototype.publish("valueMaxAngle", 270, "number", "Maximum angular length of a bar (degrees)");
|
|
215
|
+
RadialBar.prototype.publish("valueDomainHigh", null, "number", "Value domain high", undefined, { optional: true });
|
|
216
|
+
RadialBar.prototype.publish("transitionDelay", 100, "number", "Delay between the start of each row animation (ms)");
|
|
217
|
+
RadialBar.prototype.publish("transitionDuration", 750, "number", "Duration of a row's animation (ms)");
|