character
请先阅读dsl 的定义,然后再阅读本节内容。
Character(角色) 是 VStory 中最基础 的元素,它可以是图表、组件、表格等,它可以只是一个简单的文字,也可以是一个非常复杂的图表。Character 可以通过 DSL 配置,也可以通过 API 动态添加。Character 是需要预定义的,如果你的作品中需要使用某个 Character,你需要在 DSL 的characters数组中定义好这个 Character。
Character 的定义
所有的character都可以由一些通用的配置和一些特殊的配置定义。通用配置包括:
- id:
character的 id,用于唯一标识这个character,后续在定义具体的行为(action)时会用到 - type:
character的类型,目前 VStory 支持的character类型包括但不限于:VChart、Text、Image等 - position:
character的位置和大小,以及旋转锚点等信息 - zIndex:
character的层级,默认为 0,层级高的character会覆盖层级低的character
所有的特殊配置都在 options 里,举例:
const textConfig = { type: 'Text', // 标记是文字类型 id: 'title1', zIndex: 1, position: { top: 100, left: 200 }, // 这里定义文字的配置 options: { graphic: { text: 'A BRIEF HISTORY', fontSize: 12, fill: 'red' } } }; const imageConfig = { type: 'Image', // 标记是图片类型 id: 'image1', zIndex: 1, position: { top: 100, left: 200 }, // 这里定义图片的配置 options: { graphic: { image: 'url' } } };
关于准确的接口定义,如下所示:
type ICharacterConfig = IChartCharacterConfig | IComponentCharacterConfig;
// position的定义,描述元素的位置和大小,以及旋转锚点等信息
type IWidgetData = {
left?: number;
top?: number;
x?: number;
y?: number;
angle?: number;
anchor?: [number, number];
} & (
| {
bottom?: number;
right?: number;
}
| {
width?: number;
height?: number;
}
);
interface ICharacterConfigBase {
id: string;
type: string; // 类型
position: IWidgetData; // 定位描述
zIndex: number;
extra?: any; // 带着的额外信息
options: any; // 特殊的配置,所有不同的Character可以将自己特殊的配置传入在这里
}
内置的 Character 类型
VChart
VChart 是 VStory 中最常用的 Character 类型,它可以是各种类型的图表,比如折线图、柱状图、饼图等。VChart 可以通过直接传入 VChart 的 Spec 来定义,具体的 spec 如何定义,请参考vchart 站点。VChart 的接口定义如下:
interface IChartCharacterConfig extends ICharacterConfigBase { options: { // 图表spec spec?: any; // 初始化参数 initOption?: IInitOption; // 边距 padding?: { left: number; top: number; right: number; bottom: number }; // 图表容器 panel?: any; // 数据源 data?: any; // 标题 title?: { [key in ModelSelector]: Partial<ElementType<ISpec['title']>>; }; // 图例 legends?: { [key in ModelSelector]: Partial<ElementType<ISpec['legends']>>; }; // axes axes?: { [key in ModelSelector]: Partial<ElementType<ISpec['axes']>>; }; // 色板 color?: any; // mark 单元素样式 markStyle?: { [key: string]: IMarkStyle; }; // label 单元素样式 与 mark 区分开,runtime逻辑完全不同 labelStyle?: { [key: string]: IMarkStyle; }; // 组样式配置 dataGroupStyle?: { [StroyAllDataGroup]: IDataGroupStyle; // 全部分组的样式 [key: string]: IDataGroupStyle; // 某一组 }; // 直接合并的配置,使用VChart的spec rootConfig?: Record<string, any>; }; }
我们看一个 VChart 的例子:
VTable
VTable 是 VStory 中表格的 Character 类型,它可以是各种类型的表格。VTable 可以通过直接传入 VTable 的 Spec 来定义,具体的 spec 如何定义,请参考vtable 站点 VTable 的接口定义如下:
interface ITableCharacterConfigOptionsType {
// 表格spec
spec?: any;
records: any;
columns: any;
widthMode?: 'standard' | 'adaptive' | 'autoWidth';
defaultRowHeight: number;
showHeader?: boolean;
theme: any;
// 数据源
data?: any;
panel?: any;
padding?: number | [number, number] | [number, number, number, number];
// 单个单元格样式,框选也会应用到这里
// 使用 map 不用数组的原因。减少写入是的反复遍历
cellStyle?: {
// col_row
[key: string]: {
col: number;
row: number;
style?: any;
};
};
// 列宽
colWidth?: {
[key: number]: number;
};
// 行高
rowHeight?: {
[key: number]: number;
};
// 列样式(包括列头)
colStyle?: {
[key: number]: any;
};
// 行样式(包括行头)
rowStyle?: {
[key: number]: any;
};
// 列隐藏
colVisible?: {
[key: number]: boolean;
};
// 行隐藏
rowVisible?: {
[key: number]: boolean;
};
// 内容列样式
contentColStyle?: {
[key: number]: any;
};
// 内容行样式
contentRowStyle?: {
[key: number]: any;
};
}
export interface ITableCharacterConfig extends ICharacterConfigBase {
options: ITableCharacterConfigOptionsType;
}
我们看一个 VTable 的例子:
基本组件(Image、Line、Rect、Shape、Text、Arc、Polygon)
组件类型的接口定义如下,其中基本组件(Image、Line、Rect、Shape、Text、Arc、Polygon)的配置都直接基于 VRender 的对应图元,配置在 graphic 属性上:
- Image 是基于 VRender 的Image 图元
- Line 是基于 VRender 的Line 图元
- Rect 是基于 VRender 的Rect 图元
- Shape 是基于 VRender 的Symbol 图元
- Text 是基于 VRender 的RichText 图元
- Arc 是基于 VRender 的Arc 图元
- Polygon 是基于 VRender 的Polygon 图元
其中 panel 是组件的额外面板,其实是一个VRender 的 rect图元,可以参考VRender 的 rect图元配置。 text 配置是每个组件都带有的一个额外的配置,是一个VRender 的 text图元,可以参考VRender 的 text图元配置。 padding 表示面板和内容的边距,分别表示上、右、下、左的边距。
interface IComponentCharacterConfig extends ICharacterConfigBase { options: { // 主图元的配置 graphic: any; // 面板配置 panel?: any; // 文字配置 text?: any; // 边距 padding?: { left: number; top: number; right: number; bottom: number }; }; }
使用案例如下:
Timeline 组件
Timeline组件是一个时间轴组件,可以展示一整个时间序列,以及时间的流向,它的接口定义如下:
interface TimelineAttrs extends IGroupGraphicAttribute { width: number; // 宽度 // height?: number; times: { label: string; desc?: string }[]; // 具体的时间序列 labelSpace?: number; // 标签的间距 symbolStyle?: Partial<ISymbolGraphicAttribute>; // 时间点的样式 activeSymbolStyle?: Partial<ISymbolGraphicAttribute>; // 激活的时间点的样式 lineStyle?: Partial<ILineGraphicAttribute>; // 时间线的样式 activeLineStyle?: Partial<ILineGraphicAttribute>; // 激活的时间线的样式 labelStyle?: Partial<ITextGraphicAttribute>; // 标签的样式 activeLabelStyle?: Partial<ITextGraphicAttribute>; // 激活的标签的样式 pointLayoutMode?: 'space-around' | 'space-between'; // 布局模式 // 当前进度 clipRange?: number; animation?: boolean; // 是否开启动画 } interface ITimelineComponentAttributes extends IGroupGraphicAttribute { // 结合富文本textConfig的文本配置 textStyle?: Partial<ITextGraphicAttribute & { textConfig: IRichTextAttribute['textConfig'] }>; graphic?: TimelineAttrs; /** * 内部边距 */ padding?: { top?: number; bottom?: number; left?: number; right?: number; }; }
使用案例如下:
Unit 组件
单元可视化组件,单元可视化是一种将数据转化为视觉元素的叙事方式,能够直观地展示复杂信息。通过将每个数据点个体化,观众能更深入地理解每一个数据背后所代表的真实故事。这种方式利用动画和时间推移,生动地描绘数据变化的过程,同时通过颜色和形状等视觉元素传达多维度的信息,增强了情感共鸣。它不仅提升了数据的可读性,还易于在社交媒体上分享,有助于提高公众对重要社会问题的关注。
Unit组件的接口定义如下
interface IUnitGraphicAttributes extends IGroupAttribute {
/**
* The width of the container.
* Defaults to the width defined by the position of the character.
*/
width: number;
/**
* The height of the container.
* Defaults to the height defined by the position of the character.
*/
height: number;
/**
* The padding inside the container, specifying space between the container border and its content.
* @default { top: 50, bottom: 50, right: 50, left: 50 }
*/
padding?: {
top?: number;
bottom?: number;
right?: number;
left?: number;
};
/**
* The total number of units to be rendered within the container.
* @default 250
*/
count?: number;
/**
* 每个symbol代表多少数量
* @default 1
*/
countPerSymbol?: number;
/**
* The gap between units, represented as a percentage of the unit's width and height.
* The first value specifies the horizontal gap, and the second value specifies the vertical gap.
* @default [0.5, 0.5]
*/
gap?: [number, number];
// 定义了从什么区间到什么区间是什么样式
units: {
style: ISymbolGraphicAttribute;
range: [number, number];
}[];
/**
* The aspect ratio of the units, defined as width divided by height.
* @default 1
*/
aspect?: number;
/**
* The direction in which units are laid out within the container.
* @default 'horizontal'
*/
direction?: 'horizontal' | 'vertical';
duration?: number;
}
使用案例如下: