Skip to content

Commit 3991a66

Browse files
feat: standardize the className of the axis (#362)
* feat: standardize the className of the axis * feat: legend axis 根节点 className 兼容 * feat: legend axis 根节点 className 兼容 * fix: fix cr
1 parent bace973 commit 3991a66

13 files changed

Lines changed: 240 additions & 46 deletions

File tree

src/ui/axis/axis.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { renderAxisLine } from './guides/line';
1111
import { renderTicks } from './guides/ticks';
1212
import { renderTitle } from './guides/title';
1313
import type { AxisDatum, AxisOptions, AxisStyleProps, RequiredAxisStyleProps } from './types';
14+
import { applyClassName, getAxisClassName } from './utils/classname';
15+
import { CLASSNAME_SUFFIX_MAP } from './classname-map';
1416

1517
export type {
1618
ArcAxisOptions,
@@ -27,23 +29,26 @@ function renderAxisMain(
2729
data: AxisDatum[],
2830
animation: StandardAnimationOption
2931
) {
30-
const { showLine, showTick, showLabel } = attributes;
32+
const { showLine, showTick, showLabel, classNamePrefix } = attributes;
3133
/** line */
3234
const lineGroup = container.maybeAppendByClassName(CLASS_NAMES.lineGroup, 'g');
35+
applyClassName(lineGroup, CLASS_NAMES.lineGroup, CLASSNAME_SUFFIX_MAP.lineGroup, classNamePrefix);
3336
const lineTransitions =
3437
ifShow(showLine!, lineGroup, (group) => {
3538
return renderAxisLine(group, attributes, animation);
3639
}) || [];
3740

3841
/** tick */
3942
const tickGroup = container.maybeAppendByClassName(CLASS_NAMES.tickGroup, 'g');
43+
applyClassName(tickGroup, CLASS_NAMES.tickGroup, CLASSNAME_SUFFIX_MAP.tickGroup, classNamePrefix);
4044
const tickTransitions =
4145
ifShow(showTick!, tickGroup, (group) => {
4246
return renderTicks(group, data, attributes, animation);
4347
}) || [];
4448

4549
/** label */
4650
const labelGroup = container.maybeAppendByClassName(CLASS_NAMES.labelGroup, 'g');
51+
applyClassName(labelGroup, CLASS_NAMES.labelGroup, CLASSNAME_SUFFIX_MAP.labelGroup, classNamePrefix);
4752
const labelTransitions =
4853
ifShow(showLabel!, labelGroup, (group) => {
4954
return renderLabels(group, data, attributes, animation, container.node());
@@ -58,7 +63,16 @@ export class Axis extends Component<AxisStyleProps> {
5863
}
5964

6065
render(attributes: RequiredAxisStyleProps, container: Group, specificAnimation?: GenericAnimation) {
61-
const { titleText, data, animate, showTitle, showGrid, dataThreshold, truncRange } = attributes;
66+
const { titleText, data, animate, showTitle, showGrid, dataThreshold, truncRange, classNamePrefix } = attributes;
67+
68+
// Set root container className
69+
const baseClassName = container.className || 'axis';
70+
if (classNamePrefix) {
71+
container.attr('className', `${baseClassName} ${classNamePrefix}axis`);
72+
} else if (!container.className) {
73+
container.attr('className', 'axis');
74+
}
75+
6276
const sampledData = sampling(data, dataThreshold).filter(({ value }) => {
6377
if (truncRange && value > truncRange[0] && value < truncRange[1]) return false;
6478
return true;
@@ -68,11 +82,13 @@ export class Axis extends Component<AxisStyleProps> {
6882

6983
/** grid */
7084
const gridGroup = select(container).maybeAppendByClassName(CLASS_NAMES.gridGroup, 'g');
85+
applyClassName(gridGroup, CLASS_NAMES.gridGroup, CLASSNAME_SUFFIX_MAP.gridGroup, classNamePrefix);
7186
const gridTransitions =
7287
ifShow(showGrid!, gridGroup, (group) => renderGrid(group, sampledData, attributes, finalAnimation)) || [];
7388

7489
/** main group */
7590
const mainGroup = select(container).maybeAppendByClassName(CLASS_NAMES.mainGroup, 'g');
91+
applyClassName(mainGroup, CLASS_NAMES.mainGroup, CLASSNAME_SUFFIX_MAP.mainGroup, classNamePrefix);
7692

7793
if (titleText && ((!this.initialized && finalAnimation.enter) || (this.initialized && finalAnimation.update))) {
7894
renderAxisMain(attributes, select(this.offscreenGroup), sampledData, parseAnimationOption(false));
@@ -81,6 +97,7 @@ export class Axis extends Component<AxisStyleProps> {
8197
const mainTransitions = renderAxisMain(attributes, select(mainGroup.node()), sampledData, finalAnimation);
8298
/** title */
8399
const titleGroup = select(container).maybeAppendByClassName(CLASS_NAMES.titleGroup, 'g');
100+
applyClassName(titleGroup, CLASS_NAMES.titleGroup, CLASSNAME_SUFFIX_MAP.titleGroup, classNamePrefix);
84101
const titleTransitions =
85102
ifShow(showTitle, titleGroup, (group) => {
86103
return renderTitle(group, this, attributes, finalAnimation);

src/ui/axis/classname-map.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export const CLASSNAME_SUFFIX_MAP = {
2+
// group
3+
gridGroup: 'grid-group',
4+
mainGroup: 'main-group',
5+
lineGroup: 'line-group',
6+
tickGroup: 'tick-group',
7+
labelGroup: 'label-group',
8+
titleGroup: 'title-group',
9+
10+
// content
11+
grid: 'grid',
12+
line: 'line',
13+
lineFirst: 'line-first',
14+
lineSecond: 'line-second',
15+
tick: 'tick',
16+
tickItem: 'tick-item',
17+
label: 'label',
18+
labelItem: 'label-item',
19+
title: 'title',
20+
} as const;
21+
22+
export type ClassNameSuffix = keyof typeof CLASSNAME_SUFFIX_MAP;

src/ui/axis/constant.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { Path } from '../../shapes';
33
import { classNames } from '../../util';
44
import type { AxisBaseStyleProps } from './types';
55

6+
import { CLASSNAME_SUFFIX_MAP } from './classname-map';
7+
68
export const AXIS_BASE_DEFAULT_ATTR: Partial<AxisBaseStyleProps> = {
79
data: [],
810
animate: {
@@ -76,21 +78,21 @@ export const HELIX_DEFAULT_OPTIONS = deepMix({}, AXIS_BASE_DEFAULT_ATTR, {
7678

7779
export const CLASS_NAMES = classNames(
7880
{
79-
mainGroup: 'main-group',
80-
gridGroup: 'grid-group',
81-
grid: 'grid',
82-
lineGroup: 'line-group',
83-
line: 'line',
84-
tickGroup: 'tick-group',
85-
tick: 'tick',
86-
tickItem: 'tick-item',
87-
labelGroup: 'label-group',
88-
label: 'label',
89-
labelItem: 'label-item',
90-
titleGroup: 'title-group',
91-
title: 'title',
92-
lineFirst: 'line-first',
93-
lineSecond: 'line-second',
81+
mainGroup: CLASSNAME_SUFFIX_MAP.mainGroup,
82+
gridGroup: CLASSNAME_SUFFIX_MAP.gridGroup,
83+
grid: CLASSNAME_SUFFIX_MAP.grid,
84+
lineGroup: CLASSNAME_SUFFIX_MAP.lineGroup,
85+
line: CLASSNAME_SUFFIX_MAP.line,
86+
tickGroup: CLASSNAME_SUFFIX_MAP.tickGroup,
87+
tick: CLASSNAME_SUFFIX_MAP.tick,
88+
tickItem: CLASSNAME_SUFFIX_MAP.tickItem,
89+
labelGroup: CLASSNAME_SUFFIX_MAP.labelGroup,
90+
label: CLASSNAME_SUFFIX_MAP.label,
91+
labelItem: CLASSNAME_SUFFIX_MAP.labelItem,
92+
titleGroup: CLASSNAME_SUFFIX_MAP.titleGroup,
93+
title: CLASSNAME_SUFFIX_MAP.title,
94+
lineFirst: CLASSNAME_SUFFIX_MAP.lineFirst,
95+
lineSecond: CLASSNAME_SUFFIX_MAP.lineSecond,
9496
},
9597
'axis'
9698
);

src/ui/axis/guides/grid.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { CLASS_NAMES } from '../constant';
77
import type { AxisDatum, AxisGridStyleProps, AxisStyleProps } from '../types';
88
import { getValuePos } from './line';
99
import { filterExec, getDirectionVector } from './utils';
10+
import { applyClassName } from '../utils/classname';
11+
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';
1012

1113
function getGridVector(value: number, attr: Required<AxisStyleProps>) {
1214
return getDirectionVector(value, attr.gridDirection, attr);
@@ -63,6 +65,7 @@ export function renderGrid(
6365
attr: Required<AxisStyleProps>,
6466
animate: StandardAnimationOption
6567
) {
68+
const { classNamePrefix } = attr;
6669
const gridAttr = subStyleProps<Required<AxisGridStyleProps>>(attr, 'grid');
6770
const { type, areaFill } = gridAttr;
6871
const center = getGridCenter(attr);
@@ -83,7 +86,11 @@ export function renderGrid(
8386
.selectAll(CLASS_NAMES.grid.class)
8487
.data([1])
8588
.join(
86-
(enter) => enter.append(() => new Grid({ style })).attr('className', CLASS_NAMES.grid.name),
89+
(enter) => {
90+
const grid = enter.append(() => new Grid({ style })).attr('className', CLASS_NAMES.grid.name);
91+
applyClassName(grid, CLASS_NAMES.grid, CLASSNAME_SUFFIX_MAP.grid, classNamePrefix);
92+
return grid;
93+
},
8794
(update) =>
8895
update.transition(function () {
8996
return this.update(style);

src/ui/axis/guides/labels.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import type { AxisDatum, AxisLabelStyleProps, AxisStyleProps } from '../types';
3030
import { getFactor } from '../utils';
3131
import { getValuePos } from './line';
3232
import { filterExec, getCallbackStyle, getLabelVector, getLineTangentVector } from './utils';
33+
import { applyClassName } from '../utils/classname';
34+
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';
3335

3436
function angleNormalizer(angle: number) {
3537
let normalizedAngle = angle;
@@ -198,7 +200,9 @@ function overlapHandler(attr: Required<AxisStyleProps>, main: DisplayObject) {
198200
wrap: (label, width, lines) => {
199201
label && wrapIt(label, width, lines);
200202
},
201-
getTextShape: (label) => label.querySelector<DisplayObject>('text') as Text,
203+
getTextShape: (label) => {
204+
return label.querySelector<DisplayObject>(CLASS_NAMES.labelItem.class) as Text;
205+
},
202206
});
203207
}
204208

@@ -210,11 +214,13 @@ function renderLabel(
210214
attr: Required<AxisStyleProps>
211215
): DisplayObject {
212216
const index = data.indexOf(datum);
213-
const { labelRender } = attr;
217+
const { labelRender, classNamePrefix } = attr;
218+
214219
const label = select(container)
215220
.append(labelRender ? renderHTMLLabel(datum, index, data, attr) : formatter(datum, index, data, attr))
216221
.attr('className', CLASS_NAMES.labelItem.name)
217222
.node();
223+
applyClassName(select(label), CLASS_NAMES.labelItem, CLASSNAME_SUFFIX_MAP.labelItem, classNamePrefix);
218224
const [labelStyle, { transform, ...groupStyle }] = splitStyle(getCallbackStyle(style, [datum, index, data]));
219225

220226
percentTransform(label, transform);
@@ -238,24 +244,28 @@ export function renderLabels(
238244
animate: StandardAnimationOption,
239245
main: DisplayObject
240246
) {
247+
const { classNamePrefix } = attr;
241248
const finalData = filterExec(data, attr.labelFilter);
242249
const style = subStyleProps<AxisLabelStyleProps>(attr, 'label');
250+
243251
let _exit!: Selection<AxisDatum>;
244252
const transitions = container
245253
.selectAll(CLASS_NAMES.label.class)
246254
.data(finalData, (d, i) => i)
247255
.join(
248-
(enter) =>
249-
enter
256+
(enter) => {
257+
const labels = enter
250258
.append('g')
251259
.attr('className', CLASS_NAMES.label.name)
252260
.transition(function (datum) {
253261
renderLabel(this, datum, data, style, attr);
254262
const { x, y } = getLabelPos(datum, data, attr);
255-
// .axis-label
256263
this.style.transform = `translate(${x}, ${y})`;
257264
return null;
258-
}),
265+
});
266+
applyClassName(labels, CLASS_NAMES.label, CLASSNAME_SUFFIX_MAP.label, classNamePrefix);
267+
return labels;
268+
},
259269
(update) =>
260270
update.transition(function (datum) {
261271
const prevLabel = this.querySelector(CLASS_NAMES.labelItem.class);

src/ui/axis/guides/line.ts

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import {
1515
import { CLASS_NAMES } from '../constant';
1616
import type { RequiredArcAxisStyleProps, RequiredAxisStyleProps, RequiredLinearAxisStyleProps } from '../types';
1717
import { getLineAngle, getLineTangentVector } from './utils';
18+
import { applyClassName, getAxisClassName } from '../utils/classname';
19+
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';
1820

1921
type LineDatum = {
2022
line: [Vector2, Vector2];
@@ -97,18 +99,21 @@ function renderArc(
9799
style: RequiredArcAxisStyleProps,
98100
animate: StandardAnimationOption
99101
) {
100-
const { startAngle, endAngle, center, radius } = attr;
102+
const { startAngle, endAngle, center, radius, classNamePrefix } = attr;
101103

102104
return container
103105
.selectAll(CLASS_NAMES.line.class)
104106
.data([{ d: getArcPath(startAngle, endAngle, ...center, radius) }], (d, i) => i)
105107
.join(
106-
(enter) =>
107-
enter
108+
(enter) => {
109+
const line = enter
108110
.append('path')
109111
.attr('className', CLASS_NAMES.line.name)
110112
.styles(attr)
111-
.styles({ d: (d: any) => d.d }),
113+
.styles({ d: (d: any) => d.d });
114+
applyClassName(line, CLASS_NAMES.line, CLASSNAME_SUFFIX_MAP.line, classNamePrefix);
115+
return line;
116+
},
112117
(update) =>
113118
update
114119
.transition(function () {
@@ -158,22 +163,51 @@ function renderLinear(
158163
style: RequiredLinearAxisStyleProps,
159164
animate: StandardAnimationOption
160165
) {
161-
const { showTrunc, startPos, endPos, truncRange, lineExtension } = attr;
166+
const { showTrunc, startPos, endPos, truncRange, lineExtension, classNamePrefix } = attr;
162167
const [[x1, y1], [x2, y2]] = [startPos, endPos];
163168
const [ox1, oy1, ox2, oy2] = lineExtension ? extendLine(startPos, endPos, lineExtension) : new Array(4).fill(0);
164169
const renderLine = (data: LineDatum[]) => {
165170
return container
166171
.selectAll(CLASS_NAMES.line.class)
167172
.data(data, (d, i) => i)
168173
.join(
169-
(enter) =>
170-
enter
174+
(enter) => {
175+
const lines = enter
171176
.append('line')
172-
.attr('className', (d: LineDatum) => `${CLASS_NAMES.line.name} ${d.className}`)
173177
.styles(style)
174178
.transition(function (d: LineDatum) {
175179
return transition(this, getLinePath(d.line), false);
176-
}),
180+
});
181+
// Set className with appropriate logic for line elements
182+
lines.attr('className', (d: LineDatum) => {
183+
if (!classNamePrefix) {
184+
return `${CLASS_NAMES.line.name} ${d.className}`;
185+
}
186+
const baseLineClassName = getAxisClassName(
187+
CLASS_NAMES.line.name,
188+
CLASSNAME_SUFFIX_MAP.line,
189+
classNamePrefix
190+
);
191+
if (d.className === CLASS_NAMES.lineFirst.name) {
192+
const specificClassName = getAxisClassName(
193+
CLASS_NAMES.lineFirst.name,
194+
CLASSNAME_SUFFIX_MAP.lineFirst,
195+
classNamePrefix
196+
);
197+
return `${baseLineClassName} ${specificClassName}`;
198+
}
199+
if (d.className === CLASS_NAMES.lineSecond.name) {
200+
const specificClassName = getAxisClassName(
201+
CLASS_NAMES.lineSecond.name,
202+
CLASSNAME_SUFFIX_MAP.lineSecond,
203+
classNamePrefix
204+
);
205+
return `${baseLineClassName} ${specificClassName}`;
206+
}
207+
return baseLineClassName;
208+
});
209+
return lines;
210+
},
177211
(update) =>
178212
update.styles(style).transition(function ({ line }: LineDatum) {
179213
return transition(this, getLinePath(line), animate.update);
@@ -228,9 +262,13 @@ function renderAxisArrow(
228262
const { showArrow, showTrunc, lineArrow, lineArrowOffset, lineArrowSize } = attr;
229263

230264
let shapeToAddArrow: Selection;
231-
if (type === 'arc') shapeToAddArrow = container.select(CLASS_NAMES.line.class);
232-
else if (showTrunc) shapeToAddArrow = container.select(CLASS_NAMES.lineSecond.class);
233-
else shapeToAddArrow = container.select(CLASS_NAMES.line.class);
265+
if (type === 'arc') {
266+
shapeToAddArrow = container.select(CLASS_NAMES.line.class);
267+
} else if (showTrunc) {
268+
shapeToAddArrow = container.select(CLASS_NAMES.lineSecond.class);
269+
} else {
270+
shapeToAddArrow = container.select(CLASS_NAMES.line.class);
271+
}
234272
if (!showArrow || !lineArrow || (attr.type === 'arc' && isCircle(attr.startAngle, attr.endAngle))) {
235273
const node = shapeToAddArrow.node<Line>();
236274
if (node) node.style.markerEnd = undefined;

0 commit comments

Comments
 (0)