diff --git a/__tests__/integration/snapshots/static/alphabetIntervalAxisOptions.png b/__tests__/integration/snapshots/static/alphabetIntervalAxisOptions.png new file mode 100644 index 0000000000..d91e774047 Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalAxisOptions.png differ diff --git a/__tests__/integration/snapshots/static/profitIntervalAxisTransform.png b/__tests__/integration/snapshots/static/profitIntervalAxisTransform.png new file mode 100644 index 0000000000..55bee3e4c6 Binary files /dev/null and b/__tests__/integration/snapshots/static/profitIntervalAxisTransform.png differ diff --git a/__tests__/plots/static/alphabet-interval-axis-options.ts b/__tests__/plots/static/alphabet-interval-axis-options.ts new file mode 100644 index 0000000000..90ff255904 --- /dev/null +++ b/__tests__/plots/static/alphabet-interval-axis-options.ts @@ -0,0 +1,50 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalAxisOptions(): G2Spec { + return { + type: 'interval', + data: { + type: 'fetch', + value: 'data/alphabet.csv', + }, + encode: { + x: 'letter', + y: 'frequency', + }, + axis: { + y: { + // Title + title: 'Frequency', + titleSpacing: 30, + titleFill: 'steelblue', + + // Line + line: true, + arrow: true, + lineExtension: [-30, -40], + lineArrowOffset: 30, + lineArrowSize: 20, + lineLineWidth: 10, + + // Tick + tickLength: 20, + tickFilter: (_, i) => i % 3 !== 0, + + // Label + labelFormatter: '.0%', + + // Grid + gridLineDash: null, + gridStroke: 'red', + gridStrokeWidth: 5, + gridAreaFill: '#eee', + }, + x: { + title: 'Letter', + labelFormatter: (d) => d.repeat(3), + labelFontSize: 30, + labelSpacing: 30, + }, + }, + }; +} diff --git a/__tests__/plots/static/index.ts b/__tests__/plots/static/index.ts index 251c6151f0..ef14049358 100644 --- a/__tests__/plots/static/index.ts +++ b/__tests__/plots/static/index.ts @@ -281,3 +281,5 @@ export { alphabetIntervalTitleAuto } from './alphabet-interval-title-auto'; export { alphabetIntervalAutoPaddingLabelHide } from './alphabet-interval-auto-padding-label-hide'; export { settleWeatherCellLineXY } from './seattle-weather-cell-lineXY'; export { alphabetIntervalFunnelConnectorLabel } from './alphabet-interval-funnel-connector-label'; +export { alphabetIntervalAxisOptions } from './alphabet-interval-axis-options'; +export { profitIntervalAxisTransform } from './profit-interval-axis-transform'; diff --git a/__tests__/plots/static/profit-interval-axis-transform.ts b/__tests__/plots/static/profit-interval-axis-transform.ts new file mode 100644 index 0000000000..5e3907313c --- /dev/null +++ b/__tests__/plots/static/profit-interval-axis-transform.ts @@ -0,0 +1,48 @@ +import { G2Spec } from '../../../src'; + +export function profitIntervalAxisTransform(): G2Spec { + return { + type: 'interval', + data: [ + { month: 'JJan.Jan.an.', profit: 387264, start: 0, end: 387264 }, + { month: 'Feb.', profit: 772096, start: 387264, end: 1159360 }, + { month: 'MJan.Jan.ar.', profit: 638075, start: 1159360, end: 1797435 }, + { month: 'AJan.Jan.pr.', profit: -211386, start: 1797435, end: 1586049 }, + { month: 'May', profit: -138135, start: 1586049, end: 1447914 }, + { month: 'JJan.Jan.un', profit: -267238, start: 1447914, end: 1180676 }, + { month: 'Jul.', profit: 431406, start: 1180676, end: 1612082 }, + { month: 'Aug.', profit: 363018, start: 1612082, end: 1975100 }, + { month: 'Sep.', profit: -224638, start: 1975100, end: 1750462 }, + { + month: 'OcJan.Jan.Jan.t.', + profit: -299867, + start: 1750462, + end: 1450595, + }, + { + month: 'NJan.Jan.Jan.ov.', + profit: 607365, + start: 1450595, + end: 2057960, + }, + { month: 'Dec.', profit: 1106986, start: 2057960, end: 3164946 }, + { month: 'ToJan.Jan.tal', start: 0, end: 3164946 }, + ], + encode: { + x: 'month', + y: ['end', 'start'], + color: (d) => + d.month === 'Total' ? 'Total' : d.profit > 0 ? 'Increase' : 'Decrease', + }, + axis: { + x: { + labelAutoRotate: { + optionalAngles: [60], + recoverWhenFailed: false, + }, + size: 120, + }, + y: { labelFormatter: '~s' }, + }, + }; +} diff --git a/site/docs/spec/component/axis.zh.md b/site/docs/spec/component/axis.zh.md index 1f0549ec40..c9df264678 100644 --- a/site/docs/spec/component/axis.zh.md +++ b/site/docs/spec/component/axis.zh.md @@ -3,123 +3,169 @@ title: axis order: 1 --- -## 开始使用 +绘制坐标轴,目前支持直角坐标系坐标轴与极坐标系坐标轴。 + +```js +// View Level +const viewLevel = { + type: 'view', + axis: { + x: {}, + y: {}, + }, +}; + +// Mark Level +const markLevel = { + type: 'interval', + axis: { + x: {}, + y: {}, + }, +}; +``` -G2 会根据当前绘制的视图类型自动选择合适的坐标轴,目前支持直角坐标系坐标轴与极坐标系坐标轴。 +```js +// API -axis -
-axis +chart.axis('x', {}).axis('y', {}); -```ts -import { Chart } from '@antv/g2'; - -const chart = new Chart({ - container: 'container', -}); - -chart - .interval() - .data({ - type: 'fetch', - value: - 'https://gw.alipayobjects.com/os/bmw-prod/87b2ff47-2a33-4509-869c-dae4cdd81163.csv', - format: 'csv', - }) - .transform({ type: 'groupX', y: 'sum' }) - .encode('x', 'age') - .encode('y', 'people') - .encode('color', 'sex') - .scale('color', { type: 'ordinal', range: ['#ca8861', '#675193'] }) - .axis('x', { - animate: { duration: 500 }, - labelAutoHide: true, - labelDirection: 'positive', - labelFilter: (datum, index, data) => index % 5 === 0, - grid: true, - style: { - lineLineWidth: 5, - lineStroke: '#675193', - labelAlign: 'parallel', - labelSpacing: 10, +chart.interval().axis('x', {}).axis('y', {}); +``` + +## 开始使用 + +```js | ob +(() => { + const chart = new G2.Chart(); + + chart.options({ + type: 'interval', + marginTop: 40, + data: { + type: 'fetch', + value: + 'https://gw.alipayobjects.com/os/bmw-prod/fb9db6b7-23a5-4c23-bbef-c54a55fee580.csv', + }, + encode: { + x: 'letter', + y: 'frequency', + }, + axis: { + y: { + // Title + title: 'Frequency', + titleSpacing: 30, + titleFill: 'steelblue', + + // Line + line: true, + arrow: true, + lineArrowOffset: 10, + lineArrowSize: 30, + lineLineWidth: 10, + + // Tick + tickLength: 20, + tickFilter: (_, i) => i % 3 !== 0, + + // Label + labelFormatter: '.0%', + + // Grid + gridLineDash: null, + gridStroke: 'red', + gridStrokeWidth: 5, + gridAreaFill: '#eee', + }, + x: { + title: 'Letter', + labelFormatter: (d) => d.repeat(3), + labelFontSize: 30, + labelSpacing: 30, + }, }, }); -chart.render(); + chart.render(); + + return chart.getContainer(); +})(); ``` ## 选项 ### 标题 -| 属性 | 描述 | 类型 | 默认值 | -| -------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------ | ------ | -| title | 关闭标题或设置标题内容 | `false`|`string` | `number` | `DisplayObject` | - | -| `style.`titleSpacing | 标题到坐标轴的距离 | `number` | 10 | -| `style.`titlePosition | 标题相对坐标轴的位置,支持首字母简写形式,如`'top'`简写为`'t'` | `'top'`|`'bottom'`|`'left'`|`'right'` | `'lb'` | -| `style.`titleFontSize | 标题文字大小 | `number` | - | -| `style.`titleFontFamily | 标题文字字体 | `string` | - | -| `style.`titleFontWeight | 标题字体粗细 | `number` | - | -| `style.`titleStroke | 标题字体颜色 | `string` | - | -| `style.`titleStrokeOpacity | 标题透明度 | `number` | - | +| 属性 | 描述 | 类型 | 默认值 | +| ------------------ | -------------------------------------------------------------- | ------------------------------------------------------------ | ------ | +| title | 关闭标题或设置标题内容 | `false`|`string` | `number` | `DisplayObject` | - | +| titleSpacing | 标题到坐标轴的距离 | `number` | 10 | +| titlePosition | 标题相对坐标轴的位置,支持首字母简写形式,如`'top'`简写为`'t'` | `'top'`|`'bottom'`|`'left'`|`'right'` | `'lb'` | +| titleFontSize | 标题文字大小 | `number` | - | +| titleFontFamily | 标题文字字体 | `string` | - | +| titleFontWeight | 标题字体粗细 | `number` | - | +| titleStroke | 标题字体颜色 | `string` | - | +| titleStrokeOpacity | 标题透明度 | `number` | - | ### 轴线 -| 属性 | 描述 | 类型 | 默认值 | -| ------------------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------ | ------ | -| line | 是否显示轴线 | `boolean` | true | -| arrow | 是否显示箭头 | `boolean` | true | -| `style.`lineExtension | 轴线两侧的延长线 | `[number, number]` | - | -| `style.`lineArrow | 定义轴线箭头形状,默认为箭头形状 | `DisplayObject` | - | -| `style.`lineArrowOffset | 箭头偏移长度 | `number` | 15 | -| `style.`lineArrowSize | 箭头尺寸 | `number` | - | -| `style.`lineLineWidth | 轴线宽度 | `number` | - | -| `style.`lineLineDash | 轴线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | - | -| `style.`lineStroke | 轴线描边色 | `string` | - | -| `style.`lineStrokeOpacity | 轴线描边色透明度 | `number` | - | +| 属性 | 描述 | 类型 | 默认值 | +| ----------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------ | ------ | +| line | 是否显示轴线 | `boolean` | true | +| arrow | 是否显示箭头 | `boolean` | true | +| lineExtension | 轴线两侧的延长线 | `[number, number]` | - | +| lineArrow | 定义轴线箭头形状,默认为箭头形状 | `DisplayObject` | - | +| lineArrowOffset | 箭头偏移长度 | `number` | 15 | +| lineArrowSize | 箭头尺寸 | `number` | - | +| lineLineWidth | 轴线宽度 | `number` | - | +| lineLineDash | 轴线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | - | +| lineStroke | 轴线描边色 | `string` | - | +| lineStrokeOpacity | 轴线描边色透明度 | `number` | - | ### 刻度 -| 属性 | 描述 | 类型 | 默认值 | -| ------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ---------- | -| tick | 是否显示刻度 | `boolean` | true | -| tickFilter | 刻度线过滤 | `(datum, index, data)=>boolean` | - | -| tickFormatter | 刻度线格式化,可用于自定义刻度样式,回调函数中会额外返回该刻度的方向 | `DisplayObject` | `(datum, index, data, Vector)=> DisplayObject` | - | -| `style.`tickDirection | 刻度朝向,为 `positive` 时,位于侧轴方向(即主轴顺时针 90 度方向), 为 `negative` 时,刻度位于侧轴负方向 | `'positive'` | `'negative'` | 'positive' | -| `style.`tickLength | 轴线长度 | `number`|`(datum, index, data)=>number` | 15 | -| `style.`tickLineWidth | 刻度线宽度 | `number` | `(datum, index, data, Vector)=>number` | - | -| `style.`tickLineDash | 刻度线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | `(datum, index, data, Vector)=>[number,number]` | - | -| `style.`tickStroke | 刻度线颜色 | `string` | `(datum, index, data, Vector)=>string` | - | -| `style.`tickStrokeOpacity | 刻度线透明度 | `number` | `(datum, index, data, Vector)=>number` | - | +| 属性 | 描述 | 类型 | 默认值 | +| ----------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ---------- | +| tick | 是否显示刻度 | `boolean` | true | +| tickFilter | 刻度线过滤 | `(datum, index, data)=>boolean` | - | +| tickFormatter | 刻度线格式化,可用于自定义刻度样式,回调函数中会额外返回该刻度的方向 | `DisplayObject` | `(datum, index, data, Vector)=> DisplayObject` | - | +| tickDirection | 刻度朝向,为 `positive` 时,位于侧轴方向(即主轴顺时针 90 度方向), 为 `negative` 时,刻度位于侧轴负方向 | `'positive'` | `'negative'` | 'positive' | +| tickLength | 轴线长度 | `number`|`(datum, index, data)=>number` | 15 | +| tickLineWidth | 刻度线宽度 | `number` | `(datum, index, data, Vector)=>number` | - | +| tickLineDash | 刻度线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | `(datum, index, data, Vector)=>[number,number]` | - | +| tickStroke | 刻度线颜色 | `string` | `(datum, index, data, Vector)=>string` | - | +| tickStrokeOpacity | 刻度线透明度 | `number` | `(datum, index, data, Vector)=>number` | - | ### 刻度值 -| 属性 | 描述 | 类型 | 默认值 | -| -------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------- | -| label | 是否显示刻度值 | `boolean` | - | -| labelFilter | 刻度值过滤 | `(datum, index, data)=> boolean` | - | -| labelFormatter | 刻度值线格式化 | `DisplayObject` | `(datum, index, data, Vector)=> DisplayObject` | - | -| transform | 刻度值转换,避免文本之间发生重叠。当前支持超长文本缩略、重叠刻度值隐藏、自动旋转 | `boolean` | - | -| labelAutoHide | 自动隐藏重叠的刻度值 | `number` | `(datum, index, data)=>number` | - | -| labelAutoRotate | 自动旋转刻度值 | `boolean` | - | -| labelAutoEllipsis | 自动缩略刻度值 | `boolean` | - | -| labelAutoWrap | 自动换行刻度值 | `boolean` | - | -| `style.`labelAlign | 刻度值对齐方式
- 'horizontal' 始终保持水平
- 'parallel' 平行于坐标轴
- 'perpendicular' 垂直于坐标轴 | `'horizontal'` | `'parallel'` | `'perpendicular'` | 'parallel' | -| `style.`labelDirection | 刻度值位于轴线的位置,参考`tickDirection` | `'positive'` | `'negative'` | 'positive' | -| `style.`labelSpacing | 刻度值到其对应刻度的间距 | `number` | 0 | -| `style.`labelLineWidth | 刻度值宽度 | `number` |`(datum, index, data)=>number` | - | -| `style.`labelLineDash | 刻度值描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | `(datum, index, data)=>[number, number]` | - | -| `style.`labelFontSize | 刻度值文字大小 | `number` | `(datum, index, data)=>number` | - | -| `style.`labelFontFamily | 刻度值文字字体 | `string` | `(datum, index, data)=>string` | - | -| `style.`labelFontWeight | 刻度值字体粗细 | `number` |`(datum, index, data)=>number` | - | -| `style.`labelStroke | 刻度值字体颜色 | `string` | `(datum, index, data)=>string` | - | -| `style.`labelStrokeOpacity | 刻度值文本透明度 | `number` | `(datum, index, data)=>number` | - | +| 属性 | 描述 | 类型 | 默认值 | +| ------------------ | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ---------- | +| label | 是否显示刻度值 | `boolean` | - | +| labelFilter | 刻度值过滤 | `(datum, index, data)=> boolean` | - | +| labelFormatter | 刻度值线格式化 | `DisplayObject` | `(datum, index, data, Vector)=> DisplayObject` | - | +| transform | 刻度值转换,避免文本之间发生重叠。当前支持超长文本缩略、重叠刻度值隐藏、自动旋转 | `Transform[]` | - | +| labelAutoHide | 自动隐藏重叠的刻度值,设置 size 值的时候生效 | `boolean` | `HideOverlapCfg` | - | +| labelAutoRotate | 自动旋转刻度,设置 size 值的时候生效值 | `boolean` | `RotateOverlapCfg` | - | +| labelAutoEllipsis | 自动缩略刻度值,设置 size 值的时候生效 | `boolean` | `EllipsisOverlapCfg` | - | +| labelAutoWrap | 自动换行刻度值,设置 size 值的时候是生效 | `boolean` | `WrapOverlapCfg` | - | +| labelAlign | 刻度值对齐方式
- 'horizontal' 始终保持水平
- 'parallel' 平行于坐标轴
- 'perpendicular' 垂直于坐标轴 | `'horizontal'` | `'parallel'` | `'perpendicular'` | 'parallel' | +| labelDirection | 刻度值位于轴线的位置,参考`tickDirection` | `'positive'` | `'negative'` | 'positive' | +| labelSpacing | 刻度值到其对应刻度的间距 | `number` | 0 | +| labelLineWidth | 刻度值宽度 | `number` |`(datum, index, data)=>number` | - | +| labelLineDash | 刻度值描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | `(datum, index, data)=>[number, number]` | - | +| labelFontSize | 刻度值文字大小 | `number` | `(datum, index, data)=>number` | - | +| labelFontFamily | 刻度值文字字体 | `string` | `(datum, index, data)=>string` | - | +| labelFontWeight | 刻度值字体粗细 | `number` |`(datum, index, data)=>number` | - | +| labelStroke | 刻度值字体颜色 | `string` | `(datum, index, data)=>string` | - | +| labelStrokeOpacity | 刻度值文本透明度 | `number` | `(datum, index, data)=>number` | - | ```ts export interface Transform { /** 避免刻度值重叠时的额外边距 */ margin?: number[]; } + export interface EllipsisOverlapCfg extends Transform { type: 'ellipsis'; /** 缩略替换字符,默认为 ... */ @@ -131,6 +177,7 @@ export interface EllipsisOverlapCfg extends Transform { /** 每次缩略执行步长 */ step?: string | number; } + export interface RotateOverlapCfg extends Transform { type: 'rotate'; /** 可选的旋转角度值 */ @@ -138,6 +185,7 @@ export interface RotateOverlapCfg extends Transform { /** 当旋转无法避免重叠时,是否恢复为默认旋转角度 */ recoverWhenFailed?: boolean; } + export interface HideOverlapCfg extends Transform { type: 'hide'; /** 保证第一个刻度值不被隐藏 */ @@ -145,6 +193,7 @@ export interface HideOverlapCfg extends Transform { /** 保证最后一个刻度值不被隐藏 */ keepTail?: boolean; } + export interface WrapOverlapCfg extends Transform { type: 'wrap'; /** 单行最大宽度 */ @@ -166,16 +215,16 @@ export interface WrapOverlapCfg extends Transform { | `极坐标系` | polar-grid | | `极坐标系` `雷达图` | polygon-grid | -| 属性 | 描述 | 类型 | 默认值 | -| ------------------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------ | -| grid | 是否显示网格线 | `boolean` | false | -| gridFilter | 网格线过滤 | `(datum, index, data)=> boolean` | - | -| `style.`gridLength | 网格线长度。一般情况下,不需要用户配置。 | `number` | `(datum, index, data)=> number` | 0 | -| `style.`gridAreaFill | 网格线区域颜色 | `string` | `string[]`| `(datum, index, data)=> string` | - | -| `style.`gridLineWidth | 网格线宽度 | `number` | - | -| `style.`gridLineDash | 网格线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | - | -| `style.`gridStroke | 网格线颜色 | `string` | - | -| `style.`gridStrokeOpacity | 网格线透明度 | `number` | - | +| 属性 | 描述 | 类型 | 默认值 | +| ----------------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------ | +| grid | 是否显示网格线 | `boolean` | false | +| gridFilter | 网格线过滤 | `(datum, index, data)=> boolean` | - | +| gridLength | 网格线长度。一般情况下,不需要用户配置。 | `number` | `(datum, index, data)=> number` | 0 | +| gridAreaFill | 网格线区域颜色 | `string` | `string[]`| `(datum, index, data)=> string` | - | +| gridLineWidth | 网格线宽度 | `number` | - | +| gridLineDash | 网格线描边的虚线配置,第一个值为虚线每个分段的长度,第二个值为分段间隔的距离。lineDash 设为[0, 0]的效果为没有描边。 | `[number,number]` | - | +| gridStroke | 网格线颜色 | `string` | - | +| gridStrokeOpacity | 网格线透明度 | `number` | - | ### 动画 diff --git a/src/component/axis.ts b/src/component/axis.ts index aa70fc9c91..d87d58aa55 100644 --- a/src/component/axis.ts +++ b/src/component/axis.ts @@ -241,7 +241,7 @@ function inferLabelOverlap(transform = [], style: Record) { const addToTransforms = (overlap, state) => { if (state) { - finalTransforms.push(overlap); + finalTransforms.push({ ...overlap, ...state }); } }; diff --git a/src/theme/light.ts b/src/theme/light.ts index b8ad0bfc7d..1962eb5b8b 100644 --- a/src/theme/light.ts +++ b/src/theme/light.ts @@ -278,6 +278,7 @@ export const Light: TC = (options) => { labelDirection: 'negative', tickDirection: 'negative', titlePosition: 'top', + labelAutoRotate: false, titleSpacing: 12, labelSpacing: 4, titleTextBaseline: 'middle', @@ -285,7 +286,7 @@ export const Light: TC = (options) => { axisBottom: { gridDirection: 'negative', labelDirection: 'positive', - labelAutoRotate: true, + labelAutoRotate: false, tickDirection: 'positive', titlePosition: 'bottom', titleSpacing: 12,