Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/ui/axis/axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { renderAxisLine } from './guides/line';
import { renderTicks } from './guides/ticks';
import { renderTitle } from './guides/title';
import type { AxisDatum, AxisOptions, AxisStyleProps, RequiredAxisStyleProps } from './types';
import { applyClassName, getAxisClassName } from './utils/classname';
import { CLASSNAME_SUFFIX_MAP } from './classname-map';

export type {
ArcAxisOptions,
Expand All @@ -27,23 +29,26 @@ function renderAxisMain(
data: AxisDatum[],
animation: StandardAnimationOption
) {
const { showLine, showTick, showLabel } = attributes;
const { showLine, showTick, showLabel, classNamePrefix } = attributes;
/** line */
const lineGroup = container.maybeAppendByClassName(CLASS_NAMES.lineGroup, 'g');
applyClassName(lineGroup, CLASS_NAMES.lineGroup, CLASSNAME_SUFFIX_MAP.lineGroup, classNamePrefix);
const lineTransitions =
ifShow(showLine!, lineGroup, (group) => {
return renderAxisLine(group, attributes, animation);
}) || [];

/** tick */
const tickGroup = container.maybeAppendByClassName(CLASS_NAMES.tickGroup, 'g');
applyClassName(tickGroup, CLASS_NAMES.tickGroup, CLASSNAME_SUFFIX_MAP.tickGroup, classNamePrefix);
const tickTransitions =
ifShow(showTick!, tickGroup, (group) => {
return renderTicks(group, data, attributes, animation);
}) || [];

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

render(attributes: RequiredAxisStyleProps, container: Group, specificAnimation?: GenericAnimation) {
const { titleText, data, animate, showTitle, showGrid, dataThreshold, truncRange } = attributes;
const { titleText, data, animate, showTitle, showGrid, dataThreshold, truncRange, classNamePrefix } = attributes;

// Set root container className
const baseClassName = container.className || 'axis';
if (classNamePrefix) {
container.attr('className', `${baseClassName} ${classNamePrefix}axis`);
} else if (!container.className) {
container.attr('className', 'axis');
}

const sampledData = sampling(data, dataThreshold).filter(({ value }) => {
if (truncRange && value > truncRange[0] && value < truncRange[1]) return false;
return true;
Expand All @@ -68,11 +82,13 @@ export class Axis extends Component<AxisStyleProps> {

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

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

if (titleText && ((!this.initialized && finalAnimation.enter) || (this.initialized && finalAnimation.update))) {
renderAxisMain(attributes, select(this.offscreenGroup), sampledData, parseAnimationOption(false));
Expand All @@ -81,6 +97,7 @@ export class Axis extends Component<AxisStyleProps> {
const mainTransitions = renderAxisMain(attributes, select(mainGroup.node()), sampledData, finalAnimation);
/** title */
const titleGroup = select(container).maybeAppendByClassName(CLASS_NAMES.titleGroup, 'g');
applyClassName(titleGroup, CLASS_NAMES.titleGroup, CLASSNAME_SUFFIX_MAP.titleGroup, classNamePrefix);
const titleTransitions =
ifShow(showTitle, titleGroup, (group) => {
return renderTitle(group, this, attributes, finalAnimation);
Expand Down
22 changes: 22 additions & 0 deletions src/ui/axis/classname-map.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export const CLASSNAME_SUFFIX_MAP = {
// group
gridGroup: 'grid-group',
mainGroup: 'main-group',
lineGroup: 'line-group',
tickGroup: 'tick-group',
labelGroup: 'label-group',
titleGroup: 'title-group',

// content
grid: 'grid',
line: 'line',
lineFirst: 'line-first',
lineSecond: 'line-second',
tick: 'tick',
tickItem: 'tick-item',
label: 'label',
labelItem: 'label-item',
title: 'title',
} as const;

export type ClassNameSuffix = keyof typeof CLASSNAME_SUFFIX_MAP;
32 changes: 17 additions & 15 deletions src/ui/axis/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Path } from '../../shapes';
import { classNames } from '../../util';
import type { AxisBaseStyleProps } from './types';

import { CLASSNAME_SUFFIX_MAP } from './classname-map';

export const AXIS_BASE_DEFAULT_ATTR: Partial<AxisBaseStyleProps> = {
data: [],
animate: {
Expand Down Expand Up @@ -76,21 +78,21 @@ export const HELIX_DEFAULT_OPTIONS = deepMix({}, AXIS_BASE_DEFAULT_ATTR, {

export const CLASS_NAMES = classNames(
{
mainGroup: 'main-group',
gridGroup: 'grid-group',
grid: 'grid',
lineGroup: 'line-group',
line: 'line',
tickGroup: 'tick-group',
tick: 'tick',
tickItem: 'tick-item',
labelGroup: 'label-group',
label: 'label',
labelItem: 'label-item',
titleGroup: 'title-group',
title: 'title',
lineFirst: 'line-first',
lineSecond: 'line-second',
mainGroup: CLASSNAME_SUFFIX_MAP.mainGroup,
gridGroup: CLASSNAME_SUFFIX_MAP.gridGroup,
grid: CLASSNAME_SUFFIX_MAP.grid,
lineGroup: CLASSNAME_SUFFIX_MAP.lineGroup,
line: CLASSNAME_SUFFIX_MAP.line,
tickGroup: CLASSNAME_SUFFIX_MAP.tickGroup,
tick: CLASSNAME_SUFFIX_MAP.tick,
tickItem: CLASSNAME_SUFFIX_MAP.tickItem,
labelGroup: CLASSNAME_SUFFIX_MAP.labelGroup,
label: CLASSNAME_SUFFIX_MAP.label,
labelItem: CLASSNAME_SUFFIX_MAP.labelItem,
titleGroup: CLASSNAME_SUFFIX_MAP.titleGroup,
title: CLASSNAME_SUFFIX_MAP.title,
lineFirst: CLASSNAME_SUFFIX_MAP.lineFirst,
lineSecond: CLASSNAME_SUFFIX_MAP.lineSecond,
},
'axis'
);
9 changes: 8 additions & 1 deletion src/ui/axis/guides/grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { CLASS_NAMES } from '../constant';
import type { AxisDatum, AxisGridStyleProps, AxisStyleProps } from '../types';
import { getValuePos } from './line';
import { filterExec, getDirectionVector } from './utils';
import { applyClassName } from '../utils/classname';
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';

function getGridVector(value: number, attr: Required<AxisStyleProps>) {
return getDirectionVector(value, attr.gridDirection, attr);
Expand Down Expand Up @@ -63,6 +65,7 @@ export function renderGrid(
attr: Required<AxisStyleProps>,
animate: StandardAnimationOption
) {
const { classNamePrefix } = attr;
const gridAttr = subStyleProps<Required<AxisGridStyleProps>>(attr, 'grid');
const { type, areaFill } = gridAttr;
const center = getGridCenter(attr);
Expand All @@ -83,7 +86,11 @@ export function renderGrid(
.selectAll(CLASS_NAMES.grid.class)
.data([1])
.join(
(enter) => enter.append(() => new Grid({ style })).attr('className', CLASS_NAMES.grid.name),
(enter) => {
const grid = enter.append(() => new Grid({ style })).attr('className', CLASS_NAMES.grid.name);
applyClassName(grid, CLASS_NAMES.grid, CLASSNAME_SUFFIX_MAP.grid, classNamePrefix);
return grid;
},
(update) =>
update.transition(function () {
return this.update(style);
Expand Down
22 changes: 16 additions & 6 deletions src/ui/axis/guides/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import type { AxisDatum, AxisLabelStyleProps, AxisStyleProps } from '../types';
import { getFactor } from '../utils';
import { getValuePos } from './line';
import { filterExec, getCallbackStyle, getLabelVector, getLineTangentVector } from './utils';
import { applyClassName } from '../utils/classname';
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';

function angleNormalizer(angle: number) {
let normalizedAngle = angle;
Expand Down Expand Up @@ -198,7 +200,9 @@ function overlapHandler(attr: Required<AxisStyleProps>, main: DisplayObject) {
wrap: (label, width, lines) => {
label && wrapIt(label, width, lines);
},
getTextShape: (label) => label.querySelector<DisplayObject>('text') as Text,
getTextShape: (label) => {
return label.querySelector<DisplayObject>(CLASS_NAMES.labelItem.class) as Text;
},
});
}

Expand All @@ -210,11 +214,13 @@ function renderLabel(
attr: Required<AxisStyleProps>
): DisplayObject {
const index = data.indexOf(datum);
const { labelRender } = attr;
const { labelRender, classNamePrefix } = attr;

const label = select(container)
.append(labelRender ? renderHTMLLabel(datum, index, data, attr) : formatter(datum, index, data, attr))
.attr('className', CLASS_NAMES.labelItem.name)
.node();
applyClassName(select(label), CLASS_NAMES.labelItem, CLASSNAME_SUFFIX_MAP.labelItem, classNamePrefix);
const [labelStyle, { transform, ...groupStyle }] = splitStyle(getCallbackStyle(style, [datum, index, data]));

percentTransform(label, transform);
Expand All @@ -238,24 +244,28 @@ export function renderLabels(
animate: StandardAnimationOption,
main: DisplayObject
) {
const { classNamePrefix } = attr;
const finalData = filterExec(data, attr.labelFilter);
const style = subStyleProps<AxisLabelStyleProps>(attr, 'label');

let _exit!: Selection<AxisDatum>;
const transitions = container
.selectAll(CLASS_NAMES.label.class)
.data(finalData, (d, i) => i)
.join(
(enter) =>
enter
(enter) => {
const labels = enter
.append('g')
.attr('className', CLASS_NAMES.label.name)
.transition(function (datum) {
renderLabel(this, datum, data, style, attr);
const { x, y } = getLabelPos(datum, data, attr);
// .axis-label
this.style.transform = `translate(${x}, ${y})`;
return null;
}),
});
applyClassName(labels, CLASS_NAMES.label, CLASSNAME_SUFFIX_MAP.label, classNamePrefix);
return labels;
},
(update) =>
update.transition(function (datum) {
const prevLabel = this.querySelector(CLASS_NAMES.labelItem.class);
Expand Down
62 changes: 50 additions & 12 deletions src/ui/axis/guides/line.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
import { CLASS_NAMES } from '../constant';
import type { RequiredArcAxisStyleProps, RequiredAxisStyleProps, RequiredLinearAxisStyleProps } from '../types';
import { getLineAngle, getLineTangentVector } from './utils';
import { applyClassName, getAxisClassName } from '../utils/classname';
import { CLASSNAME_SUFFIX_MAP } from '../classname-map';

type LineDatum = {
line: [Vector2, Vector2];
Expand Down Expand Up @@ -97,18 +99,21 @@ function renderArc(
style: RequiredArcAxisStyleProps,
animate: StandardAnimationOption
) {
const { startAngle, endAngle, center, radius } = attr;
const { startAngle, endAngle, center, radius, classNamePrefix } = attr;

return container
.selectAll(CLASS_NAMES.line.class)
.data([{ d: getArcPath(startAngle, endAngle, ...center, radius) }], (d, i) => i)
.join(
(enter) =>
enter
(enter) => {
const line = enter
.append('path')
.attr('className', CLASS_NAMES.line.name)
.styles(attr)
.styles({ d: (d: any) => d.d }),
.styles({ d: (d: any) => d.d });
applyClassName(line, CLASS_NAMES.line, CLASSNAME_SUFFIX_MAP.line, classNamePrefix);
return line;
},
(update) =>
update
.transition(function () {
Expand Down Expand Up @@ -158,22 +163,51 @@ function renderLinear(
style: RequiredLinearAxisStyleProps,
animate: StandardAnimationOption
) {
const { showTrunc, startPos, endPos, truncRange, lineExtension } = attr;
const { showTrunc, startPos, endPos, truncRange, lineExtension, classNamePrefix } = attr;
const [[x1, y1], [x2, y2]] = [startPos, endPos];
const [ox1, oy1, ox2, oy2] = lineExtension ? extendLine(startPos, endPos, lineExtension) : new Array(4).fill(0);
const renderLine = (data: LineDatum[]) => {
return container
.selectAll(CLASS_NAMES.line.class)
.data(data, (d, i) => i)
.join(
(enter) =>
enter
(enter) => {
const lines = enter
.append('line')
.attr('className', (d: LineDatum) => `${CLASS_NAMES.line.name} ${d.className}`)
.styles(style)
.transition(function (d: LineDatum) {
return transition(this, getLinePath(d.line), false);
}),
});
// Set className with appropriate logic for line elements
lines.attr('className', (d: LineDatum) => {
if (!classNamePrefix) {
return `${CLASS_NAMES.line.name} ${d.className}`;
}
const baseLineClassName = getAxisClassName(
CLASS_NAMES.line.name,
CLASSNAME_SUFFIX_MAP.line,
classNamePrefix
);
if (d.className === CLASS_NAMES.lineFirst.name) {
const specificClassName = getAxisClassName(
CLASS_NAMES.lineFirst.name,
CLASSNAME_SUFFIX_MAP.lineFirst,
classNamePrefix
);
return `${baseLineClassName} ${specificClassName}`;
}
if (d.className === CLASS_NAMES.lineSecond.name) {
const specificClassName = getAxisClassName(
CLASS_NAMES.lineSecond.name,
CLASSNAME_SUFFIX_MAP.lineSecond,
classNamePrefix
);
return `${baseLineClassName} ${specificClassName}`;
}
return baseLineClassName;
});
return lines;
},
(update) =>
update.styles(style).transition(function ({ line }: LineDatum) {
return transition(this, getLinePath(line), animate.update);
Expand Down Expand Up @@ -228,9 +262,13 @@ function renderAxisArrow(
const { showArrow, showTrunc, lineArrow, lineArrowOffset, lineArrowSize } = attr;

let shapeToAddArrow: Selection;
if (type === 'arc') shapeToAddArrow = container.select(CLASS_NAMES.line.class);
else if (showTrunc) shapeToAddArrow = container.select(CLASS_NAMES.lineSecond.class);
else shapeToAddArrow = container.select(CLASS_NAMES.line.class);
if (type === 'arc') {
shapeToAddArrow = container.select(CLASS_NAMES.line.class);
} else if (showTrunc) {
shapeToAddArrow = container.select(CLASS_NAMES.lineSecond.class);
} else {
shapeToAddArrow = container.select(CLASS_NAMES.line.class);
}
if (!showArrow || !lineArrow || (attr.type === 'arc' && isCircle(attr.startAngle, attr.endAngle))) {
const node = shapeToAddArrow.node<Line>();
if (node) node.style.markerEnd = undefined;
Expand Down
Loading
Loading