AntV Infographic
Home
Learn
Reference
Gallery
Icon
Editor
AI
Enterprise

目录

  • Overview
  • 基础用法
  • 核心模块
  • JSX 运行时
  • 渲染器
  • 布局
  • Infographic
    • API
    • 配置项
    • 类型定义
    • 导出内容
  • JSX
    • 原语节点
    • 创建布局
    • 工具函数
  • 设计资产
    • 内置结构
    • 内置数据项
    • 内置模版
    • 内置主题
    • 内置色板
    • 内置图案
    • 内置组件
API Reference

JSX

AntV Infographic 提供了一个轻量化的 JSX 渲染引擎,支持通过 JSX 语法描述图形元素,并渲染为 SVG。

基础用法

在编写 AntV Infographic JSX 前,你需要在文件头部引入 /** @jsxImportSource @antv/infographic */ 指令,以启用 JSX 转换功能:

下面的示例中通过 JSX 语法创建了一个包含矩形和文本的简单节点组件 Node,并使用 renderSVG 方法将其渲染为 SVG 字符串。

JSX
/** @jsxImportSource @antv/infographic */ import {renderSVG, Rect, Text, Group} from '@antv/infographic'; const Node = () => ( <Group> <Rect width={100} height={50} fill="blue" /> <Text x={10} y={30} fill="white"> Hello World </Text> </Group> ); const svgString = renderSVG(<Node />); console.log(svgString);

核心模块

JSX 运行时

实现 JSX 转换函数:

TYPESCRIPT
// jsx-runtime.ts export function jsx(type, props, key) { /* ... */ } export function jsxs(type, props, key) { /* ... */ } export function jsxDEV(type, props, key, ...) { /* ... */ } export const Fragment: unique symbol;

功能:

  • jsx():创建单个 JSX 元素
  • jsxs():创建静态 JSX 元素(编译优化)
  • jsxDEV():开发模式(包含更多调试信息)
  • Fragment:片段支持 <>...</>

渲染器

两阶段渲染管线:

1. 处理阶段 (processElement)

将 JSX 元素树转换为可渲染的元素树:

TYPESCRIPT
function processElement( element: JSXElement, context: RenderContext ): ProcessedElement;

主要工作:

  • 展开函数组件(递归调用函数)
  • 处理 Fragment(扁平化子元素)
  • 执行布局计算(调用 layout 函数)
  • 收集边界信息
  • 生成渲染树

示例:

TSX
// 输入 JSX <MyComponent> <Rect width={100} height={50} /> </MyComponent> // 处理后 { type: 'Group', props: { ... }, children: [ { type: 'Rect', props: { width: 100, height: 50 }, children: [] } ] }

2. 渲染阶段 (render)

将处理后的元素树转换为 SVG 字符串:

TYPESCRIPT
function render(element: ProcessedElement, context: RenderContext): string;

主要工作:

  • 根据元素类型生成对应的 SVG 标签
  • 应用属性和样式
  • 递归渲染子元素
  • 自动计算 viewBox
  • 优化输出(去除冗余属性等)

示例:

TSX
// 输入处理后的元素 { type: 'Rect', props: { width: 100, height: 50, fill: 'blue' } } // 输出 SVG <rect width="100" height="50" fill="blue" />

布局

提供 createLayout 函数创建自定义布局组件。

基本原理

布局组件是特殊的函数组件,使用 Symbol 标记:

TYPESCRIPT
const LAYOUT_SYMBOL = Symbol('layout'); export function createLayout<T>(fn: LayoutFunction<T>): LayoutComponent<T> { const component = (props) => fn(props); component[LAYOUT_SYMBOL] = true; return component; }

创建布局

TSX
import {createLayout, getElementBounds} from '@antv/infographic-jsx'; // 创建垂直堆叠布局 const VerticalLayout = createLayout<{gap: number}>(({children, gap = 10}) => { let currentY = 0; return children.map((child) => { const bounds = getElementBounds(child); const positioned = { ...child, props: {...child.props, y: currentY}, }; currentY += bounds.height + gap; return positioned; }); });

使用布局

TSX
<VerticalLayout gap={20}> <Rect width={100} height={50} /> <Rect width={100} height={50} /> <Rect width={100} height={50} /> </VerticalLayout> // 渲染结果:三个矩形垂直排列,间距 20

布局执行流程

  1. 渲染器识别:检测到 layout symbol
  2. 收集 children:获取所有子元素
  3. 调用布局函数:传入 children 和 props
  4. 获取新 children:布局函数返回调整位置后的 children
  5. 继续渲染:渲染新的 children 数组

Note

  • 布局函数可以修改 children 的位置、尺寸等属性
  • 使用 getElementBounds 获取子元素的边界信息
  • 支持嵌套布局
  • 布局是在处理阶段执行的

复杂布局示例

参考 packages/infographic/src/designs/layouts/Align.tsx:

TSX
export const AlignLayout = createLayout<{ horizontal?: 'left' | 'center' | 'right'; vertical?: 'top' | 'center' | 'bottom'; width?: number; height?: number; }>(({children, horizontal, vertical, width, height}) => { const bounds = getElementsBounds(children); const containerWidth = width ?? bounds.width; const containerHeight = height ?? bounds.height; return children.map((child) => { const childBounds = getElementBounds(child); let x = child.props.x ?? 0; let y = child.props.y ?? 0; // 水平对齐 if (horizontal === 'center') { x = (containerWidth - childBounds.width) / 2; } else if (horizontal === 'right') { x = containerWidth - childBounds.width; } // 垂直对齐 if (vertical === 'center') { y = (containerHeight - childBounds.height) / 2; } else if (vertical === 'bottom') { y = containerHeight - childBounds.height; } return {...child, props: {...child.props, x, y}}; }); });
Previous导出内容
Next原语节点

AntV Infographic
Copyright © Ant Group Co.
Docs
Quick Start
Core Concepts
Custom Design
Infographic Theory
API Reference
JSX
API
Design Assets
More
More Examples
AI Generated Infographics
GitHub
Contribute
Friendly Links
AntV
G2
G6
L7
JSX
/** @jsxImportSource @antv/infographic */

import {renderSVG, Rect, Text, Group} from '@antv/infographic';

const Node = () => (
<Group>
<Rect width={100} height={50} fill="blue" />
<Text x={10} y={30} fill="white">
Hello World
</Text>
</Group>
);

const svgString = renderSVG(<Node />);
console.log(svgString);
TYPESCRIPT
// jsx-runtime.ts
export function jsx(type, props, key) { /* ... */ }
export function jsxs(type, props, key) { /* ... */ }
export function jsxDEV(type, props, key, ...) { /* ... */ }
export const Fragment: unique symbol;
TYPESCRIPT
function processElement(
element: JSXElement,
context: RenderContext
): ProcessedElement;
TSX
// 输入 JSX
<MyComponent>
<Rect width={100} height={50} />
</MyComponent>

// 处理后
{
type: 'Group',
props: { ... },
children: [
{ type: 'Rect', props: { width: 100, height: 50 }, children: [] }
]
}
TYPESCRIPT
function render(element: ProcessedElement, context: RenderContext): string;
TSX
// 输入处理后的元素
{ type: 'Rect', props: { width: 100, height: 50, fill: 'blue' } }

// 输出 SVG
<rect width="100" height="50" fill="blue" />
TYPESCRIPT
const LAYOUT_SYMBOL = Symbol('layout');

export function createLayout<T>(fn: LayoutFunction<T>): LayoutComponent<T> {
const component = (props) => fn(props);
component[LAYOUT_SYMBOL] = true;
return component;
}
TSX
import {createLayout, getElementBounds} from '@antv/infographic-jsx';

// 创建垂直堆叠布局
const VerticalLayout = createLayout<{gap: number}>(({children, gap = 10}) => {
let currentY = 0;

return children.map((child) => {
const bounds = getElementBounds(child);
const positioned = {
...child,
props: {...child.props, y: currentY},
};
currentY += bounds.height + gap;
return positioned;
});
});
TSX
<VerticalLayout gap={20}>
<Rect width={100} height={50} />
<Rect width={100} height={50} />
<Rect width={100} height={50} />
</VerticalLayout>

// 渲染结果:三个矩形垂直排列,间距 20
TSX
export const AlignLayout = createLayout<{
horizontal?: 'left' | 'center' | 'right';
vertical?: 'top' | 'center' | 'bottom';
width?: number;
height?: number;
}>(({children, horizontal, vertical, width, height}) => {
const bounds = getElementsBounds(children);
const containerWidth = width ?? bounds.width;
const containerHeight = height ?? bounds.height;

return children.map((child) => {
const childBounds = getElementBounds(child);
let x = child.props.x ?? 0;
let y = child.props.y ?? 0;

// 水平对齐
if (horizontal === 'center') {
x = (containerWidth - childBounds.width) / 2;
} else if (horizontal === 'right') {
x = containerWidth - childBounds.width;
}

// 垂直对齐
if (vertical === 'center') {
y = (containerHeight - childBounds.height) / 2;
} else if (vertical === 'bottom') {
y = containerHeight - childBounds.height;
}

return {...child, props: {...child.props, x, y}};
});
});