@hpcc-js/chart 2.86.3 → 2.86.4

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 (83) hide show
  1. package/LICENSE +43 -43
  2. package/README.md +93 -93
  3. package/dist/index.es6.js +2 -2
  4. package/dist/index.es6.js.map +1 -1
  5. package/dist/index.js +2 -2
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.min.js +1 -1
  8. package/dist/index.min.js.map +1 -1
  9. package/package.json +6 -6
  10. package/src/Area.md +176 -176
  11. package/src/Area.ts +12 -12
  12. package/src/Axis.css +34 -34
  13. package/src/Axis.ts +733 -733
  14. package/src/Bar.md +90 -90
  15. package/src/Bar.ts +9 -9
  16. package/src/Bubble.css +16 -16
  17. package/src/Bubble.md +69 -69
  18. package/src/Bubble.ts +191 -191
  19. package/src/BubbleXY.ts +14 -14
  20. package/src/Bullet.css +60 -60
  21. package/src/Bullet.md +104 -104
  22. package/src/Bullet.ts +167 -167
  23. package/src/Column.css +17 -17
  24. package/src/Column.md +90 -90
  25. package/src/Column.ts +659 -659
  26. package/src/Contour.md +88 -88
  27. package/src/Contour.ts +97 -97
  28. package/src/D3Cloud.ts +400 -400
  29. package/src/Gantt.md +119 -119
  30. package/src/Gantt.ts +14 -14
  31. package/src/Gauge.md +148 -148
  32. package/src/Gauge.ts +358 -358
  33. package/src/HalfPie.md +62 -62
  34. package/src/HalfPie.ts +26 -26
  35. package/src/Heat.md +42 -42
  36. package/src/Heat.ts +283 -283
  37. package/src/HexBin.css +9 -9
  38. package/src/HexBin.md +88 -88
  39. package/src/HexBin.ts +139 -139
  40. package/src/Line.css +6 -6
  41. package/src/Line.md +170 -170
  42. package/src/Line.ts +14 -14
  43. package/src/Pie.css +23 -23
  44. package/src/Pie.md +88 -88
  45. package/src/Pie.ts +503 -503
  46. package/src/QuarterPie.md +61 -61
  47. package/src/QuarterPie.ts +35 -35
  48. package/src/QuartileCandlestick.md +129 -129
  49. package/src/QuartileCandlestick.ts +349 -349
  50. package/src/Radar.css +15 -15
  51. package/src/Radar.md +104 -104
  52. package/src/Radar.ts +336 -336
  53. package/src/RadialBar.css +25 -25
  54. package/src/RadialBar.md +91 -91
  55. package/src/RadialBar.ts +212 -212
  56. package/src/Scatter.css +16 -16
  57. package/src/Scatter.md +163 -163
  58. package/src/Scatter.ts +376 -376
  59. package/src/StatChart.md +117 -117
  60. package/src/StatChart.ts +253 -253
  61. package/src/Step.md +163 -163
  62. package/src/Step.ts +12 -12
  63. package/src/Summary.css +56 -56
  64. package/src/Summary.md +219 -219
  65. package/src/Summary.ts +322 -322
  66. package/src/SummaryC.md +154 -154
  67. package/src/SummaryC.ts +240 -240
  68. package/src/WordCloud.css +3 -3
  69. package/src/WordCloud.md +144 -144
  70. package/src/WordCloud.ts +263 -263
  71. package/src/XYAxis.css +41 -41
  72. package/src/XYAxis.md +149 -149
  73. package/src/XYAxis.ts +803 -803
  74. package/src/__package__.ts +3 -3
  75. package/src/__tests__/heat.ts +71 -71
  76. package/src/__tests__/index.ts +3 -3
  77. package/src/__tests__/pie.ts +20 -20
  78. package/src/__tests__/stat.ts +16 -16
  79. package/src/__tests__/test3.ts +69 -69
  80. package/src/index.ts +27 -27
  81. package/src/test.ts +71 -71
  82. package/types/__package__.d.ts +2 -2
  83. package/types-3.4/__package__.d.ts +2 -2
package/src/Radar.ts CHANGED
@@ -1,336 +1,336 @@
1
- import { INDChart, ITooltip } from "@hpcc-js/api";
2
- import { SVGWidget, Utility } from "@hpcc-js/common";
3
- import { select as d3Select } from "d3-selection";
4
-
5
- import "../src/Radar.css";
6
- export class Radar extends SVGWidget {
7
-
8
- constructor() {
9
- super();
10
- INDChart.call(this);
11
- ITooltip.call(this);
12
- Utility.SimpleSelectionMixin.call(this);
13
- }
14
-
15
- mapShape(shape) {
16
- switch (shape) {
17
- case "rectangle":
18
- return "rect";
19
- case "circle":
20
- return "circle";
21
- case "cross":
22
- return "path";
23
- default:
24
- }
25
- }
26
- setPointAttributes(element, x, y) {
27
- const shape = this.mapShape(this.pointShape());
28
- const context = this;
29
- switch (shape) {
30
- case "rect":
31
- element
32
- .attr("width", context.pointSize())
33
- .attr("height", context.pointSize())
34
- .style("fill", d => this.strokeColor(d.data, d.column, d.value))
35
- ;
36
- break;
37
- case "circle":
38
- element
39
- .attr("r", context.pointSize() / 2)
40
- .attr("cx", x)
41
- .attr("cy", y)
42
- .style("fill", d => this.strokeColor(d.data, d.column, d.value))
43
- ;
44
- break;
45
- case "path":
46
- const half_size = context.pointSize() / 2;
47
- element
48
- .attr("d", function (d: any) {
49
- return "M" + (x - half_size) + " " + (y - half_size) + " " +
50
- "L" + (x + half_size) + " " + (y + half_size) + " " +
51
- "M" + (x - half_size) + " " + (y + half_size) + " " +
52
- "L" + (x + half_size) + " " + (y - half_size);
53
- })
54
- .style("stroke", d => this.strokeColor(d.data, d.column, d.value))
55
- ;
56
- break;
57
- default:
58
- }
59
- }
60
- enter(domNode, element) {
61
- super.enter(domNode, element);
62
- this._selection.widgetElement(element);
63
-
64
- this
65
- .tooltipHTML(d => {
66
- return this.tooltipFormat({ label: d.label, series: d.column, value: d.value });
67
- })
68
- ;
69
- }
70
- update(domNode, element) {
71
- super.update(domNode, element);
72
- this._palette = this._palette.switch(this.paletteID());
73
- const context = this;
74
- const h = this.height();
75
- const w = this.width();
76
- const half_h = (h / 2);
77
- const half_w = (w / 2);
78
-
79
- const columns = this.columns();
80
- const data = this.data();
81
- const flatData = this.flattenData(columns, data).map((d: any, idx: number) => {
82
- d.shape = this.mapShape(this.pointShape());
83
- d.column = columns[d.colIdx];
84
- d.row = data[idx];
85
- return d;
86
- });
87
- const domain_points = [];
88
- const arc = this.degrees2radians(360 / this.data().length);
89
- const max_label_h = this.fontSize();
90
- let max_label_w = 0;
91
- flatData.filter(n => n.colIdx === 1).forEach(n => {
92
- const isize = super.textSize(n.label, `${this.fontFamily()}`, this.fontSize());
93
- if (max_label_w < isize.width) max_label_w = isize.width;
94
- });
95
- const radius = Math.min(half_h - max_label_h, half_w - max_label_w);
96
- const labels = element
97
- .selectAll(".label")
98
- .data(flatData.filter(n => n.colIdx === 1))
99
- ;
100
- const max_val = Math.max.apply(context, flatData.map(n => n.value));
101
- labels.enter()
102
- .append("text")
103
- .attr("class", "label")
104
- .attr("text-anchor", "middle")
105
- .merge(labels)
106
- .attr("font-size", this.fontSize())
107
- .attr("font-family", this.fontFamily())
108
- .each(function (this: SVGElement, n, i) {
109
- const xy = context.polar2cartesian(radius, (i * arc) - (Math.PI / 2));
110
- domain_points.push(xy.map(n => n * context.labelPaddingRatio()));
111
- let text_anchor = "middle";
112
- const _x = Math.round(xy[0]);
113
- text_anchor = _x > 0 ? "start" : text_anchor;
114
- text_anchor = _x < 0 ? "end" : text_anchor;
115
- d3Select(this)
116
- .attr("text-anchor", text_anchor)
117
- .attr("x", xy[0])
118
- .attr("y", xy[1])
119
- ;
120
- })
121
- .text(n => n.label)
122
- ;
123
- labels.exit().remove();
124
- const domains = element
125
- .selectAll(".domain")
126
- .data(flatData.filter(n => n.colIdx === 1));
127
- domains.enter()
128
- .append("line")
129
- .classed("domain", true)
130
- .style("stroke", "#000")
131
- .style("stroke-opacity", "0.75")
132
- .style("stroke-width", "1px")
133
- .merge(domains)
134
- .attr("x1", 0)
135
- .attr("y1", 0)
136
- .attr("x2", (n, i) => domain_points[i][0])
137
- .attr("y2", (n, i) => domain_points[i][1]);
138
- domains.exit().remove();
139
- const value_guides = element
140
- .selectAll(".value_guide")
141
- .data(this.valueGuideRatios())
142
- ;
143
- value_guides.enter()
144
- .append("polygon")
145
- .classed("value_guide", true)
146
- .style("stroke", "grey")
147
- .style("stroke-opacity", "0.75")
148
- .style("stroke-width", "0.3px")
149
- .merge(value_guides)
150
- .each(function (mult, i) {
151
- const poly_points = [];
152
- domain_points.forEach((domain_point, row_idx) => {
153
- poly_points.push([
154
- domain_point[0] * mult,
155
- domain_point[1] * mult
156
- ]);
157
- });
158
- d3Select(this)
159
- .attr("points", poly_points.join(" "))
160
- .attr("stroke", "rgb(0, 0, 0)")
161
- .attr("stroke-opacity", 0.75)
162
- .attr("stroke-width", 0.3)
163
- .attr("fill-opacity", 0)
164
- ;
165
- })
166
- ;
167
- value_guides.exit().remove();
168
-
169
- const value_guide_text = element
170
- .selectAll(".value_guide_text")
171
- .data(this.valueGuideRatios())
172
- ;
173
- value_guide_text.enter()
174
- .append("text")
175
- .attr("class", "value_guide_text")
176
- .attr("text-anchor", "start")
177
- .attr("font-size", this.fontSize())
178
- .attr("font-family", this.fontFamily())
179
- .merge(value_guide_text)
180
- .attr("x", 2)
181
- .attr("y", mult => domain_points[0][1] * mult)
182
- .text((mult, i) => Math.round(mult * max_val))
183
- ;
184
- value_guides.exit().remove();
185
-
186
- // Polygon shapes ---
187
- const series_polygons = element
188
- .selectAll(".area")
189
- .data(columns.filter((n, i) => i > 0));
190
- series_polygons.enter()
191
- .append("polygon")
192
- .attr("class", "area")
193
- .style("stroke-opacity", "0.75")
194
- .style("stroke-width", "0.3px")
195
- .merge(series_polygons)
196
- .style("stroke", d => this.strokeColor([], d, 0))
197
- .style("fill", d => this.fillColor([], d, 0))
198
- .style("fill-opacity", this.fillOpacity())
199
- .attr("points", (d, col_idx) => {
200
- return domain_points.map((domain_point, row_idx) => {
201
- const val = data[row_idx][col_idx + 1];
202
- const val_mult = val === 0 ? 0 : val / max_val;
203
- return domain_point[0] * val_mult + "," + domain_point[1] * val_mult;
204
- }).join(" ");
205
- });
206
- series_polygons.exit().remove();
207
-
208
- // Points ---
209
- const point_elm = element
210
- .selectAll(".point")
211
- .data(flatData);
212
- point_elm.enter()
213
- .append("g")
214
- .attr("class", "point")
215
- .on("mouseout.tooltip", context.tooltip.hide)
216
- .on("mousemove.tooltip", context.tooltip.show)
217
- .on("click", function (d: any, _idx) {
218
- const data_row = context.data()[d.rowIdx];
219
- const row_obj = context.rowToObj(data_row);
220
- const selected = context._selection.selected(this);
221
- context.click(row_obj, context.columns()[d.colIdx], selected);
222
- })
223
- .on("dblclick", function (d: any, _idx) {
224
- context.dblclick(context.rowToObj(context.data()[d.rowIdx]), d.column, context._selection.selected(this));
225
- })
226
- .each(function (d) {
227
- const element = d3Select(this);
228
- element.append("circle")
229
- .attr("class", "pointSelection")
230
- .attr("r", context.pointSize())
231
- .call(context._selection.enter.bind(context._selection))
232
- ;
233
- element.append(context.mapShape(context.pointShape()))
234
- .attr("class", "pointShape")
235
- ;
236
- })
237
- .merge(point_elm)
238
- .each(function (d) {
239
- const element = d3Select(this);
240
- const val_mult = d.value === 0 ? 0 : d.value / max_val;
241
- const x = domain_points[d.rowIdx][0] * val_mult;
242
- const y = domain_points[d.rowIdx][1] * val_mult;
243
- element.select(".pointSelection")
244
- .attr("cx", x)
245
- .attr("cy", y)
246
- ;
247
-
248
- const pointElement = element.select(".pointShape")
249
- .style("stroke", context.strokeColor(d.row, d.column, d.value))
250
- .style("fill", context.fillColor(d.row, d.column, d.value))
251
- ;
252
- context.setPointAttributes(pointElement, x, y);
253
- })
254
- ;
255
- point_elm.exit().remove();
256
- }
257
-
258
- polar2cartesian(r, theta) {
259
- return [r * Math.cos(theta), r * Math.sin(theta)];
260
- }
261
- cartesian2polar(x, y) {
262
- return [Math.atan2(y, x), Math.sqrt(x * x + y * y)];
263
- }
264
- degrees2radians(d) {
265
- return d / 57.295779513;
266
- }
267
- radians2degrees(r) {
268
- return r * 57.295779513;
269
- }
270
- point_in_polygon(point, vs) {
271
- const x = point[0];
272
- const y = point[1];
273
- let inside = false;
274
- for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) {
275
- const xi = vs[i][0];
276
- const yi = vs[i][1];
277
- const xj = vs[j][0];
278
- const yj = vs[j][1];
279
- const intersect = ((yi > y) !== (yj > y))
280
- && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
281
- if (intersect) inside = !inside;
282
- }
283
- return inside;
284
- }
285
-
286
- // INDChart
287
- _palette;
288
- fillColor: (row, column, value) => string;
289
- strokeColor: (row, column, value) => string;
290
- textColor: (row, column, value) => string;
291
- click: (row, column, selected) => void;
292
- dblclick: (row, column, selected) => void;
293
-
294
- // ITooltip
295
- tooltip;
296
- tooltipHTML: (_) => string;
297
- tooltipFormat: (_) => string;
298
-
299
- _selection;
300
- }
301
- Radar.prototype._class += " chart_Radar";
302
- Radar.prototype.implements(INDChart.prototype);
303
- Radar.prototype.implements(ITooltip.prototype);
304
- Radar.prototype.mixin(Utility.SimpleSelectionMixin);
305
-
306
- export interface Radar {
307
- labelPaddingRatio(): number;
308
- labelPaddingRatio(_: number): this;
309
- fillOpacity(): number;
310
- fillOpacity(_: number): this;
311
- fontFamily(): string;
312
- fontFamily(_: string): this;
313
- fontSize(): number;
314
- fontSize(_: number): this;
315
- valueGuideRatios(): any;
316
- valueGuideRatios(_: any): this;
317
- valueGuideFontSize(): number;
318
- valueGuideFontSize(_: number): this;
319
- valueGuideFontFamily(): string;
320
- valueGuideFontFamily(_: string): this;
321
- paletteID(): string;
322
- paletteID(_: string): this;
323
- pointShape(): string;
324
- pointShape(_: string): this;
325
- pointSize(): number;
326
- pointSize(_: number): this;
327
- }
328
-
329
- Radar.prototype.publish("paletteID", "default", "set", "Color palette for this widget", Radar.prototype._palette.switch());
330
- Radar.prototype.publish("pointShape", "cross", "set", "pointShape", ["circle", "rectangle", "cross"]);
331
- Radar.prototype.publish("pointSize", 6, "number", "Point Size", null, { range: { min: 1, step: 1, max: 200 } });
332
- Radar.prototype.publish("valueGuideRatios", [0.2, 0.4, 0.6, 0.8, 1], "array", "Array of values between 0 and 1 that are multiplied by the widget radius to produce guide lines");
333
- Radar.prototype.publish("fillOpacity", 0.66, "number", "Opacity of the data polygon(s)");
334
- Radar.prototype.publish("fontFamily", "", "string", "fontFamily");
335
- Radar.prototype.publish("fontSize", 16, "number", "fontSize");
336
- Radar.prototype.publish("labelPaddingRatio", 0.9, "number", "labelPaddingRatio");
1
+ import { INDChart, ITooltip } from "@hpcc-js/api";
2
+ import { SVGWidget, Utility } from "@hpcc-js/common";
3
+ import { select as d3Select } from "d3-selection";
4
+
5
+ import "../src/Radar.css";
6
+ export class Radar extends SVGWidget {
7
+
8
+ constructor() {
9
+ super();
10
+ INDChart.call(this);
11
+ ITooltip.call(this);
12
+ Utility.SimpleSelectionMixin.call(this);
13
+ }
14
+
15
+ mapShape(shape) {
16
+ switch (shape) {
17
+ case "rectangle":
18
+ return "rect";
19
+ case "circle":
20
+ return "circle";
21
+ case "cross":
22
+ return "path";
23
+ default:
24
+ }
25
+ }
26
+ setPointAttributes(element, x, y) {
27
+ const shape = this.mapShape(this.pointShape());
28
+ const context = this;
29
+ switch (shape) {
30
+ case "rect":
31
+ element
32
+ .attr("width", context.pointSize())
33
+ .attr("height", context.pointSize())
34
+ .style("fill", d => this.strokeColor(d.data, d.column, d.value))
35
+ ;
36
+ break;
37
+ case "circle":
38
+ element
39
+ .attr("r", context.pointSize() / 2)
40
+ .attr("cx", x)
41
+ .attr("cy", y)
42
+ .style("fill", d => this.strokeColor(d.data, d.column, d.value))
43
+ ;
44
+ break;
45
+ case "path":
46
+ const half_size = context.pointSize() / 2;
47
+ element
48
+ .attr("d", function (d: any) {
49
+ return "M" + (x - half_size) + " " + (y - half_size) + " " +
50
+ "L" + (x + half_size) + " " + (y + half_size) + " " +
51
+ "M" + (x - half_size) + " " + (y + half_size) + " " +
52
+ "L" + (x + half_size) + " " + (y - half_size);
53
+ })
54
+ .style("stroke", d => this.strokeColor(d.data, d.column, d.value))
55
+ ;
56
+ break;
57
+ default:
58
+ }
59
+ }
60
+ enter(domNode, element) {
61
+ super.enter(domNode, element);
62
+ this._selection.widgetElement(element);
63
+
64
+ this
65
+ .tooltipHTML(d => {
66
+ return this.tooltipFormat({ label: d.label, series: d.column, value: d.value });
67
+ })
68
+ ;
69
+ }
70
+ update(domNode, element) {
71
+ super.update(domNode, element);
72
+ this._palette = this._palette.switch(this.paletteID());
73
+ const context = this;
74
+ const h = this.height();
75
+ const w = this.width();
76
+ const half_h = (h / 2);
77
+ const half_w = (w / 2);
78
+
79
+ const columns = this.columns();
80
+ const data = this.data();
81
+ const flatData = this.flattenData(columns, data).map((d: any, idx: number) => {
82
+ d.shape = this.mapShape(this.pointShape());
83
+ d.column = columns[d.colIdx];
84
+ d.row = data[idx];
85
+ return d;
86
+ });
87
+ const domain_points = [];
88
+ const arc = this.degrees2radians(360 / this.data().length);
89
+ const max_label_h = this.fontSize();
90
+ let max_label_w = 0;
91
+ flatData.filter(n => n.colIdx === 1).forEach(n => {
92
+ const isize = super.textSize(n.label, `${this.fontFamily()}`, this.fontSize());
93
+ if (max_label_w < isize.width) max_label_w = isize.width;
94
+ });
95
+ const radius = Math.min(half_h - max_label_h, half_w - max_label_w);
96
+ const labels = element
97
+ .selectAll(".label")
98
+ .data(flatData.filter(n => n.colIdx === 1))
99
+ ;
100
+ const max_val = Math.max.apply(context, flatData.map(n => n.value));
101
+ labels.enter()
102
+ .append("text")
103
+ .attr("class", "label")
104
+ .attr("text-anchor", "middle")
105
+ .merge(labels)
106
+ .attr("font-size", this.fontSize())
107
+ .attr("font-family", this.fontFamily())
108
+ .each(function (this: SVGElement, n, i) {
109
+ const xy = context.polar2cartesian(radius, (i * arc) - (Math.PI / 2));
110
+ domain_points.push(xy.map(n => n * context.labelPaddingRatio()));
111
+ let text_anchor = "middle";
112
+ const _x = Math.round(xy[0]);
113
+ text_anchor = _x > 0 ? "start" : text_anchor;
114
+ text_anchor = _x < 0 ? "end" : text_anchor;
115
+ d3Select(this)
116
+ .attr("text-anchor", text_anchor)
117
+ .attr("x", xy[0])
118
+ .attr("y", xy[1])
119
+ ;
120
+ })
121
+ .text(n => n.label)
122
+ ;
123
+ labels.exit().remove();
124
+ const domains = element
125
+ .selectAll(".domain")
126
+ .data(flatData.filter(n => n.colIdx === 1));
127
+ domains.enter()
128
+ .append("line")
129
+ .classed("domain", true)
130
+ .style("stroke", "#000")
131
+ .style("stroke-opacity", "0.75")
132
+ .style("stroke-width", "1px")
133
+ .merge(domains)
134
+ .attr("x1", 0)
135
+ .attr("y1", 0)
136
+ .attr("x2", (n, i) => domain_points[i][0])
137
+ .attr("y2", (n, i) => domain_points[i][1]);
138
+ domains.exit().remove();
139
+ const value_guides = element
140
+ .selectAll(".value_guide")
141
+ .data(this.valueGuideRatios())
142
+ ;
143
+ value_guides.enter()
144
+ .append("polygon")
145
+ .classed("value_guide", true)
146
+ .style("stroke", "grey")
147
+ .style("stroke-opacity", "0.75")
148
+ .style("stroke-width", "0.3px")
149
+ .merge(value_guides)
150
+ .each(function (mult, i) {
151
+ const poly_points = [];
152
+ domain_points.forEach((domain_point, row_idx) => {
153
+ poly_points.push([
154
+ domain_point[0] * mult,
155
+ domain_point[1] * mult
156
+ ]);
157
+ });
158
+ d3Select(this)
159
+ .attr("points", poly_points.join(" "))
160
+ .attr("stroke", "rgb(0, 0, 0)")
161
+ .attr("stroke-opacity", 0.75)
162
+ .attr("stroke-width", 0.3)
163
+ .attr("fill-opacity", 0)
164
+ ;
165
+ })
166
+ ;
167
+ value_guides.exit().remove();
168
+
169
+ const value_guide_text = element
170
+ .selectAll(".value_guide_text")
171
+ .data(this.valueGuideRatios())
172
+ ;
173
+ value_guide_text.enter()
174
+ .append("text")
175
+ .attr("class", "value_guide_text")
176
+ .attr("text-anchor", "start")
177
+ .attr("font-size", this.fontSize())
178
+ .attr("font-family", this.fontFamily())
179
+ .merge(value_guide_text)
180
+ .attr("x", 2)
181
+ .attr("y", mult => domain_points[0][1] * mult)
182
+ .text((mult, i) => Math.round(mult * max_val))
183
+ ;
184
+ value_guides.exit().remove();
185
+
186
+ // Polygon shapes ---
187
+ const series_polygons = element
188
+ .selectAll(".area")
189
+ .data(columns.filter((n, i) => i > 0));
190
+ series_polygons.enter()
191
+ .append("polygon")
192
+ .attr("class", "area")
193
+ .style("stroke-opacity", "0.75")
194
+ .style("stroke-width", "0.3px")
195
+ .merge(series_polygons)
196
+ .style("stroke", d => this.strokeColor([], d, 0))
197
+ .style("fill", d => this.fillColor([], d, 0))
198
+ .style("fill-opacity", this.fillOpacity())
199
+ .attr("points", (d, col_idx) => {
200
+ return domain_points.map((domain_point, row_idx) => {
201
+ const val = data[row_idx][col_idx + 1];
202
+ const val_mult = val === 0 ? 0 : val / max_val;
203
+ return domain_point[0] * val_mult + "," + domain_point[1] * val_mult;
204
+ }).join(" ");
205
+ });
206
+ series_polygons.exit().remove();
207
+
208
+ // Points ---
209
+ const point_elm = element
210
+ .selectAll(".point")
211
+ .data(flatData);
212
+ point_elm.enter()
213
+ .append("g")
214
+ .attr("class", "point")
215
+ .on("mouseout.tooltip", context.tooltip.hide)
216
+ .on("mousemove.tooltip", context.tooltip.show)
217
+ .on("click", function (d: any, _idx) {
218
+ const data_row = context.data()[d.rowIdx];
219
+ const row_obj = context.rowToObj(data_row);
220
+ const selected = context._selection.selected(this);
221
+ context.click(row_obj, context.columns()[d.colIdx], selected);
222
+ })
223
+ .on("dblclick", function (d: any, _idx) {
224
+ context.dblclick(context.rowToObj(context.data()[d.rowIdx]), d.column, context._selection.selected(this));
225
+ })
226
+ .each(function (d) {
227
+ const element = d3Select(this);
228
+ element.append("circle")
229
+ .attr("class", "pointSelection")
230
+ .attr("r", context.pointSize())
231
+ .call(context._selection.enter.bind(context._selection))
232
+ ;
233
+ element.append(context.mapShape(context.pointShape()))
234
+ .attr("class", "pointShape")
235
+ ;
236
+ })
237
+ .merge(point_elm)
238
+ .each(function (d) {
239
+ const element = d3Select(this);
240
+ const val_mult = d.value === 0 ? 0 : d.value / max_val;
241
+ const x = domain_points[d.rowIdx][0] * val_mult;
242
+ const y = domain_points[d.rowIdx][1] * val_mult;
243
+ element.select(".pointSelection")
244
+ .attr("cx", x)
245
+ .attr("cy", y)
246
+ ;
247
+
248
+ const pointElement = element.select(".pointShape")
249
+ .style("stroke", context.strokeColor(d.row, d.column, d.value))
250
+ .style("fill", context.fillColor(d.row, d.column, d.value))
251
+ ;
252
+ context.setPointAttributes(pointElement, x, y);
253
+ })
254
+ ;
255
+ point_elm.exit().remove();
256
+ }
257
+
258
+ polar2cartesian(r, theta) {
259
+ return [r * Math.cos(theta), r * Math.sin(theta)];
260
+ }
261
+ cartesian2polar(x, y) {
262
+ return [Math.atan2(y, x), Math.sqrt(x * x + y * y)];
263
+ }
264
+ degrees2radians(d) {
265
+ return d / 57.295779513;
266
+ }
267
+ radians2degrees(r) {
268
+ return r * 57.295779513;
269
+ }
270
+ point_in_polygon(point, vs) {
271
+ const x = point[0];
272
+ const y = point[1];
273
+ let inside = false;
274
+ for (let i = 0, j = vs.length - 1; i < vs.length; j = i++) {
275
+ const xi = vs[i][0];
276
+ const yi = vs[i][1];
277
+ const xj = vs[j][0];
278
+ const yj = vs[j][1];
279
+ const intersect = ((yi > y) !== (yj > y))
280
+ && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
281
+ if (intersect) inside = !inside;
282
+ }
283
+ return inside;
284
+ }
285
+
286
+ // INDChart
287
+ _palette;
288
+ fillColor: (row, column, value) => string;
289
+ strokeColor: (row, column, value) => string;
290
+ textColor: (row, column, value) => string;
291
+ click: (row, column, selected) => void;
292
+ dblclick: (row, column, selected) => void;
293
+
294
+ // ITooltip
295
+ tooltip;
296
+ tooltipHTML: (_) => string;
297
+ tooltipFormat: (_) => string;
298
+
299
+ _selection;
300
+ }
301
+ Radar.prototype._class += " chart_Radar";
302
+ Radar.prototype.implements(INDChart.prototype);
303
+ Radar.prototype.implements(ITooltip.prototype);
304
+ Radar.prototype.mixin(Utility.SimpleSelectionMixin);
305
+
306
+ export interface Radar {
307
+ labelPaddingRatio(): number;
308
+ labelPaddingRatio(_: number): this;
309
+ fillOpacity(): number;
310
+ fillOpacity(_: number): this;
311
+ fontFamily(): string;
312
+ fontFamily(_: string): this;
313
+ fontSize(): number;
314
+ fontSize(_: number): this;
315
+ valueGuideRatios(): any;
316
+ valueGuideRatios(_: any): this;
317
+ valueGuideFontSize(): number;
318
+ valueGuideFontSize(_: number): this;
319
+ valueGuideFontFamily(): string;
320
+ valueGuideFontFamily(_: string): this;
321
+ paletteID(): string;
322
+ paletteID(_: string): this;
323
+ pointShape(): string;
324
+ pointShape(_: string): this;
325
+ pointSize(): number;
326
+ pointSize(_: number): this;
327
+ }
328
+
329
+ Radar.prototype.publish("paletteID", "default", "set", "Color palette for this widget", Radar.prototype._palette.switch());
330
+ Radar.prototype.publish("pointShape", "cross", "set", "pointShape", ["circle", "rectangle", "cross"]);
331
+ Radar.prototype.publish("pointSize", 6, "number", "Point Size", null, { range: { min: 1, step: 1, max: 200 } });
332
+ Radar.prototype.publish("valueGuideRatios", [0.2, 0.4, 0.6, 0.8, 1], "array", "Array of values between 0 and 1 that are multiplied by the widget radius to produce guide lines");
333
+ Radar.prototype.publish("fillOpacity", 0.66, "number", "Opacity of the data polygon(s)");
334
+ Radar.prototype.publish("fontFamily", "", "string", "fontFamily");
335
+ Radar.prototype.publish("fontSize", 16, "number", "fontSize");
336
+ Radar.prototype.publish("labelPaddingRatio", 0.9, "number", "labelPaddingRatio");