diff --git a/__tests__/integration/snapshots/static/alphabetIntervalAxisArrow.png b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrow.png new file mode 100644 index 0000000000..82e3d57e0e Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrow.png differ diff --git a/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowPosition.png b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowPosition.png new file mode 100644 index 0000000000..a0a46ee309 Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowPosition.png differ diff --git a/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowTransposed.png b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowTransposed.png new file mode 100644 index 0000000000..47c2db98da Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalAxisArrowTransposed.png differ diff --git a/__tests__/plots/static/alphabet-interval-axis-arrow-position.ts b/__tests__/plots/static/alphabet-interval-axis-arrow-position.ts new file mode 100644 index 0000000000..725dbb6c07 --- /dev/null +++ b/__tests__/plots/static/alphabet-interval-axis-arrow-position.ts @@ -0,0 +1,21 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalAxisArrowPosition(): G2Spec { + return { + type: 'interval', + transform: [{ type: 'sortX', by: 'y', reverse: true }], + data: { + type: 'fetch', + value: 'data/alphabet.csv', + }, + axis: { + x: { line: true, arrow: true, position: 'top' }, + y: { labelFormatter: '.0%', line: true, arrow: true, position: 'right' }, + }, + encode: { + x: 'letter', + y: 'frequency', + color: 'steelblue', + }, + }; +} diff --git a/__tests__/plots/static/alphabet-interval-axis-arrow-transposed.ts b/__tests__/plots/static/alphabet-interval-axis-arrow-transposed.ts new file mode 100644 index 0000000000..34cd869abc --- /dev/null +++ b/__tests__/plots/static/alphabet-interval-axis-arrow-transposed.ts @@ -0,0 +1,21 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalAxisArrowTransposed(): G2Spec { + return { + type: 'interval', + coordinate: { transform: [{ type: 'transpose' }] }, + data: { + type: 'fetch', + value: 'data/alphabet.csv', + }, + axis: { + x: { line: true, arrow: true }, + y: { labelFormatter: '.0%', line: true, arrow: true }, + }, + encode: { + x: 'letter', + y: 'frequency', + color: 'steelblue', + }, + }; +} diff --git a/__tests__/plots/static/alphabet-interval-axis-arrow.ts b/__tests__/plots/static/alphabet-interval-axis-arrow.ts new file mode 100644 index 0000000000..f1bcdf48b0 --- /dev/null +++ b/__tests__/plots/static/alphabet-interval-axis-arrow.ts @@ -0,0 +1,20 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalAxisArrow(): G2Spec { + return { + type: 'interval', + data: { + type: 'fetch', + value: 'data/alphabet.csv', + }, + axis: { + x: { line: true, arrow: true }, + y: { labelFormatter: '.0%', line: true, arrow: true }, + }, + encode: { + x: 'letter', + y: 'frequency', + color: 'steelblue', + }, + }; +} diff --git a/__tests__/plots/static/index.ts b/__tests__/plots/static/index.ts index 4f782989a5..3bff3a073b 100644 --- a/__tests__/plots/static/index.ts +++ b/__tests__/plots/static/index.ts @@ -248,6 +248,9 @@ export { mockAxisY } from './mock-axisY'; export { mockAxisXY } from './mock-axisXY'; export { mockAxisXYPolar } from './mock-axisXY-polar'; export { alphabetIntervalAxis } from './alphabet-interval-axis'; +export { alphabetIntervalAxisArrow } from './alphabet-interval-axis-arrow'; +export { alphabetIntervalAxisArrowTransposed } from './alphabet-interval-axis-arrow-transposed'; +export { alphabetIntervalAxisArrowPosition } from './alphabet-interval-axis-arrow-position'; export { commitsPointGroupedLegendFlexCenter } from './commits-point-grouped-legend-flex-center'; export { commitsPointGroupedLegendFlexRight } from './commits-point-grouped-legend-flex-right'; export { commitsPointGroupedLegendPositionRight } from './commits-point-grouped-legend-position-right'; diff --git a/src/component/axis.ts b/src/component/axis.ts index 4eca8099ed..72f343b6f2 100644 --- a/src/component/axis.ts +++ b/src/component/axis.ts @@ -2,7 +2,7 @@ import { Coordinate } from '@antv/coord'; import type { DisplayObject } from '@antv/g'; import { Axis as AxisComponent } from '@antv/gui'; import { Linear as LinearScale } from '@antv/scale'; -import { deepMix, has, omit } from '@antv/util'; +import { deepMix, omit } from '@antv/util'; import { extent } from 'd3-array'; import { format } from 'd3-format'; import { @@ -24,6 +24,7 @@ import { radiusOf, } from '../utils/coordinate'; import { capitalizeFirst } from '../utils/helper'; +import { isOrdinalScale } from '../utils/scale'; import { adaptor, isVertical, titleContent } from './utils'; export type AxisOptions = { @@ -157,6 +158,7 @@ function getData( const applyFisheye = createFisheye(position, coordinate); const isHorizontal = (position) => ['top', 'bottom', 'center', 'outer'].includes(position); + const isVertical = (position) => ['left', 'right'].includes(position); // @todo GUI should consider the overlap problem for the first // and label of arc axis. @@ -168,7 +170,9 @@ function getData( (isRadial(coordinate) && position === 'center') || (isTranspose(coordinate) && scale.getTicks?.() && - isHorizontal(position)); + isHorizontal(position)) || + (isTranspose(coordinate) && isVertical(position)); + return { value: shouldReverse ? 1 - tick : tick, label: toString(labelFormatter(prettyNumber(d), i, array)), @@ -180,8 +184,9 @@ function getData( return filteredTicks.map((d, i, array) => { const offset = scale.getBandWidth?.(d) / 2 || 0; const tick = applyFisheye(applyInset(scale.map(d) + offset)); + const shouldReverse = isVertical(position); return { - value: tick, + value: shouldReverse ? 1 - tick : tick, label: toString(labelFormatter(prettyNumber(d), i, array)), id: String(i), }; @@ -291,10 +296,10 @@ function inferAxisLinearOverrideStyle( return { startPos: [x, y], endPos: [x + width, y] }; } if (position === 'left') { - return { startPos: [x + width, y], endPos: [x + width, y + height] }; + return { startPos: [x + width, y + height], endPos: [x + width, y] }; } if (position === 'right') { - return { endPos: [x, y + height], startPos: [x, y] }; + return { startPos: [x, y + height], endPos: [x, y] }; } if (position === 'top') { return { startPos: [x, y + height], endPos: [x + width, y + height] }; diff --git a/src/theme/academy.ts b/src/theme/academy.ts index 93b2295e3a..71d702c4fa 100644 --- a/src/theme/academy.ts +++ b/src/theme/academy.ts @@ -245,10 +245,10 @@ export const Academy: TC = (options) => { titleTextBaseline: 'bottom', }, axisLeft: { - gridDirection: 'negative', - labelDirection: 'positive', + gridDirection: 'positive', + labelDirection: 'negative', labelSpacing: 4, - tickDirection: 'positive', + tickDirection: 'negative', titlePosition: 'left', titleSpacing: 4, titleTextBaseline: 'middle', @@ -256,10 +256,10 @@ export const Academy: TC = (options) => { titleTransformOrigin: 'center', }, axisRight: { - gridDirection: 'positive', - labelDirection: 'negative', + gridDirection: 'negative', + labelDirection: 'positive', labelSpacing: 4, - tickDirection: 'negative', + tickDirection: 'positive', titlePosition: 'right', titleSpacing: 0, titleTextBaseline: 'top', diff --git a/src/theme/classic.ts b/src/theme/classic.ts index 51785f2e29..38cbfc497f 100644 --- a/src/theme/classic.ts +++ b/src/theme/classic.ts @@ -245,11 +245,11 @@ export const Classic: TC = (options) => { titleTextBaseline: 'bottom', }, axisLeft: { - gridDirection: 'negative', + gridDirection: 'positive', labelAutoRotate: false, - labelDirection: 'positive', + labelDirection: 'negative', labelSpacing: 4, - tickDirection: 'positive', + tickDirection: 'negative', titlePosition: 'left', titleSpacing: 10, titleTextBaseline: 'middle', @@ -257,11 +257,10 @@ export const Classic: TC = (options) => { titleTransformOrigin: 'center', }, axisRight: { - gridDirection: 'positive', - labelDirection: 'negative', + gridDirection: 'negative', + labelDirection: 'positive', labelSpacing: 4, - labelAutoRotate: false, - tickDirection: 'negative', + tickDirection: 'positive', titlePosition: 'right', titleSpacing: 0, titleTextBaseline: 'top', diff --git a/src/theme/classicDark.ts b/src/theme/classicDark.ts index edc38262cc..679e1bd939 100644 --- a/src/theme/classicDark.ts +++ b/src/theme/classicDark.ts @@ -244,11 +244,11 @@ export const ClassicDark: TC = (options) => { titleTextBaseline: 'bottom', }, axisLeft: { - gridDirection: 'negative', + gridDirection: 'positive', labelAutoRotate: false, - labelDirection: 'positive', + labelDirection: 'negative', labelSpacing: 4, - tickDirection: 'positive', + tickDirection: 'negative', titlePosition: 'left', titleSpacing: 10, titleTextBaseline: 'middle', @@ -256,10 +256,10 @@ export const ClassicDark: TC = (options) => { titleTransformOrigin: 'center', }, axisRight: { - gridDirection: 'positive', - labelDirection: 'negative', + gridDirection: 'negative', + labelDirection: 'positive', labelSpacing: 4, - tickDirection: 'negative', + tickDirection: 'positive', titlePosition: 'right', titleSpacing: 0, titleTextBaseline: 'top', diff --git a/src/utils/scale.ts b/src/utils/scale.ts index ef0fa34bc8..2e0177edc8 100644 --- a/src/utils/scale.ts +++ b/src/utils/scale.ts @@ -5,7 +5,7 @@ function constrain(x, lo, hi) { } export function isOrdinalScale(scale) { - return scale.getBandWidth; + return !!scale.getBandWidth; } export function invert(scale, x, start) {