cx 24.3.11 → 24.4.0
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/charts.css +6 -0
- package/dist/charts.js +307 -62
- package/dist/manifest.js +765 -764
- package/dist/ui.js +2 -75
- package/package.json +1 -1
- package/src/charts/BarGraph.d.ts +7 -9
- package/src/charts/ColumnGraph.d.ts +10 -12
- package/src/charts/LineGraph.d.ts +1 -1
- package/src/charts/PieChart.d.ts +6 -0
- package/src/charts/PieChart.js +162 -82
- package/src/charts/RangeMarker.d.ts +35 -0
- package/src/charts/RangeMarker.js +155 -0
- package/src/charts/RangeMarker.scss +15 -0
- package/src/charts/ScatterGraph.d.ts +30 -32
- package/src/charts/index.d.ts +1 -0
- package/src/charts/index.js +1 -0
- package/src/charts/index.scss +1 -0
- package/src/charts/variables.scss +21 -20
- package/src/data/Expression.d.ts +17 -17
- package/src/data/Expression.js +220 -220
- package/src/data/StringTemplate.d.ts +15 -15
- package/src/data/StringTemplate.js +92 -92
- package/src/ui/Culture.d.ts +51 -51
- package/src/ui/Culture.js +129 -139
- package/src/ui/Cx.js +313 -313
- package/src/ui/Format.js +107 -107
- package/src/ui/Restate.d.ts +21 -21
- package/src/ui/Restate.js +163 -163
- package/src/ui/index.d.ts +0 -1
- package/src/ui/index.js +44 -45
- package/src/util/Console.d.ts +2 -7
- package/src/util/Format.d.ts +18 -18
- package/src/util/Format.js +234 -234
- package/src/widgets/drag-drop/DropZone.d.ts +9 -9
- package/src/widgets/grid/Grid.d.ts +12 -12
- package/src/ui/CultureScope.d.ts +0 -10
- package/src/ui/CultureScope.js +0 -53
package/dist/ui.js
CHANGED
|
@@ -814,13 +814,6 @@ var Localization = /*#__PURE__*/ (function () {
|
|
|
814
814
|
return Localization;
|
|
815
815
|
})();
|
|
816
816
|
|
|
817
|
-
// let culture = "en";
|
|
818
|
-
// let numberCulture = null;
|
|
819
|
-
// let dateTimeCulture = null;
|
|
820
|
-
// let cache = {};
|
|
821
|
-
// let defaultCurrency = "USD";
|
|
822
|
-
// let dateEncoding = (date) => date.toISOString();
|
|
823
|
-
|
|
824
817
|
var stack = [
|
|
825
818
|
{
|
|
826
819
|
culture: "en",
|
|
@@ -862,13 +855,9 @@ function createCulture(cultureSpecs) {
|
|
|
862
855
|
function popCulture(cultureSpecs) {
|
|
863
856
|
if (stack.length == 1) throw new Error("Cannot pop the last culture object.");
|
|
864
857
|
if (cultureSpecs && stack[stack.length - 1] !== cultureSpecs) {
|
|
865
|
-
|
|
866
|
-
}
|
|
867
|
-
try {
|
|
868
|
-
return stack.pop();
|
|
869
|
-
} finally {
|
|
870
|
-
console.log(stack);
|
|
858
|
+
Console.warn("Popped culture object does not match the current one.");
|
|
871
859
|
}
|
|
860
|
+
return stack.pop();
|
|
872
861
|
}
|
|
873
862
|
var Culture = /*#__PURE__*/ (function () {
|
|
874
863
|
function Culture() {}
|
|
@@ -3173,67 +3162,6 @@ HoverSyncElement.prototype.baseClass = "hoversyncelement";
|
|
|
3173
3162
|
HoverSyncElement.prototype.styled = true;
|
|
3174
3163
|
HoverSyncElement.prototype.hoverChannel = "default";
|
|
3175
3164
|
|
|
3176
|
-
var CultureScope = /*#__PURE__*/ (function (_PureContainer) {
|
|
3177
|
-
function CultureScope() {
|
|
3178
|
-
return _PureContainer.apply(this, arguments) || this;
|
|
3179
|
-
}
|
|
3180
|
-
_inheritsLoose(CultureScope, _PureContainer);
|
|
3181
|
-
var _proto = CultureScope.prototype;
|
|
3182
|
-
_proto.init = function init() {
|
|
3183
|
-
var _this$items;
|
|
3184
|
-
this.initialItems = (_this$items = this.items) != null ? _this$items : this.children;
|
|
3185
|
-
delete this.items;
|
|
3186
|
-
delete this.children;
|
|
3187
|
-
_PureContainer.prototype.init.call(this);
|
|
3188
|
-
};
|
|
3189
|
-
_proto.declareData = function declareData() {
|
|
3190
|
-
var _PureContainer$protot;
|
|
3191
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
3192
|
-
args[_key] = arguments[_key];
|
|
3193
|
-
}
|
|
3194
|
-
(_PureContainer$protot = _PureContainer.prototype.declareData).call.apply(
|
|
3195
|
-
_PureContainer$protot,
|
|
3196
|
-
[this].concat(args, [
|
|
3197
|
-
{
|
|
3198
|
-
culture: undefined,
|
|
3199
|
-
numberCulture: undefined,
|
|
3200
|
-
dateTimeCulture: undefined,
|
|
3201
|
-
defaultCurrency: undefined,
|
|
3202
|
-
},
|
|
3203
|
-
]),
|
|
3204
|
-
);
|
|
3205
|
-
};
|
|
3206
|
-
_proto.prepareData = function prepareData(context, instance) {
|
|
3207
|
-
_PureContainer.prototype.prepareData.call(this, context, instance);
|
|
3208
|
-
this.clear();
|
|
3209
|
-
var data = instance.data;
|
|
3210
|
-
if (this.onCreateCulture) instance.culture = instance.invoke("onCreateCulture", data, instance);
|
|
3211
|
-
else
|
|
3212
|
-
instance.culture = createCulture({
|
|
3213
|
-
culture: data.culture,
|
|
3214
|
-
numberCulture: data.numberCulture,
|
|
3215
|
-
dateTimeCulture: data.dateTimeCulture,
|
|
3216
|
-
defaultCurrency: data.defaultCurrency,
|
|
3217
|
-
dateEncoding: this.dateEncoding,
|
|
3218
|
-
});
|
|
3219
|
-
};
|
|
3220
|
-
_proto.explore = function explore(context, instance) {
|
|
3221
|
-
var culture = instance.culture;
|
|
3222
|
-
pushCulture(culture);
|
|
3223
|
-
if (this.items.length == 0 && this.initialItems) this.add(this.initialItems);
|
|
3224
|
-
_PureContainer.prototype.explore.call(this, context, instance);
|
|
3225
|
-
};
|
|
3226
|
-
_proto.exploreCleanup = function exploreCleanup(context, instance) {
|
|
3227
|
-
popCulture(instance.culture);
|
|
3228
|
-
};
|
|
3229
|
-
return CultureScope;
|
|
3230
|
-
})(PureContainer);
|
|
3231
|
-
CultureScope.prototype.culture = null;
|
|
3232
|
-
CultureScope.prototype.numberCulture = null;
|
|
3233
|
-
CultureScope.prototype.dateTimeCulture = null;
|
|
3234
|
-
CultureScope.prototype.defaultCurrency = null;
|
|
3235
|
-
CultureScope.prototype.dateEncoding = null;
|
|
3236
|
-
|
|
3237
3165
|
var flattenProps = function flattenProps(props) {
|
|
3238
3166
|
if (!props) return {};
|
|
3239
3167
|
if (props.jsxSpread) {
|
|
@@ -4534,7 +4462,6 @@ export {
|
|
|
4534
4462
|
ContentResolver,
|
|
4535
4463
|
Controller,
|
|
4536
4464
|
Culture,
|
|
4537
|
-
CultureScope,
|
|
4538
4465
|
Cx,
|
|
4539
4466
|
DataAdapter,
|
|
4540
4467
|
DataProxy,
|
package/package.json
CHANGED
package/src/charts/BarGraph.d.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
import * as Cx from
|
|
2
|
-
import { ColumnBarGraphBaseProps } from
|
|
1
|
+
import * as Cx from "../core";
|
|
2
|
+
import { ColumnBarGraphBaseProps } from "./ColumnBarGraphBase";
|
|
3
3
|
|
|
4
4
|
interface BarGraphProps extends ColumnBarGraphBaseProps {
|
|
5
|
-
|
|
6
5
|
/** Base CSS class to be applied to the element. Defaults to `bargraph`. */
|
|
7
|
-
baseClass?: string
|
|
6
|
+
baseClass?: string;
|
|
8
7
|
|
|
9
|
-
/**
|
|
10
|
-
* Name of the property which holds the base value.
|
|
8
|
+
/**
|
|
9
|
+
* Name of the property which holds the base value.
|
|
11
10
|
* Default value is `false`, which means x0 value is not read from the data array.
|
|
12
11
|
*/
|
|
13
|
-
x0Field?: string
|
|
14
|
-
|
|
12
|
+
x0Field?: string | false;
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
export class BarGraph extends Cx.Widget<BarGraphProps> {}
|
|
15
|
+
export class BarGraph extends Cx.Widget<BarGraphProps> {}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import * as Cx from
|
|
2
|
-
import { ColumnBarGraphBaseProps } from
|
|
1
|
+
import * as Cx from "../core";
|
|
2
|
+
import { ColumnBarGraphBaseProps } from "./ColumnBarGraphBase";
|
|
3
3
|
|
|
4
4
|
interface ColumnGraphProps extends ColumnBarGraphBaseProps {
|
|
5
|
-
|
|
6
5
|
/** Base CSS class to be applied to the element. Defaults to `columngraph`. */
|
|
7
|
-
baseClass?: string
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Name of the property which holds the base value.
|
|
11
|
-
* Default value is `false`, which means y0 value is not read from the data array.
|
|
6
|
+
baseClass?: string;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Name of the property which holds the base value.
|
|
10
|
+
* Default value is `false`, which means y0 value is not read from the data array.
|
|
12
11
|
*/
|
|
13
|
-
y0Field?: string
|
|
12
|
+
y0Field?: string | false;
|
|
14
13
|
|
|
15
14
|
/** Column base value. Default value is `0`. */
|
|
16
|
-
y0?: Cx.NumberProp
|
|
17
|
-
|
|
15
|
+
y0?: Cx.NumberProp;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
export class ColumnGraph extends Cx.Widget<ColumnGraphProps> {}
|
|
18
|
+
export class ColumnGraph extends Cx.Widget<ColumnGraphProps> {}
|
|
@@ -77,7 +77,7 @@ interface LineGraphProps extends Cx.WidgetProps {
|
|
|
77
77
|
baseClass?: string;
|
|
78
78
|
|
|
79
79
|
/** Name of the property which holds the y0 value. Default value is `false`, which means y0 value is not read from the data array. */
|
|
80
|
-
y0Field?: string;
|
|
80
|
+
y0Field?: string | false;
|
|
81
81
|
|
|
82
82
|
/** Name of the legend to be used. Default is `legend`. */
|
|
83
83
|
legend?: string;
|
package/src/charts/PieChart.d.ts
CHANGED
|
@@ -11,6 +11,9 @@ interface PieChartProps extends BoundedObjectProps {
|
|
|
11
11
|
|
|
12
12
|
/** When set to `true`, stacks are rendered in clock wise direction. */
|
|
13
13
|
clockwise?: Cx.BooleanProp;
|
|
14
|
+
|
|
15
|
+
/** Gap between slices in pixels. Default is `0` which means there is no gap. */
|
|
16
|
+
gap?: Cx.NumberProp;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
export class PieChart extends Cx.Widget<PieChartProps> {}
|
|
@@ -78,6 +81,9 @@ interface PieSliceProps extends Cx.StyledContainerProps {
|
|
|
78
81
|
|
|
79
82
|
/** Border radius of the slice. Default is 0. */
|
|
80
83
|
borderRadius?: Cx.NumberProp;
|
|
84
|
+
|
|
85
|
+
/** Border radius of the slice. Default is 0. */
|
|
86
|
+
br?: Cx.NumberProp;
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
export class PieSlice extends Cx.Widget<PieSliceProps> {}
|
package/src/charts/PieChart.js
CHANGED
|
@@ -12,15 +12,16 @@ export class PieChart extends BoundedObject {
|
|
|
12
12
|
declareData() {
|
|
13
13
|
super.declareData(...arguments, {
|
|
14
14
|
angle: undefined,
|
|
15
|
-
startAngle:
|
|
15
|
+
startAngle: undefined,
|
|
16
16
|
clockwise: undefined,
|
|
17
|
+
gap: undefined,
|
|
17
18
|
});
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
explore(context, instance) {
|
|
21
22
|
if (!instance.pie) instance.pie = new PieCalculator();
|
|
22
|
-
|
|
23
|
-
instance.pie.reset(data.angle, data.startAngle, data.clockwise);
|
|
23
|
+
let { data } = instance;
|
|
24
|
+
instance.pie.reset(data.angle, data.startAngle, data.clockwise, data.gap);
|
|
24
25
|
|
|
25
26
|
context.push("pie", instance.pie);
|
|
26
27
|
super.explore(context, instance);
|
|
@@ -32,7 +33,7 @@ export class PieChart extends BoundedObject {
|
|
|
32
33
|
|
|
33
34
|
prepare(context, instance) {
|
|
34
35
|
this.prepareBounds(context, instance);
|
|
35
|
-
|
|
36
|
+
let { data, pie } = instance;
|
|
36
37
|
pie.measure(data.bounds);
|
|
37
38
|
let hash = pie.hash();
|
|
38
39
|
instance.cache("hash", hash);
|
|
@@ -45,17 +46,24 @@ export class PieChart extends BoundedObject {
|
|
|
45
46
|
PieChart.prototype.anchors = "0 1 1 0";
|
|
46
47
|
|
|
47
48
|
class PieCalculator {
|
|
48
|
-
reset(angle, startAngle, clockwise) {
|
|
49
|
+
reset(angle, startAngle, clockwise, gap) {
|
|
50
|
+
if (angle == 360) angle = 359.99; // really hacky way to draw full circles
|
|
49
51
|
this.angleTotal = (angle / 180) * Math.PI;
|
|
50
52
|
this.startAngle = (startAngle / 180) * Math.PI;
|
|
51
53
|
this.clockwise = clockwise;
|
|
54
|
+
this.gap = gap;
|
|
52
55
|
this.stacks = {};
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
acknowledge(stack, value) {
|
|
56
|
-
|
|
57
|
-
if (!s) s = this.stacks[stack] = { total: 0 };
|
|
58
|
-
if (value > 0)
|
|
58
|
+
acknowledge(stack, value, r, r0, percentageRadius) {
|
|
59
|
+
let s = this.stacks[stack];
|
|
60
|
+
if (!s) s = this.stacks[stack] = { total: 0, r0s: this.gap > 0 ? [] : null, r0ps: this.gap > 0 ? [] : null };
|
|
61
|
+
if (value > 0) {
|
|
62
|
+
s.total += value;
|
|
63
|
+
if (this.gap > 0 && r0 > 0)
|
|
64
|
+
if (percentageRadius) s.r0ps.push(r0);
|
|
65
|
+
else s.r0s.push(r0);
|
|
66
|
+
}
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
hash() {
|
|
@@ -69,32 +77,63 @@ class PieCalculator {
|
|
|
69
77
|
cx: this.cx,
|
|
70
78
|
cy: this.cy,
|
|
71
79
|
R: this.R,
|
|
80
|
+
gap: this.gap,
|
|
72
81
|
};
|
|
73
82
|
}
|
|
74
83
|
|
|
75
84
|
measure(rect) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
stack
|
|
85
|
+
this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
|
|
86
|
+
for (let s in this.stacks) {
|
|
87
|
+
let stack = this.stacks[s];
|
|
88
|
+
let gapAngleTotal = 0;
|
|
89
|
+
stack.gap = this.gap;
|
|
90
|
+
if (this.gap > 0) {
|
|
91
|
+
// gap cannot be larger of two times the smallest r0
|
|
92
|
+
for (let index = 0; index < stack.r0s.length; index++)
|
|
93
|
+
if (2 * stack.r0s[index] < stack.gap) stack.gap = 2 * stack.r0s[index];
|
|
94
|
+
for (let index = 0; index < stack.r0ps.length; index++) {
|
|
95
|
+
let r0 = (stack.r0ps[index] * this.R) / 100;
|
|
96
|
+
if (2 * r0 < stack.gap) stack.gap = 2 * r0;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
while (stack.gap > 0) {
|
|
100
|
+
for (let index = 0; index < stack.r0s.length; index++)
|
|
101
|
+
gapAngleTotal += Math.asin(stack.gap / stack.r0s[index] / 2);
|
|
102
|
+
|
|
103
|
+
for (let index = 0; index < stack.r0ps.length; index++)
|
|
104
|
+
gapAngleTotal += Math.asin(stack.gap / ((stack.r0ps[index] * this.R) / 100) / 2);
|
|
105
|
+
|
|
106
|
+
if (gapAngleTotal < 0.25 * this.angleTotal) break;
|
|
107
|
+
stack.gap = stack.gap * 0.9;
|
|
108
|
+
gapAngleTotal = 0;
|
|
109
|
+
}
|
|
110
|
+
if (gapAngleTotal == 0) stack.gap = 0;
|
|
111
|
+
stack.angleFactor = stack.total > 0 ? (this.angleTotal - gapAngleTotal) / stack.total : 0;
|
|
79
112
|
stack.lastAngle = this.startAngle;
|
|
80
113
|
}
|
|
81
114
|
this.cx = (rect.l + rect.r) / 2;
|
|
82
115
|
this.cy = (rect.t + rect.b) / 2;
|
|
83
|
-
this.R = Math.max(0, Math.min(rect.width(), rect.height())) / 2;
|
|
84
116
|
}
|
|
85
117
|
|
|
86
|
-
map(stack, value) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
118
|
+
map(stack, value, r, r0, percentageRadius) {
|
|
119
|
+
if (percentageRadius) {
|
|
120
|
+
r = (r * this.R) / 100;
|
|
121
|
+
r0 = (r0 * this.R) / 100;
|
|
122
|
+
}
|
|
123
|
+
let s = this.stacks[stack];
|
|
124
|
+
let angle = value * s.angleFactor;
|
|
125
|
+
let startAngle = s.lastAngle;
|
|
126
|
+
let clockFactor = this.clockwise ? -1 : 1;
|
|
127
|
+
let gapAngle = r0 > 0 && s.gap > 0 ? Math.asin(s.gap / r0 / 2) : 0;
|
|
128
|
+
s.lastAngle += clockFactor * (angle + gapAngle);
|
|
129
|
+
let endAngle = startAngle + clockFactor * angle + gapAngle;
|
|
93
130
|
|
|
94
131
|
return {
|
|
95
132
|
startAngle,
|
|
96
|
-
endAngle:
|
|
97
|
-
|
|
133
|
+
endAngle: startAngle + clockFactor * angle + gapAngle,
|
|
134
|
+
angle,
|
|
135
|
+
midAngle: (startAngle + endAngle) / 2,
|
|
136
|
+
gap: s.gap,
|
|
98
137
|
cx: this.cx,
|
|
99
138
|
cy: this.cy,
|
|
100
139
|
R: this.R,
|
|
@@ -102,106 +141,139 @@ class PieCalculator {
|
|
|
102
141
|
}
|
|
103
142
|
}
|
|
104
143
|
|
|
105
|
-
function createSvgArc(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
144
|
+
function createSvgArc(cx, cy, r0 = 0, r, startAngle, endAngle, br = 0, gap = 0) {
|
|
145
|
+
let gap2 = gap / 2;
|
|
146
|
+
|
|
147
|
+
if (startAngle > endAngle) {
|
|
148
|
+
let s = startAngle;
|
|
149
|
+
startAngle = endAngle;
|
|
150
|
+
endAngle = s;
|
|
110
151
|
}
|
|
111
152
|
|
|
112
153
|
let path = [];
|
|
113
154
|
// limit br size based on r and r0
|
|
114
155
|
if (br > (r - r0) / 2) br = (r - r0) / 2;
|
|
115
156
|
|
|
116
|
-
let largeArc = endAngleRadian - startAngleRadian > Math.PI ? 1 : 0;
|
|
117
|
-
|
|
118
157
|
if (br > 0) {
|
|
119
158
|
if (r0 > 0) {
|
|
120
159
|
let innerBr = br;
|
|
121
|
-
let innerSmallArcAngle = Math.asin(br / (r0 + br));
|
|
122
|
-
|
|
123
|
-
|
|
160
|
+
let innerSmallArcAngle = Math.asin((br + gap2) / (r0 + br));
|
|
161
|
+
|
|
162
|
+
// adjust br according to the available area
|
|
163
|
+
if (innerSmallArcAngle > (endAngle - startAngle) / 2) {
|
|
164
|
+
innerSmallArcAngle = (endAngle - startAngle) / 2;
|
|
124
165
|
let sin = Math.sin(innerSmallArcAngle);
|
|
125
|
-
|
|
126
|
-
innerBr = (r0 * sin) / (1 - sin);
|
|
166
|
+
innerBr = (r0 * sin - gap2) / (1 - sin);
|
|
127
167
|
}
|
|
128
|
-
let innerHip = Math.cos(innerSmallArcAngle) * (r0 + innerBr);
|
|
129
168
|
|
|
130
|
-
let
|
|
131
|
-
|
|
169
|
+
let innerHipDiagonal = (r0 + innerBr) * Math.cos(innerSmallArcAngle);
|
|
170
|
+
|
|
171
|
+
let innerSmallArc1XFrom = cx + Math.cos(endAngle) * innerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
|
|
172
|
+
let innerSmallArc1YFrom = cy - Math.sin(endAngle) * innerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
|
|
132
173
|
|
|
133
174
|
// move from the first small inner arc
|
|
134
175
|
path.push(move(innerSmallArc1XFrom, innerSmallArc1YFrom));
|
|
135
176
|
|
|
136
|
-
let innerSmallArc1XTo =
|
|
137
|
-
let innerSmallArc1YTo =
|
|
177
|
+
let innerSmallArc1XTo = cx + Math.cos(endAngle - innerSmallArcAngle) * r0;
|
|
178
|
+
let innerSmallArc1YTo = cy - Math.sin(endAngle - innerSmallArcAngle) * r0;
|
|
138
179
|
|
|
139
180
|
// add first small inner arc
|
|
140
181
|
path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc1XTo, innerSmallArc1YTo));
|
|
141
182
|
|
|
142
|
-
|
|
143
|
-
let innerArcYTo = y - Math.sin(startAngleRadian + innerSmallArcAngle) * r0;
|
|
183
|
+
// SECOND ARC
|
|
144
184
|
|
|
185
|
+
let innerArcXTo = cx + Math.cos(startAngle + innerSmallArcAngle) * r0;
|
|
186
|
+
let innerArcYTo = cy - Math.sin(startAngle + innerSmallArcAngle) * r0;
|
|
145
187
|
// add large inner arc
|
|
146
|
-
path.push(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
188
|
+
path.push(
|
|
189
|
+
arc(
|
|
190
|
+
r0,
|
|
191
|
+
r0,
|
|
192
|
+
0,
|
|
193
|
+
largeArcFlag(endAngle - innerSmallArcAngle - startAngle - innerSmallArcAngle),
|
|
194
|
+
1,
|
|
195
|
+
innerArcXTo,
|
|
196
|
+
innerArcYTo,
|
|
197
|
+
),
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
let innerSmallArc2XTo =
|
|
201
|
+
cx + Math.cos(startAngle) * innerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
|
|
202
|
+
let innerSmallArc2YTo =
|
|
203
|
+
cy - Math.sin(startAngle) * innerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
|
|
150
204
|
// add second small inner arc
|
|
151
205
|
path.push(arc(innerBr, innerBr, 0, 0, 0, innerSmallArc2XTo, innerSmallArc2YTo));
|
|
152
206
|
} else {
|
|
153
|
-
path.push(move(
|
|
207
|
+
path.push(move(cx, cy));
|
|
154
208
|
}
|
|
155
209
|
|
|
156
210
|
let outerBr = br;
|
|
157
|
-
let outerSmallArcAngle = Math.asin(br / (r - br));
|
|
158
|
-
|
|
159
|
-
|
|
211
|
+
let outerSmallArcAngle = Math.asin((br + gap2) / (r - br));
|
|
212
|
+
|
|
213
|
+
// tweak br according to the available area
|
|
214
|
+
if (outerSmallArcAngle > (endAngle - startAngle) / 2) {
|
|
215
|
+
outerSmallArcAngle = (endAngle - startAngle) / 2;
|
|
160
216
|
let sin = Math.sin(outerSmallArcAngle);
|
|
161
|
-
|
|
162
|
-
outerBr = (r * sin) / (1 + sin);
|
|
217
|
+
outerBr = (r * sin - gap2) / (1 + sin);
|
|
163
218
|
}
|
|
164
|
-
let outerHip = Math.cos(outerSmallArcAngle) * (r - outerBr);
|
|
165
219
|
|
|
166
|
-
let
|
|
167
|
-
let outerSmallArc1YFrom = y - Math.sin(startAngleRadian) * outerHip;
|
|
220
|
+
let outerHipDiagonal = Math.cos(outerSmallArcAngle) * (r - outerBr);
|
|
168
221
|
|
|
169
|
-
let
|
|
170
|
-
|
|
222
|
+
let outerSmallArc1XFrom =
|
|
223
|
+
cx + Math.cos(startAngle) * outerHipDiagonal + Math.cos(startAngle + Math.PI / 2) * gap2;
|
|
224
|
+
let outerSmallArc1YFrom =
|
|
225
|
+
cy - Math.sin(startAngle) * outerHipDiagonal - Math.sin(startAngle + Math.PI / 2) * gap2;
|
|
171
226
|
|
|
172
|
-
let
|
|
173
|
-
let
|
|
227
|
+
let outerSmallArc1XTo = cx + Math.cos(startAngle + outerSmallArcAngle) * r;
|
|
228
|
+
let outerSmallArc1YTo = cy - Math.sin(startAngle + outerSmallArcAngle) * r;
|
|
174
229
|
|
|
175
|
-
let
|
|
176
|
-
let
|
|
230
|
+
let outerLargeArcXTo = cx + Math.cos(endAngle - outerSmallArcAngle) * r;
|
|
231
|
+
let outerLargeArcYTo = cy - Math.sin(endAngle - outerSmallArcAngle) * r;
|
|
232
|
+
|
|
233
|
+
let outerSmallArc2XTo = cx + Math.cos(endAngle) * outerHipDiagonal + Math.cos(endAngle - Math.PI / 2) * gap2;
|
|
234
|
+
let outerSmallArc2YTo = cy - Math.sin(endAngle) * outerHipDiagonal - Math.sin(endAngle - Math.PI / 2) * gap2;
|
|
177
235
|
|
|
178
236
|
path.push(
|
|
179
237
|
line(outerSmallArc1XFrom, outerSmallArc1YFrom),
|
|
180
238
|
arc(outerBr, outerBr, 0, 0, 0, outerSmallArc1XTo, outerSmallArc1YTo),
|
|
181
|
-
arc(
|
|
182
|
-
|
|
239
|
+
arc(
|
|
240
|
+
r,
|
|
241
|
+
r,
|
|
242
|
+
0,
|
|
243
|
+
largeArcFlag(endAngle - outerSmallArcAngle - startAngle - outerSmallArcAngle),
|
|
244
|
+
0,
|
|
245
|
+
outerLargeArcXTo,
|
|
246
|
+
outerLargeArcYTo,
|
|
247
|
+
),
|
|
248
|
+
arc(outerBr, outerBr, 0, 0, 0, outerSmallArc2XTo, outerSmallArc2YTo),
|
|
183
249
|
);
|
|
184
250
|
} else {
|
|
185
251
|
if (r0 > 0) {
|
|
186
|
-
let
|
|
187
|
-
let
|
|
252
|
+
let innerGapAngle = r0 > 0 && gap2 > 0 ? Math.asin(gap2 / r0) : 0;
|
|
253
|
+
let innerStartAngle = startAngle + innerGapAngle;
|
|
254
|
+
let innerEndAngle = endAngle - innerGapAngle;
|
|
255
|
+
let startX = cx + Math.cos(innerEndAngle) * r0;
|
|
256
|
+
let startY = cy - Math.sin(innerEndAngle) * r0;
|
|
188
257
|
path.push(move(startX, startY));
|
|
189
258
|
|
|
190
|
-
let innerArcToX =
|
|
191
|
-
let innerArcToY =
|
|
259
|
+
let innerArcToX = cx + Math.cos(innerStartAngle) * r0;
|
|
260
|
+
let innerArcToY = cy - Math.sin(innerStartAngle) * r0;
|
|
192
261
|
|
|
193
|
-
path.push(arc(r0, r0, 0,
|
|
262
|
+
path.push(arc(r0, r0, 0, largeArcFlag(innerStartAngle - innerEndAngle), 1, innerArcToX, innerArcToY));
|
|
194
263
|
} else {
|
|
195
|
-
path.push(move(
|
|
264
|
+
path.push(move(cx, cy));
|
|
196
265
|
}
|
|
197
266
|
|
|
198
|
-
let
|
|
199
|
-
let
|
|
267
|
+
let outerGapAngle = r > 0 && gap2 > 0 ? Math.asin(gap2 / r) : 0;
|
|
268
|
+
let outerStartAngle = startAngle + outerGapAngle;
|
|
269
|
+
let outerEndAngle = endAngle - outerGapAngle;
|
|
270
|
+
let lineToX = cx + Math.cos(outerStartAngle) * r;
|
|
271
|
+
let lineToY = cy - Math.sin(outerStartAngle) * r;
|
|
200
272
|
path.push(line(lineToX, lineToY));
|
|
201
273
|
|
|
202
|
-
let arcToX =
|
|
203
|
-
let arcToY =
|
|
204
|
-
path.push(arc(r, r, 0,
|
|
274
|
+
let arcToX = cx + Math.cos(outerEndAngle) * r;
|
|
275
|
+
let arcToY = cy - Math.sin(outerEndAngle) * r;
|
|
276
|
+
path.push(arc(r, r, 0, largeArcFlag(outerEndAngle - outerStartAngle), 0, arcToX, arcToY));
|
|
205
277
|
}
|
|
206
278
|
|
|
207
279
|
path.push(z());
|
|
@@ -210,6 +282,8 @@ function createSvgArc(x, y, r0 = 0, r, startAngleRadian, endAngleRadian, br = 0)
|
|
|
210
282
|
|
|
211
283
|
PieChart.prototype.anchors = "0 1 1 0";
|
|
212
284
|
PieChart.prototype.angle = 360;
|
|
285
|
+
PieChart.prototype.startAngle = 0;
|
|
286
|
+
PieChart.prototype.gap = 0;
|
|
213
287
|
|
|
214
288
|
Widget.alias("pie-slice");
|
|
215
289
|
export class PieSlice extends Container {
|
|
@@ -220,7 +294,7 @@ export class PieSlice extends Container {
|
|
|
220
294
|
}
|
|
221
295
|
|
|
222
296
|
declareData() {
|
|
223
|
-
|
|
297
|
+
let selection = this.selection.configureWidget(this);
|
|
224
298
|
super.declareData(...arguments, selection, {
|
|
225
299
|
active: true,
|
|
226
300
|
r0: undefined,
|
|
@@ -263,7 +337,7 @@ export class PieSlice extends Container {
|
|
|
263
337
|
instance.hoverSync = context.hoverSync;
|
|
264
338
|
|
|
265
339
|
if (instance.valid && data.active) {
|
|
266
|
-
instance.pie.acknowledge(data.stack, data.value);
|
|
340
|
+
instance.pie.acknowledge(data.stack, data.value, data.r, data.r0, this.percentageRadius);
|
|
267
341
|
super.explore(context, instance);
|
|
268
342
|
}
|
|
269
343
|
}
|
|
@@ -277,7 +351,7 @@ export class PieSlice extends Container {
|
|
|
277
351
|
}
|
|
278
352
|
|
|
279
353
|
if (instance.valid && data.active) {
|
|
280
|
-
let seg = pie.map(data.stack, data.value);
|
|
354
|
+
let seg = pie.map(data.stack, data.value, data.r, data.r0, this.percentageRadius);
|
|
281
355
|
|
|
282
356
|
if (
|
|
283
357
|
!segment ||
|
|
@@ -344,15 +418,15 @@ export class PieSlice extends Container {
|
|
|
344
418
|
}
|
|
345
419
|
|
|
346
420
|
onLegendClick(e, instance) {
|
|
347
|
-
|
|
348
|
-
|
|
421
|
+
let allActions = this.legendAction == "auto";
|
|
422
|
+
let { data } = instance;
|
|
349
423
|
if (allActions || this.legendAction == "toggle") if (instance.set("active", !data.active)) return;
|
|
350
424
|
|
|
351
425
|
if (allActions || this.legendAction == "select") this.handleClick(e, instance);
|
|
352
426
|
}
|
|
353
427
|
|
|
354
428
|
render(context, instance, key) {
|
|
355
|
-
|
|
429
|
+
let { segment, data } = instance;
|
|
356
430
|
if (!instance.valid || !data.active) return null;
|
|
357
431
|
|
|
358
432
|
return withHoverSync(
|
|
@@ -361,7 +435,7 @@ export class PieSlice extends Container {
|
|
|
361
435
|
this.hoverChannel,
|
|
362
436
|
data.hoverId,
|
|
363
437
|
({ hover, onMouseMove, onMouseLeave }) => {
|
|
364
|
-
|
|
438
|
+
let stateMods = {
|
|
365
439
|
selected: this.selection.isInstanceSelected(instance),
|
|
366
440
|
disabled: data.disabled,
|
|
367
441
|
selectable: !this.selection.isDummy,
|
|
@@ -376,7 +450,8 @@ export class PieSlice extends Container {
|
|
|
376
450
|
data.r * segment.radiusMultiplier,
|
|
377
451
|
segment.startAngle,
|
|
378
452
|
segment.endAngle,
|
|
379
|
-
data.br
|
|
453
|
+
data.br,
|
|
454
|
+
segment.gap,
|
|
380
455
|
);
|
|
381
456
|
|
|
382
457
|
return (
|
|
@@ -400,7 +475,7 @@ export class PieSlice extends Container {
|
|
|
400
475
|
{this.renderChildren(context, instance)}
|
|
401
476
|
</g>
|
|
402
477
|
);
|
|
403
|
-
}
|
|
478
|
+
},
|
|
404
479
|
);
|
|
405
480
|
}
|
|
406
481
|
|
|
@@ -431,6 +506,10 @@ function arc(rx, ry, xRotation, largeArc, sweep, x, y) {
|
|
|
431
506
|
return `A ${rx} ${ry} ${xRotation} ${largeArc} ${sweep} ${x} ${y}`;
|
|
432
507
|
}
|
|
433
508
|
|
|
509
|
+
function largeArcFlag(angle) {
|
|
510
|
+
return angle > Math.PI || angle < -Math.PI ? 1 : 0;
|
|
511
|
+
}
|
|
512
|
+
|
|
434
513
|
PieSlice.prototype.offset = 0;
|
|
435
514
|
PieSlice.prototype.r0 = 0;
|
|
436
515
|
PieSlice.prototype.r = 50;
|
|
@@ -443,5 +522,6 @@ PieSlice.prototype.legendAction = "auto";
|
|
|
443
522
|
PieSlice.prototype.legendShape = "circle";
|
|
444
523
|
PieSlice.prototype.hoverChannel = "default";
|
|
445
524
|
PieSlice.prototype.styled = true;
|
|
525
|
+
PieSlice.prototype.br = 0;
|
|
446
526
|
|
|
447
527
|
Widget.alias("pie-chart", PieChart);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as Cx from "../core";
|
|
2
|
+
|
|
3
|
+
interface RangeMarkerProps extends Cx.StyledContainerProps {
|
|
4
|
+
/** The `x` value binding or expression. */
|
|
5
|
+
x?: Cx.NumberProp;
|
|
6
|
+
|
|
7
|
+
/** The `y` value binding or expression. */
|
|
8
|
+
y?: Cx.NumberProp;
|
|
9
|
+
|
|
10
|
+
/** The shape of marker, Could be `min`, `max`, `line`. Default to `line`. */
|
|
11
|
+
shape?: Cx.StringProp;
|
|
12
|
+
|
|
13
|
+
/** Switch to vertical mode. */
|
|
14
|
+
vertical?: Cx.BooleanProp;
|
|
15
|
+
|
|
16
|
+
/** Size of the range marker. */
|
|
17
|
+
size?: Cx.NumberProp;
|
|
18
|
+
|
|
19
|
+
/** Style object applied to the range marker. */
|
|
20
|
+
lineStyle?: Cx.StyleProp;
|
|
21
|
+
|
|
22
|
+
/** Class object applied to the range marker. */
|
|
23
|
+
lineClass?: Cx.StyleProp;
|
|
24
|
+
|
|
25
|
+
/** Size of vertical or horizontal caps. */
|
|
26
|
+
capSize?: Cx.NumberProp;
|
|
27
|
+
|
|
28
|
+
/** The laneOffset property adjusts the positioning of lane elements, enhancing their alignment and readability. */
|
|
29
|
+
laneOffset?: Cx.NumberProp;
|
|
30
|
+
|
|
31
|
+
/** Inflate the range marker.*/
|
|
32
|
+
inflate?: Cx.NumberProp;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class RangeMarkerProps extends Cx.Widget<RangeMarkerProps> {}
|