几何元素
Interval
条形图

// https://g2.antv.vision/zh/examples/column/basic#basicconst data = [{ year: '1951 年', sales: 38 },{ year: '1952 年', sales: 52 },{ year: '1956 年', sales: 61 },{ year: '1957 年', sales: 145 },{ year: '1958 年', sales: 48 },{ year: '1959 年', sales: 38 },{ year: '1960 年', sales: 38 },{ year: '1962 年', sales: 38 },];const options = {type: 'interval',data,encode: {x: 'year',y: 'scales'}};
区间条形图

// https://g2.antv.vision/zh/examples/column/basic#rangedconst data = [{ x: '分类一', y1: 76, y2: 100 },{ x: '分类二', y1: 56, y2: 108 },{ x: '分类三', y1: 38, y2: 129 },{ x: '分类四', y1: 58, y2: 155 },{ x: '分类五', y1: 45, y2: 120 },{ x: '分类六', y1: 23, y2: 99 },{ x: '分类七', y1: 18, y2: 56 },{ x: '分类八', y1: 18, y2: 34 },];const options = {type: 'interval',data,encode: {x: 'x',y: ['y1', 'y2']}}
堆积条形图

// https://g2.antv.vision/zh/examples/column/stack#stackedconst data = [{ name: 'London', 月份: 'Jan.', 月均降雨量: 18.9 },{ name: 'London', 月份: 'Feb.', 月均降雨量: 28.8 },{ name: 'London', 月份: 'Mar.', 月均降雨量: 39.3 },{ name: 'London', 月份: 'Apr.', 月均降雨量: 81.4 },{ name: 'London', 月份: 'May', 月均降雨量: 47 },{ name: 'London', 月份: 'Jun.', 月均降雨量: 20.3 },{ name: 'London', 月份: 'Jul.', 月均降雨量: 24 },{ name: 'London', 月份: 'Aug.', 月均降雨量: 35.6 },{ name: 'Berlin', 月份: 'Jan.', 月均降雨量: 12.4 },{ name: 'Berlin', 月份: 'Feb.', 月均降雨量: 23.2 },{ name: 'Berlin', 月份: 'Mar.', 月均降雨量: 34.5 },{ name: 'Berlin', 月份: 'Apr.', 月均降雨量: 99.7 },{ name: 'Berlin', 月份: 'May', 月均降雨量: 52.6 },{ name: 'Berlin', 月份: 'Jun.', 月均降雨量: 35.5 },{ name: 'Berlin', 月份: 'Jul.', 月均降雨量: 37.4 },{ name: 'Berlin', 月份: 'Aug.', 月均降雨量: 42.4 },];const options = {type: 'interval',data,statistic: [{type: 'stackY'}],encode: {x: '月份',y: '月均降雨量',color: 'name',}}
-  [待定:] 如果没有设置 stackY,是否默认推断。如果默认推断,如何关闭
百分比堆叠柱状图
```javascript
// https://g2.antv.vision/zh/examples/column/stack#stacked-percentage 
const data = [ { country: ‘Europe’, year: ‘1750’, value: 163 }, { country: ‘Europe’, year: ‘1800’, value: 203 }, { country: ‘Europe’, year: ‘1850’, value: 276 }, { country: ‘Europe’, year: ‘1900’, value: 408 }, { country: ‘Europe’, year: ‘1950’, value: 547 }, { country: ‘Europe’, year: ‘1999’, value: 729 }, { country: ‘Europe’, year: ‘2050’, value: 628 }, { country: ‘Europe’, year: ‘2100’, value: 828 }, { country: ‘Asia’, year: ‘1750’, value: 502 }, { country: ‘Asia’, year: ‘1800’, value: 635 }, { country: ‘Asia’, year: ‘1850’, value: 809 }, { country: ‘Asia’, year: ‘1900’, value: 947 }, { country: ‘Asia’, year: ‘1950’, value: 1402 }, { country: ‘Asia’, year: ‘1999’, value: 3634 }, { country: ‘Asia’, year: ‘2050’, value: 5268 }, { country: ‘Asia’, year: ‘2100’, value: 7268 }, ];
const options = { type: ‘interval’, data, statistic: [ {type: ‘stackY’}, {type: ‘normalizeY’} ], encode: { x: ‘year’, y: ‘value’, color: ‘country’, } }
<a name="nqFVT"></a>### 分组条形图```javascript// https://g2.antv.vision/zh/examples/column/stack#stackedconst data = [{ name: 'London', 月份: 'Jan.', 月均降雨量: 18.9 },{ name: 'London', 月份: 'Feb.', 月均降雨量: 28.8 },{ name: 'London', 月份: 'Mar.', 月均降雨量: 39.3 },{ name: 'London', 月份: 'Apr.', 月均降雨量: 81.4 },{ name: 'London', 月份: 'May', 月均降雨量: 47 },{ name: 'London', 月份: 'Jun.', 月均降雨量: 20.3 },{ name: 'London', 月份: 'Jul.', 月均降雨量: 24 },{ name: 'London', 月份: 'Aug.', 月均降雨量: 35.6 },{ name: 'Berlin', 月份: 'Jan.', 月均降雨量: 12.4 },{ name: 'Berlin', 月份: 'Feb.', 月均降雨量: 23.2 },{ name: 'Berlin', 月份: 'Mar.', 月均降雨量: 34.5 },{ name: 'Berlin', 月份: 'Apr.', 月均降雨量: 99.7 },{ name: 'Berlin', 月份: 'May', 月均降雨量: 52.6 },{ name: 'Berlin', 月份: 'Jun.', 月均降雨量: 35.5 },{ name: 'Berlin', 月份: 'Jul.', 月均降雨量: 37.4 },{ name: 'Berlin', 月份: 'Aug.', 月均降雨量: 42.4 },];const options = {type: 'interval',data,statistic: [{type: 'dodgeX'}], // dodgeX 推断出 seriesencode: {x: '月份',y: '月均降雨量',color: 'name',}}// 下面的写法也是可以的const options = {type: 'interval',data,encode: {x: '月份',y: '月均降雨量',series: 'name',color: 'name',}}
饼图

// https://g2.antv.vision/zh/examples/pie/basic#labellineconst data = [{ item: '事例一', count: 40},{ item: '事例二', count: 21},{ item: '事例三', count: 17},{ item: '事例四', count: 13},{ item: '事例五', count: 9},];const options = {type: 'interval',statistic: [{type: 'percentageY'}, {type: 'stackY'}],coordinate: [{type: 'polar'}],ecnode: {y: 'count',color: 'item'}}
漏斗图
     
// https://g2.antv.vision/en/examples/funnel/funnel#pyramidconst data = [{ action: '浏览网站', pv: 50000 },{ action: '放入购物车', pv: 35000 },{ action: '生成订单', pv: 25000 },{ action: '支付订单', pv: 15000 },{ action: '完成交易', pv: 8000 },];const options = {type: 'interval',statistic: [{ type: 'symmetryY' }],coordinate: [ { type: 'transpose'}, { type: 'reflectY' }],ecnode: {y: 'count',x: 'action',color: 'action',shape: 'funnel'}}
Area
河流图

// https://g2.antv.vision/zh/examples/area/streamgraph#streamgraphconst options = {type: 'area',statistic: [{ type: 'stackY' }, { type: 'symmetryY' }],encode: {x: 'year',y: 'count',}}
雷达图

// https://g2.antv.vision/zh/examples/radar/radar#basicconst users = [{ item: 'Design', user: 'a', score: 70 },{ item: 'Design', user: 'b', score: 30 },{ item: 'Development', user: 'a', score: 60 },{ item: 'Development', user: 'b', score: 70 },{ item: 'Marketing', user: 'a', score: 50 },{ item: 'Marketing', user: 'b', score: 60 },{ item: 'Users', user: 'a', score: 40 },{ item: 'Users', user: 'b', score: 50 },{ item: 'Test', user: 'a', score: 60 },{ item: 'Test', user: 'b', score: 70 },{ item: 'Language', user: 'a', score: 70 },{ item: 'Language', user: 'b', score: 50 },{ item: 'Technology', user: 'a', score: 50 },{ item: 'Technology', user: 'b', score: 40 },{ item: 'Support', user: 'a', score: 30 },{ item: 'Support', user: 'b', score: 40 },{ item: 'Sales', user: 'a', score: 60 },{ item: 'Sales', user: 'b', score: 40 },{ item: 'UX', user: 'a', score: 50 },{ item: 'UX', user: 'b', score: 60 },];const options = {type: 'layer',data,coordinates: [{ type: 'polar' }],encode: {x: 'item',y: 'score',color: 'user'},style: {fillOpacity: 0.4,strokeOpacity: 0.4,},children: [{type: 'area'},{type: 'point'},],}
Line
平行坐标系

// https://vega.github.io/vega/examples/parallel-coordinates/const response = await fetch('https://vega.github.io/vega/data/cars.json');const data = await response.json();const options = {type: 'line',data,coordainte: [{type: 'parallel'}],component: [{type: 'axisY', channel: 'position[0]', title: 'HHH'}],scale: {'position[0]': { nice: true },},encode: {position: ['Cylinders','Displacement','Weight_in_Lbs','Horsepower','Acceleration','Miles_per_Callon','Year',],}}
Text
词云图
// https://vega.github.io/vega/examples/word-cloud/const options = {type: 'text',data: '...',transform: [{type: 'split'},{type: 'wordcloud'} // 这是个异步的操作],scale: {color: {range: ["#d5a928", "#652c90", "#939597"]}},encode: {text: 'text',x: 'x',y: 'y',fontSize: 'fontSize',rotation: 'rotation',color: 'text',},};
Annotation

// https://g2.antv.vision/zh/examples/case/line#line7const options = {type: 'layer',data,encode: {x: 'Date',y: 'Close'},children: [{type: 'line'},{type: 'text',statistic: [{type: 'selectMinY'}],encode: {text: d => `全部谷值:${d.Close}`}},{type: 'text',statistic: [{type: 'selectMaxY'}],encode: {text: d => `全部峰值:${d.Close}`}}],};
外部 Label

// https://g2.antv.vision/zh/examples/case/column#column2const data = [{ type: '未知', value: 654, percent: 0.02 },{ type: '17 岁以下', value: 654, percent: 0.02 },{ type: '18-24 岁', value: 4400, percent: 0.2 },{ type: '25-29 岁', value: 5300, percent: 0.24 },{ type: '30-39 岁', value: 6200, percent: 0.28 },{ type: '40-49 岁', value: 3300, percent: 0.14 },{ type: '50 岁以上', value: 1500, percent: 0.06 },];// 这是其中一种写法,text,interval 是同一层级的东西const config = {type: 'layer',encode: {x: 'type',y: 'value'},children: [{ type: 'interval'},{type: 'text',encode: { text: 'value' },style: { dy: '-2em' }},{type: 'text',encode: { text: 'percent' },style: { dy: '-1em' }}],}// 这是第二种写法,text 是 interval 的一部分// 这样 text 就可以感知 interval 的 bounding boxconst options = {type: 'interval',data,encode: {x: 'type',y: 'value'},children: [{type: 'text', // 默认位置是父亲元素 bounding box 的左上角encode: { text: 'value' },style: { dy: '-2em' }},{type: 'text',encode: { text: 'percent' },style: { dy: '-1em' }}]};
内部 Label

// https://g2.antv.vision/zh/examples/relation/relation#treemapconst options = {type: 'polygan',data,transform: [{type: 'treemap'}],encode: {x: 'x',y: 'y'},children: [{type: 'text',encode: {x: 0.5, // 指定为中心y: 0.5, // 指定为中心text: 'label',},// scale: {// x: {type: 'identity'},// y: {type: 'identity'}// }}]}
Image
散点图

// https://g2.antv.vision/zh/examples/point/bubble#bubble-imageconst data = [{ name: 'Internet Explorer', value: 26, imageURL: ''},{ name: 'Chrome', value: 40, imageURL: ''},{ name: 'Firefox', value: 30, imageURL: ''},{ name: 'Safari', value: 24, imageURL: ''},{ name: 'Opera', value: 15, imageURL: ''},{ name: 'Undetectable', value: 8, imageURL: ''}];const options = {type: 'layer',children: [{type: 'edge',x: ['name', 'name'],y: ['value', 1],shape: 'dash'},{type: 'image',data,scale: {size: {type: 'pow'}},encode: {x: 'name',y: 'value',url: 'imageURL',size: 'value'}}]};
Mix
桑基图

// https://g2.antv.vision/zh/examples/case/sankey/#sankey-cardconst options = {type: 'layer',data,transform: [{ type: 'sankey', /** 更多参数 **/ } // 在这里计算],children: [{transform: [{type: 'pick', fields: ['nodes']}],type: 'polygon',encode: {x: 'x',y: 'y,}},{transform: [{type: 'pick', fields: ['edges']}],type: 'edge',encode: {shape: 'arc',x: 'x',y: 'y'}}]};
双轴柱线图

// https://g2.antv.vision/zh/examples/other/other#double-axesconst data = [{ time: '10:10', call: 4, waiting: 2, people: 2 },{ time: '10:15', call: 2, waiting: 6, people: 3 },{ time: '10:20', call: 13, waiting: 2, people: 5 },{ time: '10:25', call: 9, waiting: 9, people: 1 },{ time: '10:30', call: 5, waiting: 2, people: 3 },{ time: '10:35', call: 8, waiting: 2, people: 1 },{ time: '10:40', call: 13, waiting: 1, people: 2 }];const options = {type: 'layer',data,encode: {x: 'time'},sync: {y: false},children: [{type: 'interval',encode: {y: 'waiting',color: '#3182bd',}},{type: 'layer',encode: {y: 'people',color: '#fdae6b'},component: [// 没有这条声明轴会都在右边// 因为这两者的 scale 没有同步{type: 'axisY', position: 'left'}],children: [{type: 'point'},{type: 'line'}]}],};

这种情况可能需要一种同步两边刻度的算法,但是只能保证一边刻度的可读性。
柱状双轴图

// https://codesandbox.io/s/dual-axes-of-column-5xk0pg?file=/index.tsconst data = [{ year: "1991", value: 3, count: 10 },{ year: "1992", value: 4, count: 4 },{ year: "1993", value: 3.5, count: 5 },{ year: "1994", value: 5, count: 5 },{ year: "1995", value: 4.9, count: 4.9 },{ year: "1996", value: 6, count: 35 },{ year: "1997", value: 7, count: 7 },{ year: "1998", value: 9, count: 1 },{ year: "1999", value: 13, count: 20 }];const options = {type: 'layer',data,sync: {y: false,},encode: {x: 'year',y: 'value',},scale: {series: {range: ['a', 'b'] // 指定一共有两个序列}},children: [{type: 'interval',encode: {series: 'a', // 指定是序列 a}},{type: 'interval',encode: {series: 'b', // 指定是序列 b}}]};
比例尺
分段映射
暂时用双轴图代替
// https://github.com/antvis/G2/issues/2712const options = {type: 'line',data,scale: {y: {domain: [0, 80, 100, 105],range: [0, 0.5, 0.5, 1]}},encode: {x: 'time',y: 'value',color: 'type'}};
纹理

// https://g2plot.antv.vision/zh/examples/plugin/pattern#bar-patternconst data = [{ type: '分类一', value: 27 },{ type: '分类二', value: 25 },{ type: '分类三', value: 18 },{ type: '分类四', value: 15 },{ type: '分类五', value: 10 },];const options = {type: 'interval',data,coordinate: [{type: 'transpose'}],scale: {color: {palette: {type: 'pattern'},range: [{type: 'dot'},{type: 'line'},{type: 'square'},{type: 'line',spacing: 6,lineWidth: 2,rotation: 90,},{type: 'square',size: 5,padding: 2,rotation: 45,isStagger: false,}]}},encode: {x: 'type',y: 'value',color: 'type' // 纹理也是通过 color 来指定}}
不同颜色方案
可以参考这个里面的颜色方案:https://github.com/antvis/color-schema。这个地方可能就需要人来整理 antv 对颜色方法,沉淀到 color-schema 这个库中,这个库目前完全不能用。
// https://g2.antv.vision/zh/examples/pie/basic#labellineconst data = [{ item: '事例一', count: 40},{ item: '事例二', count: 21},{ item: '事例三', count: 17},{ item: '事例四', count: 13},{ item: '事例五', count: 9},];const options = {type: 'interval',statistic: [{type: 'percentageY'}, {type: 'stackY'}],coordinate: [{type: 'polar'}],scale: {color: {// 换一种配色// 等同于修改默认的 range// 上面图表理论上会变颜色palette: {type: 'monochromatic'}}},ecnode: {y: 'count',color: 'item'}}
智能颜色
使用这个库:https://github.com/antvis/smart-color,比如下面的从图片提取颜色的能力,但这个能力应该是通过插件的形式透出。
import {createRuntime, createLibrary} from '@antv/g2';import {extract} from '@antv/smart-color';// 注册const ImagePalette = (options) => {const { url } = options;return () => {return extract(url); // 返回一个颜色数组}};ImagePalette.props = {type: 'image',};const library = Object.assgin(createLibrary(), {'palette.image': ImagePalette});const runtime = createRuntime({container},library);const data = [{ item: '事例一', count: 40},{ item: '事例二', count: 21},{ item: '事例三', count: 17},{ item: '事例四', count: 13},{ item: '事例五', count: 9},];const options = {type: 'interval',statistic: [{type: 'percentageY'}, {type: 'stackY'}],coordinate: [{type: 'polar'}],scale: {color: {palette: {type: 'image', url: 'xxx'}}},ecnode: {y: 'count',color: 'item'}}
视图复合
flex

const options = {type: 'flex',direction: 'col',data,flex: [1, 1],encode: {x: 'time',y: 'value;},children: [{type: 'area'},{type: 'flex',direction: 'col',flex: [1, 1],axis: false,children: [{type: 'interval'},{type: 'area'}]}]};
分面
矩形分面
默认同步 data domain
// https://vega.github.io/vega-lite/examples/trellis_bar.htmlconst options = {type: 'rect',data,encode: {y: 'gender',},// 如果没有下面的注释的话就不同同步 data domain// 这样上面 y 轴的范围将是不一样的// sync 的时候是给孩子增加一个 statistic 去 filter index// 不 sync 的时候是给孩子一个 transform 去 filter data// sync: {// data: false// },children: [{type: 'interval',encode: {x: 'age',y: 'population'}}],};
带背景的矩形分面

// https://observablehq.com/@observablehq/plot-facets?collection=@observablehq/plotconst options = {type: 'rect',data,encode: {x: 'sex',y: 'species'},children: [{type: 'layer',encode: {x: 'culmen_depth_mm',y: 'culmen_length_mm'},children: [{type: 'point',// 不过滤数据// 实现背景非常的有效filter: false},{type: 'point'}]}]};
矩阵分面

// https://vega.github.io/editor/#/examples/vega/brushing-scatter-plotsconst response = await fetch('https://vega.github.io/editor/data/penguins.json');const data = response.json();// 会自动的生成一系列标准的配置const options = {type: 'matrix',data,component: [{type: 'legendCategory', channel: 'color', position: 'right'}],fields: ['Break Length (mm)','Break Depth (mm)','Flipper Length (mm)','Body Mass (g)'],children: [{type: 'point',encode: {// facet 元素会自动的生成该元素的 x 和 y encode// 这个地方就不会 filter 了color: 'Species'}}]};
带回调的矩阵分面

// https://g2.antv.vision/zh/examples/facet/facet#matrixconst options = {type: 'matrix',data,fields: ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth'],children: (props) => {const {data, rowIndex, columnIndex, rowField, colField} = props;if (rowIndex === columnIndex) {return {type: 'polygon',data,statistic: [{type: 'binX'},{type: 'summaryX', aggregate: 'count'}],encode: {y: 'count',x: colField,color: 'Species'}}} else {return {type: 'point',data,statistic: [{type: 'stackY'}],encode: {x: rowField,y: colField,color: 'Species',}}}}};
树状分面

// https://g2.antv.vision/zh/examples/facet/facet#tree-columnconst data = [{ gender: '男', count: 40, class: '一班', grade: '一年级' },{ gender: '女', count: 30, class: '一班', grade: '一年级' },{ gender: '男', count: 35, class: '二班', grade: '一年级' },{ gender: '女', count: 45, class: '二班', grade: '一年级' },{ gender: '男', count: 20, class: '三班', grade: '一年级' },{ gender: '女', count: 35, class: '三班', grade: '一年级' },{ gender: '男', count: 30, class: '一班', grade: '二年级' },{ gender: '女', count: 40, class: '一班', grade: '二年级' },{ gender: '男', count: 25, class: '二班', grade: '二年级' },{ gender: '女', count: 32, class: '二班', grade: '二年级' },{ gender: '男', count: 28, class: '三班', grade: '二年级' },{ gender: '女', count: 36, class: '三班', grade: '二年级' }];const options = {type: 'tree',data,fields: ['grade', 'class'],// 会默认生成 edge 和 text geometry// 会被包裹成一个 layer containerchildren: [{type: 'interval',statistic: [{type: 'stackY'}],encode: {x: 'percent',color: 'gender',}}]};
组件
标题

const options = {type: 'interval',data,encode: {x: 'a',y: 'b'},component: [{type: 'title', content: 'A Simple Bar Chart'},],}
合并图例

const options = {type: 'point',data,encode: {x: 'Flipper Lengh (mm)',y: 'Body Mass (g)',color: 'Species',shape: 'Species'}}
统计
选择

const options = {type: 'layer',encode: {x:'Date',y:'Close',series: 'Symbol'},children: [{type: 'text',statistic: [{type: 'selectLast'}],},{type: 'line',encode: {color: 'Symbol'}}]};
总结

// https://g2.antv.vision/zh/examples/component/label#line2const data = [{"date": "2012-09","buyin": 7228},// ...]const options = {type: 'layer',data,children: [{type: 'layer',encode: {x: 'date',y: 'buyin'},children: [{ type: 'line' },{type: 'text',encode: {text: 'buyin'}}]},{type: 'annotation.line', // 新的 linestatistic: [{type: 'summaryY', aggregate: 'mean'}],encode: {y: 'mean'}}]}
分箱

const options = {type: 'polygon',statistic: [{type: 'bin', shape:'rect'},{type: 'summary', aggregate: 'count'}],encode: {x: 'rainfall',y: 'degdays',// 这是一个 lazy encode// 它的值是在 transform 完成之后才提取出来的color: 'count'}}

const options = {type: 'rect',statistic: [{type: 'binX'},{type: 'summary', aggregate:'count'} // 可以省略 count],encode: {x: 'weight',y: 'count',color: 'sex',}}
动画
更多案例:https://hanabi.data-viz.cn/templates?lang=zh-CN
条竞赛图


// https://observablehq.com/@d3/bar-chart-race-explainedconst options = {type: 'sequnce',scale: {timming: {range: [0, 60 * 1000] // 一共执行时间是 1分钟}},encode: {timing: 'date'},children: [{type: 'text',statistic: [{type: 'selectLast'}],scale: {},encode: {key: 'date',text: d => d.date.getFullYear(),x: 1,y: 1},style: {textAnchor: 'end',fontSize: 50}},{type: 'interval',coordinate: [{type: 'transpose'}],statistic: [// 只展示前 12 条数据{type: 'sort', by: 'value'},{type: 'filterRank', count: 12}],encode: {key: 'name',x: 'name',y: 'value',color: 'category'}}]};
数据实时更新
https://www.highcharts.com.cn/demo/highcharts/dynamic-update/dark-unica
甘特图动画

// https://canisjs.github.io/canis-editor/index.html?exmp=gantt_1const data = [{ eventStartTime: '', eventDurationTime: '', eventName: ''},// ...];const config = {type: 'interval',data,encode: {x: 'eventName',y: ['eventStartTime', d => d.eventStartTime + d.eventDurationTime],enterDelay: 'eventStartTime', // 动画属性也和通道绑定enterDuration: 'eventDurationTime' // 动画属性也和通道绑定},}
条形图动画(New)

// https://canisjs.github.io/canis-editor/index.html?exmp=groupedBar_1const data = [{year: '', sale: '', type: ''}];const options = {data,encode: {x: 'year',y: 'sale',color: 'type',enterDelay: 'type',},animte: {enterDuration: 100,enterType: '',}};
折线图尾随动画

const options = {type: 'layer',data,children: [{type: 'line',encode: {x: 'year',y: 'value',color: 'type'},animate: {enterType: 'path-in',enterDuration: 10 * 1000,}},{type: 'sequnce',scale: {timing: {range: [0, 10 * 1000]}},encode: {timing: 'year'},}]};
简单可视化叙事

这个地方应该再加上坐标轴的动画。
// https://echarts.apache.org/examples/zh/editor.html?c=scatter-aggregate-bar// https://www.w3schools.com/css/css3_animations.aspconst data = [{ height: '', weight: '', sex: 'male', name: '' },// ...];const options = {type: 'keyframe',data,iterationCount: 'infinite',direction: 'alternate',duration: '3000',children: [{type: 'interval',statistic: [{type: 'groupX'},{type: 'summary', aggregate: 'mean'}],encode: {x: 'sex',y: 'mean',color: 'blue',key: 'sex'}},{type: 'point',encode: {x: 'height',y: 'weight',color: 'sex',key: 'name',groupKey: 'sex'}}],};
普通可视化叙事 (Todo)
// https://stackblitz.com/github/pissang/echarts-www-landing-animation
复杂可视化叙事 (Todo)
// https://bl.ocks.org/mbostock/1256572
单元可视化
泰坦尼克(一)

关键有几点:
- 分 data domain 和 space domain
 - 兄弟节点是否共享(同步)data domain 和 space domain
 - 防止重叠的算法:pack
const options = {type: 'rect',data,encode: {x: 'Class',y: 'Gender',},children: [{type: 'point',ajust: [{type: 'pack'} // 使用默认的大小 uniform 的],encode: {color: 'Survived',},}]};
泰坦尼克(二)

const options = {type: 'rect',encode: {x: 'Class'},children: [{type: 'point',adjust: [{type: 'pack'}],encode: {size: 'ticket',color: 'Survived'}}]};
泰坦尼克(三)

// (b)const options = {type: 'rect',encode: {x: 'Class',},sync: {data: false // 不同步 data domain},children: [{type: 'point',adjust: [{type: 'pack'}],encode: {color: 'Survived',}}]};
泰坦尼克(四)


const options = {type: 'rect',encode: {x: 'survived',y: 'pclass',},children: [{type: 'rect',encode: {y: 'sex',},children: [{type: 'point',adjust: [{ type: 'pack' }],encode: {color: 'survived',}}]}]}
Sand Dance(Todo)
交互
有的交互修改数据,有的交互修改状态。框选
```javascript
// https://g2.antv.vision/zh/examples/interaction/brush#brush-filter-record 
function Brush() { return () => ({ showEnable: [ { trigger: ‘plot:mouseenter’, action: ‘cursor:crosshair’ }, { trigger: ‘mask:mouseenter’, action: ‘cursor:move’ }, { trigger: ‘plot:mouseleave’, action: ‘cursor:default’ }, { trigger: ‘mask:mouseleave’, action: ‘cursor:crosshair’ }, ], start: [ { trigger: ‘plot:mousedown’, isEnable(context) { return !context.isInShape(‘mask’); }, action: [‘rect-mask:start’, ‘rect-mask:show’] }, { trigger: ‘mask:dragstart’, action: ‘rect-mask:moveStart’ } ], processing: [ { trigger: ‘plot:mousemove’, action: ‘rect-mask:resize’ }, { trigger: ‘mask:drag’, isEnable(context) { return context.isInPlot(); }, action: ‘rect-mask:move’ }, { trigger: ‘mask:change’, action: ‘element-sibling-filter-record:filter’ } ], end: [ { trigger: ‘plot:mouseup’, action: ‘rect-mask:end’ }, { trigger: ‘mask:dragend’, action: ‘rect-mask:moveEnd’ } ], rollback: [ { trigger: ‘dblclick’, action: [‘rect-mask:hide’, ‘element-sibling-filter-record:reset’] } ] }); }
Brush.props = { name: ‘brush’ };
const options = { type: ‘flex’, data, children: [ { type: ‘point’, encode: { x: ‘carat’, y: ‘price’, }, interaction: [ { type: ‘brush’} ], }, { type: ‘point’, encode: { x: ‘depth’, y: ‘x’ } } ] };
<a name="Oyn2n"></a>## 饼图转动```javascript// https://lark-assets-prod-aliyun.oss-accelerate.aliyuncs.com/lark/0/2021/gif/355/1636429547581-2de3143e-7a36-4775-bf2e-4dd6214576aa.gif?OSSAccessKeyId=LTAI4GGhPJmQ4HWCmhDAn4F5&Expires=1645519032&Signature=RO9%2F3LPuQkVWsRyCWrcufFtrUvQ%3D&response-content-disposition=inline// https://intranetproxy.alipay.com/skylark/lark/0/2021/gif/355/1636429547581-2de3143e-7a36-4775-bf2e-4dd6214576aa.gif// 注册一个新的 Actionfunction Rotate() {// ...}// 注册一个新的 Actionfunction Select(options) {const {x, y, eid, sid} = options;return (runtime) => {const context = runtime.getContext();const view = getView(context, id); // 获得对应视图const datum = getDatum(context, y); // 获得这个点的数据const index = getIndex(context, datum); // 获得数据的索引runtime.update([sid, {index} // 更新对应的 idnex]);}}const options = {type: 'layer',data,children: [{type: 'interval',id: '$interval',data,statistic: [{type: 'stackY'}],coordainte: [{type: 'polar', innerRadius: 0.5}],encode: {y: 'value',color: 'type',},interaction: [{type: 'on',event: 'element:drag',action: [{type: 'rotate'},{type: 'select', x: '50%', y: '10', eid: '$interval', sid: '$index'}],}],},{type: 'layer',statistic: [{type: 'selectIndex', id: '$index', index: 0}], // 定义一个 idchildren: [{type: 'text',encode: {text: d => d.value + '人'},},{type: 'text',encode: {text: d => d.type},style: {dy: '-1em'}}]},// 视图树里面也可以有简单的 G 元素// 和几何元素的区别在于和数据没有关联// 不是数据驱动的{type: 'lineG',style: {x1: '50%', y1: 0,x2: '50%', y2: 10}}]}
鱼眼

// https://g2.antv.vision/zh/examples/point/bubble#bubbleconst options = {type: 'point',coordinate: [{type: 'fisheye', focusX: 0.5, focusY: 0.5, id: '$fisheye'}],encode: {x: 'GDP',y: 'LifeExpectancy',color: 'continent',size: 'Population',},interaction: [{type: 'on', // 监听事件本身就是一个 interactiontrigger: 'plot:mousemove',action: [{// 说明返回值是配置的更新函描述// 内部会重新调用 update 方法type: 'runtime:update',handler: (e) => {const {x, y} = e.target;// 更新 id 为 $fisheye 的配置return ['$fisheye', { focusX: x, focusY: y }];}}]}],};// on 的内部大概实现function On(options) {const {trigger, action} = optionsreturn () => {return {start: [{trigger, action}]}}}On.props = {type: 'on'};
自定义
图形
水波图

// https://g2plot.antv.vision/zh/examples/progress-plots/liquid#basicimport {createRuntime, createLibrary} from '@antv/g2';const LiquidShape = (options) => {const {shape} = options;return (renderer, coordinate, attributes) => {// draw liquid// animation}};LiquidShape.props = {type: 'liquid',metadata: {geometry: 'interval',},};const library = Object.assgin(createLibrary(), {'shape.liquild': LiquidShape});const runtime = createRuntime({container}, library);const options = {type: 'layer',data: [{value: 0.25}],children: [{type: 'text',encode: {x: 0.5,y: 0.5,text: d => (d * 100).toFixed(2) + '%',}},{type: 'interval',scale: {y: {domain: [0, 1]}},encode: {y: 'value',shape: 'liquid'}}],};
连接不同视图

// https://g2.antv.vision/zh/examples/case/pie#pie2

