antvg2 环图轮播_教你使用 G2Plot 绘制星空诺贝尔奖可视化

语雀

作品介绍

本次要分享的是使用 G2Plot 来实现「财新网」 诺贝尔奖可视化作品,原作品地址。本次对该作品进行了部分简化和改造,下文先介绍下具体的视觉设计和视觉元素对应的含义,再给大家介绍下实现该作品的一个技术实现思路。知乎视频​www.zhihu.com

视觉设计

数据分析思路

(1)以时间线为导线,将获奖年龄划分为4个年龄阶段,按年份累计分别展示:各奖项获奖比例(内环图)

各国各奖项按获奖年龄分布的情况(环形散点图)

(2)最后对 1901-2015 年的获奖情况进行一个汇总,可以看到 42 个国家按照获奖年龄段在不同学科奖项上的分布情况,点越大代表获奖人数越多。

视觉通道映射

(1)获奖年龄:位置

(2)国家:位置

(3)奖项学科类别:颜色

(4)获奖人数:大小

(5)其他的数据信息:边栏

实现思路

初步了解视觉设计之后,我们来对该可视化信息图进行拆解分析,可以划分为以下几部分:内环图(含义:代表各奖项获奖比例;视觉通道:颜色;映射属性:奖项学科类别)+ 中心文本

环形散点图(含义:代表各国各奖项按获奖年龄分布的情况;视觉通道:位置、颜色、大小;分别映射属性:国家、获奖年龄、奖项学科类别、获奖人数)

辅助元素:年份边栏、当前年份滑块

经过拆解分析之后,我们可以把每一部分都作为一个 View(1)(即图层),对每一个 view 进行组装处理之后,进行叠加就可以形成一个多图层的信息图表了

G2Plot 多图层实验室透传 80% G2 能力,下面我们来看下如何利用 G2Plot 多图层实验室来实现该可视化信息图表,重点的部分会使用 ✨ 来标识 (*╹▽╹*)

内环图

我们先准备第一个 view

① 准备数据

② 设置坐标系:theta 坐标系,调整下半径 radius 和内半径 innerRadius

③ 绘制几何图形,确定视觉通道映射:环图对应的几何标记是 interval,x 轴无映射,y 轴位置映射到获奖数量,以 奖项类别 作为颜色映射,因此 type = interval yField = counts colorField = type ,同时还需要对数据进行调整,设置 adjust = stack

④ 进行图表组件和样式的装饰:通过 annotations 来配置中心文本标注,详细可见:Annotations 文档

伪代码:

const view1 = {

// ① 环图的数据 donutData

data: donutData,

region: { start: { x: 0, y: 0.35 }, end: { x: 1, y: 0.65 } },

coordinate: {

type: "theta",

cfg: { innerRadius: 0.84, radius: 0.96 },

},

geometries: [

{

type: "interval",

yField: "counts",

colorField: "type",

// 通道映射支持 color,size、shape 等

mapping: {

// 在 color 映射的回调中,我们可以进行颜色的自定义

color: ({ type }) => {

const idx = types.indexOf(type);

const { colors10 = [] } = labChart.chart.getTheme();

return colors10[idx] || "#D9D9D9";

},

},

adjust: { type: "stack" },

},

],

annotations: [

{

type: "text",

content: "G2Plot",

position: ["50%", "50%"],

style: {

textAlign: "center",

fontWeight: 400,

fontSize: 28,

},

},

],

};

效果图:

环形散点图

① 准备数据

② 设置坐标系:polar 极坐标系,调整下半径 radius 和内半径 innerRadius

③ 绘制几何图形,确定视觉通道映射:散点图对应的几何标记是 point,x 轴映射到国家,y 轴位置映射到获奖年龄,以 奖项类别 作为颜色映射,因此 type = point xField = country yField = ageGroup colorField = type ,同时还需要对数据进行调整,设置 adjust = dodge (这里我们对同颜色的 point 进行分组错开)

④ 进行图表组件和样式的装饰:可以适当调整下坐标轴 axes 的样式,详细可见:Axis 文档

⑤ ✨ 放射状的国家标签 ✨:这里我们可以巧妙利用 polar 坐标系下的 label 设置 labelEmit 来达到一个放射状标签的效果。新增一个 interval 的几何标记,x 轴映射到国家,y轴无需映射或者映射到 "1",详细可见:Label 文档

const view2 = {

// ① 散点图的数据 pointViewData

data: pointViewData,

region: { start: { x: 0, y: 0 }, end: { x: 1, y: 1 } },

coordinate: {

type: "polar",

cfg: {

innerRadius: 0.45,

radius: 0.64,

},

},

axes: {/* 略 */},

geometries: [

{

type: "point",

xField: "country",

yField: "ageGroup",

colorField: "type",

sizeField: "number",

adjust: {

type: "dodge",

},

mapping: {

size: [2, 8],

shape: "circle",

style: {

fillOpacity: 0.65,

lineWidth: 0,

},

},

},

{

// 国家标签

type: "interval",

xField: "country",

label: {

labelEmit: true,

fields: ["country"],

offset: 50,

style: {

fontSize: 10,

},

},

mapping: {

color: "transparent",

},

},

],

};

效果图:

辅助元素:年份边栏、当前年份滑块

最后我们还剩下一些辅助元素,我们继续准备一个 view,主要实现一个年份的边栏和当前年份的滑块。同样我们还是可以借助 polar 坐标系下的 label 设置 labelEmit 来达到一个放射状标签的效果。数据就是 1901 - 2015年啦(这里附加2条数据:1900和2016,作为起点和重点)

确定视觉通道映射:几何标记选择 line 或 interval 均可,因为没有实际含义,只是需要用到 label 标签的展示;x 轴映射 year,y 轴无映射,label 设置 labelEmit ;边栏和滑块使用不同的几何标记(geometry),对应使用不同的 label 组件,便于后期的交互处理。

确定好思路之后,代码大概如下:

const view3 = {

// ① 年份数据 pointViewData

data: yearData,

region: { start: { x: 0.05, y: 0.05 }, end: { x: 0.95, y: 0.95 } },

axes: {/* 略 */},

coordinate: { type: "polar", cfg: { innerRadius: 0.99, radius: 1 } },

geometries: [

{

type: "line",

xField: "year",

label: {

labelEmit: true,

content: ({ year }) => {/* ✨ 重点处理,通过回调只展示整数值的年份 */},

},

mapping: {

// 几何图形没有实际含义,设置填充色为 透明

color: "transparent",

},

},

{

type: "interval",

xField: "year",

label: {

labelEmit: true,

fields: ["year"],

callback: (year) => {

return {/* ✨ 重点处理,通过回调只展示当前年份 */},

},

mapping: {

// 几何图形没有实际含义,设置填充色为 透明

color: "transparent",

},

},

]

};

整合到多图层实验室(MultiView)MultiView 的每个图层包括有自己的:数据、图形、图形映射,可以独立完成自己的逻辑组装。

tooltip、legend 等在顶层进行配置。如下:设置 legend: { number: false } 可以将 number 字段映射的图例进行关闭,其他同普通 plot 的图例和 tooltip 使用方式保持一致,保持心智统一,带来更加友好的开发体验。

高级进阶:动态交互

从前面的预览图,可以看到有一些动态交互:① 整体按照时间线进行轮播变换;② 单击边栏,将滑块移动至指定年份;③ 双击边栏,将滑块移动至指定年份,并且停止轮播

整体按照时间线进行轮播变换

可以看到轮播的时候,变化的是「内环图」和「散点图」的数据,因此我们可以启动一个定时器来定时改变这两个 view 对应的数据。

✨ 技术实现关键点:获取「内环图」和「散点图」对应的 view,通过 labChart.chart 获取到 G2 的 chart 对象,再通过 chart.views 可获取到所有的 view 对象,再根据 views 传进的顺序即可获取到对应的 view

获取「内环图」和「散点图」当前年份对应的数据,调用 view.changeData

function rerender(specYear) {

labChart.chart.views[0].changeData(getIntervalViewData(specYear));

labChart.chart.views[1].changeData(getPointViewData(specYear));

}

单击边栏,将滑块移动至指定年份

关于这个交互要做的事情:监听边栏元素点击事件,将当前年份修改为鼠标事件指定年份,并且移动滑块和重新渲染环图与散点图。

✨ 技术实现关键点:监听边栏元素点击事件,获取边栏对应的 view 对象,监听图形元素(2)(element)点击事件

高亮当前选中年份,进行滑块移动(这里通过指令式的方式,重新调用 label 通道,再执行 render(true) 进行重新绘制,而非重新渲染)

const view1 = labChart.chart.views[0];

const view2 = labChart.chart.views[1];

const view3 = labChart.chart.views[2];

// 根据 view3 中创建的顺序,可知 滑块对应的第 2 个几何标记对象 geometryconst sliderBlock = view3.geometries[1];

function rerender(specYear) {

view1.changeData(getIntervalViewData(specYear));

view2.changeData(getPointViewData(specYear));

sliderBlock.label('year', (year) => {

const { defaultColor } = labChart.chart.getTheme();

return {

labelEmit: true,

style: {

fill: year === specYear ? 'rgba(255,255,255,0.85)' : 'transparent',

},

content: () => `${specYear === 2016 ? ' ALL ' : specYear}`,

background: {

padding: 2,

style: {

radius: 1,

// 非当前年份,进行透明展示 fill: year === specYear ? defaultColor : 'transparent',

},

},

};

});

// 传入参数 true,重新绘制,不重新触发更新流程。 view3.render(true);

}

// 监听 element click 事件,指定当前年份,并且启动轮播view3.on('element:click', (evt) => {

handldSlideBlockClick(evt);

start();

});

// 监听 element click 事件,指定当前年份,并且暂停轮播view3.on('element:dblclick', (evt) => {

handldSlideBlockClick(evt);

end();

});双击边栏,将滑块移动至指定年份,并且停止轮播同理,只要将监听事件修改为 dblclick 再执行具体的事件处理即可

最后

这周分享的可视化信息图表实现原理就到这里了,源代码在 G2Plot 的 官网示例 上,大家可以亲自动手尝试下~

更多文章,可以帮助了解 G2 的基础概念和进阶内容:

View(图层)

View 是图层容器的概念,每一个 View 拥有自己独立的数据源、坐标系、几何标记、Tooltip 以及图例,可以理解 View 是用来组装数据,Component,Geometry 的容器。 一个 View 可以包含有多个子 View,通过这种嵌套关系,可以将一个画布按照不同的布局划分多个不同区域(分面),也可以将不同数据源的多个 View 叠加到一起,形成一个多数据源,多图层的图表。详细文档

Geometry(几何标记)

geometry 即你在图表中实际看到的图形元素,如点、线、多边形等,每个几何标记对象含有多个图形属性,G2 的核心就是建立数据中的一系列变量到图形属性的映射。详细文档。

Element(图形元素)

Element 即一条/一组数据对应的图形元素,它代表一条数据或者一个数据集。

数据在不同的 geometry 上的渲染方式不同,在点图上一条数据会对应一个点,在柱状图中 每条数据对应一个柱子,而在折线图上则是一组数据对应一条折线。

职责:绘制、更新、销毁 Shape & 状态管理


版权声明:本文为weixin_33681937原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。