图形组件
图表通常包含以下组件
- 几何图形:决定生成图表的类型
- 坐标轴:衡量数据的基准,包括直角坐标系和极坐标系
- 图例:用于标定不同数据类型或范围,辅助图表阅读
- 提示信息:鼠标悬停时展示详细信息
- 辅助标记:用于标记特定数据范围
- 缩略轴:用于集中展示部分区域数据
- 滚动条
TODO: 顺序调整:几何图形、坐标轴、提示信息、辅助标记、提示信息、图例、缩略轴、滚动条 (由信息呈现 -> 交互)
以下示例部分省略了 Chart 的创建
import { Chart } from "@antv/g2";
const chart = new Chart({
container: "chart",
width: 800,
height: 300,
});坐标轴
chart.coordinate 和 chart.scale 用于配置数据到位置的映射方式 chart.axis 则用来配置坐标轴的展示方式,由 标题、轴线、刻度线、刻度文本、网格线 组成
配置概览
interface AxisConfig {
top?: boolean; // 是否渲染在画布顶层
position?: "top" | "bottom" | "right" | "left"; // 设置坐标轴的位置(直角坐标系)
line?: { style?: ShapeAttrs } | null; // 坐标轴线样式
tickLine?: AxisTickLineCfg | null; // 坐标轴刻度线配置
subTickLine?: AxisSubTickLineCfg | null; // 坐标轴子刻度线配置
title?: AxisTitleCfg | null; // 标题配置
label?: AxisLabelCfg | null; // 刻度文本标签
grid?: AxisGridCfg | null; // 网格线配置
animate?: boolean; // 是否开启动画
animateOption?: ComponentAnimateOption; // 动画配置
verticalFactor?: number; // 坐标轴 label 方向,左侧为 1,右侧为 -1
verticalLimitLength?: number; // 坐标轴垂直方向最大长度,支持像素或百分比(小于1);默认 x 轴 1/2, y 轴 1/3
}
class View extends Base {
axis(show: boolean): View; // 是否展示
axis(filed: AxisConfig): View;
}配置示例
TODO:
const data = [
{ x: 1, y: 4.6 },
{ x: 2, y: 1.2 },
{ x: 3, y: 2.2 },
];
chart.axis("x", {
title: { text: "X 轴" },
label: { rotate: Math.PI / 2 },
grid: {
line: { style: { stroke: "red", strokeOpacity: 0.2 } },
alternateColor: "black",
closed: false,
},
});
chart.line().position("x*y");
chart.data(data);
chart.render();图例
图例是图表的辅助元素,用于增加图表可读性,提供数据筛选等功能
根据数据的类型,分为 分类图例(分类项离散)和连续图例(分类项连续)
分类图例由几何标记和描述组成,连续图例类似坐标轴,内容由 scale 控制
图例会根据图表属性映射自动对 shape, color, size 进行映射
图例支持整体配置和针对某一数据字段进行单独配置
配置概览
interface LegendCfg {
readonly custom?: boolean; // 是否为自定义图例,当该属性为 true 时,需要声明 items 属性。
layout?: "horizontal" | "vertical"; // 布局方式
title?: G2LegendTitleCfg; // 图例标题配置,默认不展示
background?: LegendBackgroundCfg; // 背景框配置项。
position?: Position; // 图例的位置。
animate?: boolean; // 动画开关,默认关闭。
animateOption?: ComponentAnimateOption; // 动画参数配置,`animate` 属性为 true 时生效
itemSpacing?: number; // **分类图例适用**,控制图例项水平方向的间距。
itemMarginBottom?: number; // **分类图例适用**,控制图例项垂直方向的间距。
maxItemWidth?: number; // *分类图例适用**,图例项的最大宽度,超出则自动缩略。可以是像素值或百分比(小于1)
itemWidth?: number; // **分类图例适用**,图例项的宽度, 默认为 null,自动计算。
itemHeight?: number; // **分类图例适用**,图例的高度,默认为 null。
itemName?: LegendItemNameCfg; // **分类图例适用**,图例项 name 文本的配置。
itemValue?: LegendItemValueCfg; // **分类图例适用**,图例项 value 附加值的配置项。
maxWidth?: number; // **分类图例适用**,图例项最大宽度设置。
maxHeight?: number; // **分类图例适用**,图例项最大高度设置。
marker?: MarkerCfg; // **分类图例适用**,图例项的 marker 图标的配置。
flipPage?: boolean; // **适用于分类图例**,当图例项过多时是否进行分页。
items?: LegendItem[]; // **分类图例适用**,用户自己配置图例项的内容。
reversed?: boolean; // **分类图例适用**,是否将图例项逆序展示。
min?: number; // **连续图例适用**,选择范围的最小值。
max?: number; // **连续图例适用**,选择范围的最大值。
value?: number[]; // **连续图例适用**,选择的值。
track?: ContinueLegendTrackCfg; // **连续图例适用**,选择范围的色块样式配置项。
rail?: ContinueLegendRailCfg; // **连续图例适用**,图例滑轨(背景)的样式配置项。
label?: ContinueLegendLabelCfg; // **连续图例适用**,文本的配置项。
handler?: ContinueLegendHandlerCfg; // **连续图例适用**,滑块的配置项。
slidable?: boolean; // **连续图例适用**,滑块是否可以滑动。
offsetX?: number; // 图例 x 方向的偏移
offsetY?: number; // 图例 y 方向的偏移
padding?: number[]; // 图例在四个方向的偏移量
}配置示例
TODO:
提示信息
提示信息用于展示某点或区域对应的数据以及相关信息等。
提示信息由以下部分组成
crosshairs: tooltip 辅助线,用于定位数据在坐标系中的位置marker: 突出当前数据点的位置tooltip: 展示数据信息的内容框,该部分通过 html 实现
开启关闭,其中 Chart 和 View 控制 tooltip 显示样式, Geometry 控制 tooltip 内容
Chart: 控制整个图表的 tooltip 开关,优先级高于 View 和 GeometryView: 控制当前视图的 tooltip 开关,优先级高于 GeometryGeometry: 控制当前几何标记的 tooltip 开关
配置概览
// Chart & View 下对 tooltip 的配置
interface TooltipCfg {
follow?: boolean; // tooltip 内容框是否跟随鼠标移动,默认 true
enterable?: boolean; // tooltip 是否允许鼠标滑入,默认为 false
showDelay?: number; // tooltip 显示延迟(ms),默认为 16ms,建议在 enterable = true 的时候才设置
showTitle?: boolean; // 是否展示 tooltip 标题
title?: TooltipTitle; // tooltip 的标题内容
position?: "top" | "bottom" | "left" | "right"; // tooltip 相对于数据点的固定展示位置
shared?: boolean; // true 表示合并当前点对应的所有数据并展示,false 表示只展示离当前点最逼近的数据内容。
showCrosshairs?: boolean; // 是否展示 crosshairs
crosshairs?: TooltipCrosshairs; // 配置 tooltip 的 crosshairs,当 `showCrosshairs` 为 true 时生效
showMarkers?: boolean; // 是否渲染 tooltipMarkers
marker?: object; // tooltipMarker 的样式配置
showContent?: boolean | ((datum: Datum) => boolean); // 是否展示 tooltip 内容框
container?: string | HTMLElement; // 自定义 tooltip 的容器
containerTpl?: string; // 用于指定图例容器的模板,自定义模板时必须包含各个 dom 节点的 class
itemTpl?: string; // 每项记录的默认模板,自定义模板时必须包含各个 dom 节点的 class。
domStyles?: TooltipDomStyles; // 传入各个 dom 的样式
offset?: number; // tooltip 偏移量
reversed?: boolean; // 是否将 tooltip items 逆序
showNil?: boolean; // 否显示空值的 tooltip 项目
customItems?: (originalItems: TooltipItem[]) => TooltipItem[]; // 在 tooltip 渲染之前,对最终的 items 进行自定义处理
customContent?: (title: string, data: any[]) => string | HTMLElement; // 支持自定义模板
}// Geometry 下对 tooltip 的配置
interface GeometryTooltipOption {
readonly fields: string[]; // 参与映射的字段。
readonly callback?: (...args: any[]) => LooseObject; // 回调函数。
}
class Geometry extends Base {
tooltip(field: GeometryTooltipOption | boolean): Geometry;
tooltip(field: string, cfg?: (...args: any[]) => LooseObject): Geometry; // field 为参与映射的字段,如 `x*y*z`
}相关事件
// tooltip 显示时触发
chart.on("tooltip:show", ev => {
// x: 当前鼠标的 x 坐标,
// y: 当前鼠标的 y 坐标,
// items: 数组对象,当前 tooltip 显示的每条内容
// title: tooltip 标题
const { items, title, x, y } = ev.data;
});
// tooltip 内容变更时触发
chart.on("tooltip:change", ev => {
// x: 当前鼠标的 x 坐标,
// y: 当前鼠标的 y 坐标,
// items: 数组对象,当前 tooltip 显示的每条内容
// title: tooltip 标题
const { items, title, x, y } = ev.data;
});
// tooltip 消失时触发
chart.on("tooltip:hide", ev => {});配置示例
const data = new Array(20).fill(undefined).map((v, i) => ({
x: 2000 + (i < 10 ? i : i - 10),
y: 100 + parseInt("" + Math.random() * 100),
type: i < 10 ? "a" : "b",
}));
chart
.data(data)
.scale("x", { tickInterval: 1 })
.line()
.position("x*y")
.color("type")
.tooltip("x*y*type", (x: number, y: number, type: "a" | "b") => {
return { type: type, year: x + "年", sale: y + "个" };
});
chart.tooltip({
title: "当前年份",
showCrosshairs: true,
crosshairs: { type: "x" },
shared: true, // 共享分组数据
itemTpl: `<i>{type}在{year}卖了{sale}<br/></i>`,
});
chart.render();文本标签
标签是对当前一组数据进行的内容标注;可以包括数据点、拉线、文本数值等元素
文本标签通过 Geometry.label 进行配置,提供了不同的文本类型和布局风格
文本标签类型
base: 默认,用于直角坐标系下图表interval: 用于interval几何标记下所有图形的标注pie: 用于饼图,带有文本连接线polar: 用于极坐标下文本标注
文本标签布局
overlap: 防遮挡,尝试向四周偏移以展示 labelfixedOverlap: 不改变 label 位置的情况下对重叠的 label 进行调整limitInShape: 剔除 shape 容纳不下的 label
配置概览
配置项除了 类型、布局 外大多与位置和样式相关,通常使用默认值即可
interface LabelCfg {
type?: string; // 用于声明渲染的 label 类型。
offset?: number | string; // 相对数据点的偏移距离, polar 和 theta 坐标系下可使用百分比字符串
offsetX?: number; // label 相对于数据点在 X 方向的偏移距离
offsetY?: number; // label 相对于数据点在 Y 方向的偏移距离
/**
* 展示的文本内容,如果不声明则按照参与映射的第一字段的值进行显示。
* 当 content 为 IGroup 或者 IShape 类型时,请使用相对定位,即 x 和 y 坐标都设为 0,G2 内部会整体做最后的 label 进行定位的。
*/
content?: string | IGroup | IShape | GeometryLabelContentCallback;
style?: LooseObject; // label 文本图形属性样式
autoRotate?: boolean; // label 是否自动旋转,默认为 true
rotate?: number; // 当且仅当 `autoRotate` 为 false 时生效,用于设置文本的旋转角度,**弧度制**
labelHeight?: number; // 标签高度设置,仅当标签类型 type 为 pie 时生效;也可在主题中设置 pieLabels.labelHeight
labelLine?: null | boolean | { style?: object }; // 用于设置文本连接线的样式属性,null 表示不展示。
labelEmit?: boolean; // 只对极坐标下的文本生效,表示文本是否按照角度进行放射状显示,true 表示开启,false 表示关闭
layout?: GeometryLabelLayoutCfg | GeometryLabelLayoutCfg[]; // 文本布局类型
background?: LabelBackground; // label 背景
// 仅当 geometry 为 interval 时生效,指定当前 label 与当前图形的相对位置。
position?:
| IntervalGeometryLabelPosition
| ((d: Datum, mapData: MappingDatum, i: number) => IntervalLabelPosition);
/** 动画配置。 */
animate?: AnimateOption | false | null;
}
type LabelCb = (...args: any[]) => LabelCfg | null | undefined;
type LabelOption = { fields?: string[]; cb?: LabelCb; cfg?: LabelCfg };
class Geometry extends Base {
label(field: LabelOption | false | string): Geometry;
label(field: string, secondParam: LabelCfg | LabelCb): Geometry;
label(field: string, cb: LabelCb, cfg: LabelCfg): Geometry;
}配置示例
const data = new Array(20).fill(undefined).map((v, i) => ({
x: 2000 + (i < 10 ? i : i - 10),
y: 100 + parseInt("" + Math.random() * 100),
type: i < 10 ? "a" : "b",
}));
chart.line().position("x*y").color("type").label("y");
chart.data(data);
chart.render();图形标注
图像标注主要用于在图表上标识额外的注解信息,一个图表可以添加多个图形标注
图表标注类型: chart.annotation().<type>({ ...config })
arc: 辅助弧线,只在极坐标下生效image: 辅助图片line: 辅助线,常用于添加均值线、预期线text: 辅助文本,在指定位置添加额外的文本说明region: 辅助框,对指定区域进行设置regionFilter: 区域着色,对指定区域中的图形元素进行设置dataMarker: 特殊数据点标注,多用于折线图和面积图dataRegion: 特殊数据区间标注,多用于折线图和面积图shape: 自定义图形html: 自定义 DOM
清空图形标注
chart.annotation().clear(): 清空图形标注,但不清空配置,再次调用.render时会重新绘制chart.annotation().clear(true): 清空图形标注,同时清空配置
对于经常进行数据更新需要频繁修改图形标注的情况,其位置信息可以使用回调函数
配置概览
// 不同类型的图形标注大致分为基于点和域两类配置进行扩展
// 具体类型该处省略
type AnnotationPositionCallback = (
xScales: Scale[] | Record<string, Scale>,
yScales: Scale[] | Record<string, Scale>
) => [number | string, number | string];
type AnnotationPosition =
| [number | string, number | string]
| Record<string, number | string>
| AnnotationPositionCallback;
interface AnnotationBaseOption {
readonly top?: boolean; // 指定 annotation 是否绘制在 canvas 最上层,默认为 false
readonly animate?: boolean; // 是否进行动画
readonly animateOption?: ComponentAnimateOption; // 动画参数配置,当 `animate` 为 true 时生效
readonly offsetX?: number; // x 方向的偏移量
readonly offsetY?: number; // y 方向的偏移量
}
interface RegionPositionBaseOption extends AnnotationBaseOption {
readonly start: AnnotationPosition; // 起始位置
readonly end: AnnotationPosition; // 结束位置
readonly style?: ShapeAttrs; // 图形样式属性
}
interface PointPositionBaseOption extends AnnotationBaseOption {
readonly position: AnnotationPosition; // Point 定位位置
}
interface ShapeAnnotationOption extends AnnotationBaseOption {
render: ShapeAnnotationRenderer; // 自定义 Annotation 绘制函数
}应用示例
const data = new Array(20).fill(undefined).map((v, i) => ({
x: 2000 + (i < 10 ? i : i - 10),
y: 100 + parseInt("" + Math.random() * 100),
type: i < 10 ? "a" : "b",
}));
const mean = data.reduce((acc, cur) => (acc += cur.y), 0) / 20;
chart.scale("x", { tickInterval: 1 });
chart.scale("y", { min: 100, max: 200 });
chart.annotation().line({
start: [2000, mean],
end: [2009, mean],
text: { content: `均值${mean}`, style: { fill: "red" }, offsetY: -5 },
style: { stroke: "red", lineDash: [5] },
});
chart.annotation().text({ content: "图形标注文本说明", position: [2000, 105] });
chart.line().position("x*y").color("type");
chart.data(data);
chart.render();滑块(缩略轴)
缩略轴适用于大量数据图表绘制,用于控制部分数据范围的展示
按需引入
import Slider from "@antv/g2/lib/chart/controller/slider";
import { registerComponentController, Chart } from "@antv/g2/lib/core";
registerComponentController("slider", Slider);直接使用
chart.option("slider", {});配置概览
interface SliderCfg {
readonly height?: number;
readonly trendCfg?: TrendCfg; // 滑块背景区域配置
readonly backgroundStyle?: any; // 滑块背景样式
readonly foregroundStyle?: any; // 滑块前景样式
readonly handlerStyle?: any; // 滑块两个操作块样式
readonly textStyle?: any; // 文本样式
readonly minLimit?: number; // 允许滑动位置的最小值
readonly maxLimit?: number; // 允许滑动位置的最大值
readonly start?: number; // 滑块初始化的起始位置
readonly end?: number; // 滑块初始化的结束位置
readonly padding?: number[];
formatter?: (val: any, datum: Datum, idx: number) => any; // 滑块文本格式化函数
}应用示例
const data = new Array(50)
.fill(undefined)
.map((v, i) => ({ x: i * 10, y: parseInt("" + Math.random() * 100) }));
chart.option("slider", {});
chart.coordinate("polar");
chart.line().position("x*y");
chart.data(data);
chart.render();滚动条
与缩略轴类似,通过滑动展示图表的一部分
按需引入
import Scrollbar from "@antv/g2/lib/chart/controller/scrollbar";
import { registerComponentController, Chart } from "@antv/g2/lib/core";
registerComponentController("scrollbar", Scrollbar);直接使用
chart.option("scrollbar", {});配置概览
interface ScrollbarCfg {
type?: "horizontal" | "vertical"; // 滚动条类型,默认 horizontal
width?: number; // 宽度,在 vertical 下生效
height?: number; // 高度,在 horizontal 下生效
padding?: Padding;
/** 对应水平滚动条,为 X 轴每个分类字段的宽度;对于垂直滚动条,为 X 轴每个分类字段的高度 */
categorySize?: number;
animate?: boolean; // 滚动的时候是否开启动画,默认跟随 view 中 animate 配置
/** 主题样式设置, 暂不提供 hover 高亮滑块样式配置 */
style?: {
trackColor?: string; // 滑道颜色
thumbColor?: string; // 滑块颜色
thumbHighlightColor?: string; // 滑块高亮样式,对应主题的 hover.style.thumbColor
lineCap?: string;
};
}应用示例
const data = new Array(50)
.fill(undefined)
.map((v, i) => ({ x: i * 10, y: parseInt("" + Math.random() * 100) }));
chart.option("scrollbar", {});
chart.line().position("x*y");
chart.data(data);
chart.render();