@easyv/charts 1.10.14 → 1.10.16
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/change.md +26 -0
- package/config.json +119 -0
- package/lib/components/Chart.js +5 -5
- package/lib/components/Legend.js +207 -16
- package/lib/components/Marquee.js +1 -1
- package/lib/components/PieChart.js +193 -102
- package/lib/formatter/legend.js +78 -26
- package/lib/utils/legendPlacement.js +37 -0
- package/package.json +1 -1
- package/src/components/Chart.js +11 -3
- package/src/components/Legend.js +256 -8
- package/src/components/Marquee.tsx +4 -4
- package/src/components/PieChart.js +161 -102
- package/src/formatter/legend.js +151 -68
- package/src/utils/legendPlacement.js +28 -0
package/src/formatter/legend.js
CHANGED
|
@@ -92,13 +92,20 @@ export const pieLegendFormatter = (series, props) => {
|
|
|
92
92
|
|
|
93
93
|
const _color = seriesColorType == "pure" ? pure : stops[0].color;
|
|
94
94
|
const textMarginLeft = 5;
|
|
95
|
+
const { adaptiveMaxWidth, isPieAdaptive, chartWidth } = props;
|
|
96
|
+
const isSideAdaptive = !!adaptiveMaxWidth;
|
|
97
|
+
const isTopBottomAdaptive = isPieAdaptive && !isSideAdaptive;
|
|
98
|
+
const nameOverflowType =
|
|
99
|
+
isSideAdaptive || isTopBottomAdaptive ? "ellipsis" : textOverflow;
|
|
95
100
|
|
|
96
|
-
// 1.
|
|
101
|
+
// 1. 计算每列宽度(加上间距);正上/正下自适应不按全局列宽对齐
|
|
97
102
|
let columns = [];
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
if (!isTopBottomAdaptive) {
|
|
104
|
+
if (showName) columns.push(`${props.nameMaxWidth}px`);
|
|
105
|
+
if (showValue) columns.push(`${props.valueMaxWidth + valueGap}px`);
|
|
106
|
+
if (showPercent) columns.push(`${props.percentMaxWidth + percentGap}px`);
|
|
107
|
+
}
|
|
108
|
+
if (!isTopBottomAdaptive && series.fieldsData.length > 0) {
|
|
102
109
|
//网格布局新增的各列宽度
|
|
103
110
|
series.fieldsData.forEach((item) => {
|
|
104
111
|
const idx = item.fieldsColumnIndex ?? 0;
|
|
@@ -135,6 +142,66 @@ export const pieLegendFormatter = (series, props) => {
|
|
|
135
142
|
});
|
|
136
143
|
}
|
|
137
144
|
|
|
145
|
+
const scaleColumnsToMax = (cols, maxTotal) => {
|
|
146
|
+
const widths = cols.map((c) => parseFloat(c) || 0);
|
|
147
|
+
const total = widths.reduce((a, b) => a + b, 0);
|
|
148
|
+
if (!total || total <= maxTotal) return cols.join(" ");
|
|
149
|
+
const scale = maxTotal / total;
|
|
150
|
+
return widths
|
|
151
|
+
.map((w) => `${Math.max(1, Math.floor(w * scale))}px`)
|
|
152
|
+
.join(" ");
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const sideGridMaxWidth = isSideAdaptive
|
|
156
|
+
? Math.max(
|
|
157
|
+
0,
|
|
158
|
+
adaptiveMaxWidth -
|
|
159
|
+
(icon
|
|
160
|
+
? (parseFloat(icon.width) || 0) +
|
|
161
|
+
(parseFloat(icon.marginRight) || 0)
|
|
162
|
+
: 0),
|
|
163
|
+
)
|
|
164
|
+
: adaptiveMaxWidth;
|
|
165
|
+
|
|
166
|
+
const contentStyle = isSideAdaptive
|
|
167
|
+
? {
|
|
168
|
+
display: "grid",
|
|
169
|
+
gridTemplateColumns: scaleColumnsToMax(columns, sideGridMaxWidth),
|
|
170
|
+
width: "max-content",
|
|
171
|
+
maxWidth: "100%",
|
|
172
|
+
minWidth: 0,
|
|
173
|
+
overflow: "hidden",
|
|
174
|
+
boxSizing: "border-box",
|
|
175
|
+
}
|
|
176
|
+
: isTopBottomAdaptive
|
|
177
|
+
? {
|
|
178
|
+
display: "flex",
|
|
179
|
+
flexDirection: "row",
|
|
180
|
+
alignItems: "center",
|
|
181
|
+
flexWrap: "nowrap",
|
|
182
|
+
width: "max-content",
|
|
183
|
+
maxWidth: chartWidth ? `${chartWidth}px` : "100%",
|
|
184
|
+
minWidth: 0,
|
|
185
|
+
overflow: "hidden",
|
|
186
|
+
boxSizing: "border-box",
|
|
187
|
+
gap: `${valueGap}px ${percentGap}px`,
|
|
188
|
+
}
|
|
189
|
+
: {
|
|
190
|
+
width: `calc( 100% + ${textMarginLeft + valueGap + percentGap}px )`,
|
|
191
|
+
gridTemplateColumns: columns.join(" "),
|
|
192
|
+
overflowX: "visible",
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const contentClassName = isTopBottomAdaptive
|
|
196
|
+
? undefined
|
|
197
|
+
: isSideAdaptive
|
|
198
|
+
? showName && showValue && showPercent
|
|
199
|
+
? css.showAllStyle
|
|
200
|
+
: css.notShowAllStyle
|
|
201
|
+
: showName && showValue && showPercent
|
|
202
|
+
? css.showAllStyle
|
|
203
|
+
: css.notShowAllStyle;
|
|
204
|
+
|
|
138
205
|
return (
|
|
139
206
|
<>
|
|
140
207
|
{icon && (
|
|
@@ -142,30 +209,33 @@ export const pieLegendFormatter = (series, props) => {
|
|
|
142
209
|
style={{
|
|
143
210
|
...icon,
|
|
144
211
|
marginRight: icon.marginRight,
|
|
212
|
+
flexShrink: 0,
|
|
145
213
|
transform: `translate(${nameX}px, ${nameY}px)`,
|
|
146
214
|
}}
|
|
147
215
|
/>
|
|
148
216
|
)}
|
|
149
|
-
<div
|
|
150
|
-
className={
|
|
151
|
-
showName && showValue && showPercent
|
|
152
|
-
? css.showAllStyle
|
|
153
|
-
: css.notShowAllStyle
|
|
154
|
-
}
|
|
155
|
-
style={{
|
|
156
|
-
width: `calc( 100% + ${textMarginLeft + valueGap + percentGap}px )`,
|
|
157
|
-
gridTemplateColumns: columns.join(" "),
|
|
158
|
-
overflowX: "visible",
|
|
159
|
-
}}
|
|
160
|
-
>
|
|
217
|
+
<div className={contentClassName} style={contentStyle}>
|
|
161
218
|
{showName && (
|
|
162
219
|
<TextOverflow
|
|
163
220
|
value={displayName}
|
|
164
|
-
type={
|
|
221
|
+
type={nameOverflowType}
|
|
165
222
|
speed={speed}
|
|
166
223
|
style={{
|
|
167
|
-
width:
|
|
224
|
+
width: isSideAdaptive
|
|
225
|
+
? "100%"
|
|
226
|
+
: isTopBottomAdaptive
|
|
227
|
+
? "auto"
|
|
228
|
+
: maxWidth,
|
|
229
|
+
maxWidth: isSideAdaptive
|
|
230
|
+
? "100%"
|
|
231
|
+
: isTopBottomAdaptive
|
|
232
|
+
? "none"
|
|
233
|
+
: maxWidth,
|
|
234
|
+
minWidth: isSideAdaptive ? 0 : undefined,
|
|
235
|
+
flexShrink: isTopBottomAdaptive ? 1 : undefined,
|
|
168
236
|
marginLeft: textMarginLeft,
|
|
237
|
+
// whiteSpace: "nowrap",
|
|
238
|
+
overflow: "hidden",
|
|
169
239
|
...getFontStyle(nameFont),
|
|
170
240
|
transform: `translate(${nameX}px, ${nameY}px)`,
|
|
171
241
|
}}
|
|
@@ -177,12 +247,17 @@ export const pieLegendFormatter = (series, props) => {
|
|
|
177
247
|
display: "flex",
|
|
178
248
|
whiteSpace: "nowrap",
|
|
179
249
|
...getFontStyle(valueFont),
|
|
180
|
-
marginLeft: valueGap,
|
|
250
|
+
marginLeft: isSideAdaptive || isTopBottomAdaptive ? 0 : valueGap,
|
|
251
|
+
flexShrink: isTopBottomAdaptive ? 0 : undefined,
|
|
181
252
|
transform: `translate(${valueX}px,${valueY}px)`,
|
|
182
253
|
color: valueSameColor ? _color : valueFont.color,
|
|
183
254
|
alignItems: "center",
|
|
184
|
-
justifyContent: alignToJustify(
|
|
185
|
-
|
|
255
|
+
justifyContent: alignToJustify(
|
|
256
|
+
isTopBottomAdaptive ? "left" : (valueAlign ?? "center"),
|
|
257
|
+
),
|
|
258
|
+
textAlign: alignToTextAlign(
|
|
259
|
+
isTopBottomAdaptive ? "left" : valueAlign,
|
|
260
|
+
),
|
|
186
261
|
}}
|
|
187
262
|
>
|
|
188
263
|
<span>
|
|
@@ -207,66 +282,74 @@ export const pieLegendFormatter = (series, props) => {
|
|
|
207
282
|
display: "flex",
|
|
208
283
|
whiteSpace: "nowrap",
|
|
209
284
|
...getFontStyle(percentFont),
|
|
210
|
-
marginLeft:
|
|
285
|
+
marginLeft:
|
|
286
|
+
isSideAdaptive || isTopBottomAdaptive ? 0 : percentGap,
|
|
287
|
+
flexShrink: isTopBottomAdaptive ? 0 : undefined,
|
|
211
288
|
transform: `translate(${percentX}px,${percentY}px)`,
|
|
212
289
|
color: percentSameColor ? _color : percentFont.color,
|
|
213
290
|
alignItems: "center",
|
|
214
|
-
justifyContent: alignToJustify(
|
|
215
|
-
|
|
291
|
+
justifyContent: alignToJustify(
|
|
292
|
+
isTopBottomAdaptive ? "left" : percentAlign,
|
|
293
|
+
),
|
|
294
|
+
textAlign: alignToTextAlign(
|
|
295
|
+
isTopBottomAdaptive ? "left" : percentAlign,
|
|
296
|
+
),
|
|
216
297
|
}}
|
|
217
298
|
>
|
|
218
299
|
{percent + "%"}
|
|
219
300
|
</span>
|
|
220
301
|
)}
|
|
221
|
-
{series.fieldsData?.map(
|
|
222
|
-
|
|
223
|
-
item
|
|
224
|
-
|
|
225
|
-
|
|
302
|
+
{series.fieldsData?.map((item, index) => (
|
|
303
|
+
<span
|
|
304
|
+
key={fieldColumnKeys[item.fieldsColumnIndex ?? index] ?? index}
|
|
305
|
+
style={{
|
|
306
|
+
display: "flex",
|
|
307
|
+
boxSizing: "border-box",
|
|
308
|
+
width: isTopBottomAdaptive ? "auto" : "100%",
|
|
309
|
+
minWidth: 0,
|
|
310
|
+
flexShrink: isTopBottomAdaptive ? 0 : undefined,
|
|
311
|
+
alignItems: "center",
|
|
312
|
+
justifyContent: alignToJustify(
|
|
313
|
+
isTopBottomAdaptive ? "left" : (item.align ?? "center"),
|
|
314
|
+
),
|
|
315
|
+
textAlign: alignToTextAlign(
|
|
316
|
+
isTopBottomAdaptive ? "left" : (item.align ?? "center"),
|
|
317
|
+
),
|
|
318
|
+
overflow:
|
|
319
|
+
isSideAdaptive || isTopBottomAdaptive ? "hidden" : "visible",
|
|
320
|
+
whiteSpace: "nowrap",
|
|
321
|
+
...getFontStyle(item.font),
|
|
322
|
+
color: item.sameColor ? _color : item.font.color,
|
|
323
|
+
}}
|
|
324
|
+
>
|
|
226
325
|
<span
|
|
227
|
-
key={fieldColumnKeys[item.fieldsColumnIndex ?? index] ?? index}
|
|
228
326
|
style={{
|
|
229
|
-
display: "flex",
|
|
230
|
-
boxSizing: "border-box",
|
|
231
|
-
width: "100%",
|
|
232
|
-
minWidth: 0,
|
|
327
|
+
display: "inline-flex",
|
|
233
328
|
alignItems: "center",
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
color: item.sameColor ? _color : item.font.color,
|
|
329
|
+
flexWrap: "nowrap",
|
|
330
|
+
whiteSpace: "nowrap",
|
|
331
|
+
marginLeft: item.translate?.x ?? 0,
|
|
332
|
+
marginTop: item.translate?.y ?? 0,
|
|
239
333
|
}}
|
|
240
334
|
>
|
|
241
|
-
<span
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
style={{
|
|
257
|
-
whiteSpace: "nowrap",
|
|
258
|
-
fontSize: item.suffix.fontSize,
|
|
259
|
-
marginLeft: item.suffix.translate?.x ?? 0,
|
|
260
|
-
marginTop: item.suffix.translate?.y ?? 0,
|
|
261
|
-
}}
|
|
262
|
-
>
|
|
263
|
-
{item.suffix.text}
|
|
264
|
-
</span>
|
|
265
|
-
)}
|
|
266
|
-
</span>
|
|
335
|
+
<span style={{ whiteSpace: "nowrap" }}>{item.value}</span>
|
|
336
|
+
{item.suffix?.show &&
|
|
337
|
+
item.suffix?.text != null &&
|
|
338
|
+
String(item.suffix.text) !== "" && (
|
|
339
|
+
<span
|
|
340
|
+
style={{
|
|
341
|
+
whiteSpace: "nowrap",
|
|
342
|
+
fontSize: item.suffix.fontSize,
|
|
343
|
+
marginLeft: item.suffix.translate?.x ?? 0,
|
|
344
|
+
marginTop: item.suffix.translate?.y ?? 0,
|
|
345
|
+
}}
|
|
346
|
+
>
|
|
347
|
+
{item.suffix.text}
|
|
348
|
+
</span>
|
|
349
|
+
)}
|
|
267
350
|
</span>
|
|
268
|
-
|
|
269
|
-
)}
|
|
351
|
+
</span>
|
|
352
|
+
))}
|
|
270
353
|
</div>
|
|
271
354
|
</>
|
|
272
355
|
);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 解析图例 layout.alignment(如 "center top"、"right top")
|
|
3
|
+
* 格式:{水平对齐} {位置},位置为 top | right | left | bottom
|
|
4
|
+
*/
|
|
5
|
+
export const parseLegendAlignment = (alignment = "right center") => {
|
|
6
|
+
const [_alignment, position] = alignment.split(" ");
|
|
7
|
+
const isCenterTopOrBottom =
|
|
8
|
+
(position === "top" || position === "bottom") && _alignment === "center";
|
|
9
|
+
const isSidePlacement =
|
|
10
|
+
position === "left" ||
|
|
11
|
+
position === "right" ||
|
|
12
|
+
((position === "top" || position === "bottom") && _alignment !== "center");
|
|
13
|
+
return {
|
|
14
|
+
alignment: _alignment,
|
|
15
|
+
position,
|
|
16
|
+
isCenterTopOrBottom,
|
|
17
|
+
isSidePlacement,
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const getPieAdaptiveMarginPreset = (show, alignment, presets) => {
|
|
22
|
+
if (!show) return presets.hidden;
|
|
23
|
+
const { alignment: mainAlign, position, isCenterTopOrBottom } =
|
|
24
|
+
parseLegendAlignment(alignment);
|
|
25
|
+
if (isCenterTopOrBottom) return presets[position];
|
|
26
|
+
if (position === "left" || mainAlign === "left") return presets.left;
|
|
27
|
+
return presets.right;
|
|
28
|
+
};
|