自定义绘图

<< Click to Display Table of Contents >>

当前位置:  设计可视化分析报告 > 可视化组件 > 制作图表 > 图表类型 

自定义绘图

复制链接

1. 概述

1.1 应用场景

产品内置的图表类型和样式虽然丰富,但在某些特定场景或样式需求下可能无法满足用户的全部要求。自定义绘图组件的引入,正是为了填补这一空白,使得用户能够根据自己的需求进行图表的定制。

1.2 功能简介

自定义绘图组件支持用户通过编写JS代码,直接调用内置的Echarts、AntV_G2、AntV_G2Plot、AntV_G6等图表库,实现图表的完全自定义绘制。用户可以自由配置图表样式、布局、交互等属性,打造独一无二的视觉化效果。

2. 应用举例

用户在制作报告时,需要做一个各产品种类销售额的环形图。产品自带的图表样式无法满足可视化需求,在Echarts中找到了对应的图表样式。如下图,

js33

这个时候就可以使用自定义绘图功能,详细操作步骤如下,

1)新建自定义绘图组件:从右侧【组件】区域拖拽自定义绘图组件到画布中。

js1_zoom28

2)给组件绑定数据:从数据列表中拖拽所需的数据列(产品种类、销售额)到数据绑定区,数据列会按照绑定顺序依次定义为column1、column2等,并显示在Data区域。

js34_zoom60

3)点击Echarts图表,复制JS代码。

js36_zoom50

4)点击数据绑定区的“自定义JS代码”,进入代码编辑区。选择Echarts库,代码格式选择“option”。

js35_zoom60

5)粘贴复制的JS代码,并替换数据,即data部分。这里需要将数据转换为特定的数组或键值对格式。如下图,

原始代码:

js37

替换为:

data: options.data.map(o => ({value: o.column2, name: o.column1}))

js38

6)执行与预览:编写完JS代码后,点击代码编辑区右上角的“执行”按钮,系统会在右侧预览区域绘制图表。若代码存在错误,会给出相应的提示信息。

js39_zoom70

7)点击“确定”,再点击“保存”报告即可。

3. 功能说明

自定义绘图组件支持多种图表库,包括 EchartsAntV_G2AntV_G2PlotAntV_G6,您可以直接调用代码库,相关代码的配置属性以及图表示例请前往官网查看。

Echarts:支持丰富的图表类型和高度可定制的样式,适用于大多数基础图表和复杂图表的绘制。

AntV_G2:一套简洁的渐进式可视化语法,用于报表搭建、数据探索以及可视化叙事。

AntV_G2Plot:专为数据可视化设计的图表库,提供简洁易用的API和强大的数据处理能力。现已被AntV_G2替代,AntV官方不再主推。

AntV_G6:专注于图网络的可视化,支持复杂的图结构展示和丰富的交互功能。

3.1 数据绑定说明

图表

数据

自定义绘图

0个或多个

3.2 自定义JS代码说明

绑定完数据后,我们需要给组件自定义JS代码,以定义图表绘制规则,点击数据绑定区的“自定义JS代码”,在弹窗中进行配置:

js3_zoom79

自定义JS代码配置:

【chart库】默认可以选择Echarts、AntV_G2、AntV_G2Plot、AntV_G6,选择以后,在绘制时会直接调用对应代码库绘制图表。

【代码格式】选择完chart库后,需要选择JS代码格式,Echarts仅支持option格式,AntV_G2、AntV_G2Plot、AntV_G6仅支持完整代码,为保证正常绘图,代码格式与所选格式需保持一致。

【Data】绑定的数据列会展示在Data区域,并按照绑定的顺序依次定义为column1、column2......,可以直接在代码中引用,例如绑定了市场级别、产品种类2列数据,如下图:

js10

【执行】输入完JS代码之后,点击代码编辑区右上角的“执行”按钮,会在右侧预览区域绘制图表,若代码存在错误会给出提示。

3.3 JS代码示例

3.3.1 Echarts

Echarts可以复制option的代码,也可以复制完整代码。

options代码

代码示例如下图:

js4

3D地球类图表,需要定义路径,如下图:

js5_zoom78

完整代码

如果是复制完整代码,请不要定义chartDom变量,产品已经定义了DOMid为$container,可能会都导致无法绘制到报告画布中。因此需要去掉或者注释以下两行代码,

js6

正确写法如下图:

js7

或者如下:

import * as echarts from 'echarts';

//var chartDom = document.getElementById('main');

//var myChart = echarts.init(chartDom);

var option;

option = {

 tooltip: {

   formatter: '{a} <br/>{b} : {c}%'

 },

 series: [

   {

     name: 'Pressure',

     type: 'gauge',

     detail: {

       formatter: '{value}'

     },

     data: [

       {

         value: 50,

         name: 'SCORE'

       }

     ]

   }

 ]

};

option && myChart.setOption(option);

3.3.2 AntV_G2和AntV_G2Plot

选择AntV_G2和AntV_G2Plot需要输入完整代码,可以参考官网文档说明,格式如下:

js8

基础条形图示例代码:

js23_zoom85

import { Bar } from '@antv/g2plot';

const data = [

 { year: '1951 年', value: 38 },

 { year: '1952 年', value: 52 },

 { year: '1956 年', value: 61 },

 { year: '1957 年', value: 145 },

 { year: '1958 年', value: 48 },

];

const bar = new Bar('container', {

 data,

 xField: 'value',

 yField: 'year',

 seriesField: 'year',

 legend: {

   position: 'top-left',

 },

});

bar.render();

3.3.3 AntV_G6

选择AntV_G6需要输入完整代码,可以参考官网文档说明,格式如下:

js9

自定义边示例代码:

js24_zoom85

import G6 from '@antv/g6';

G6.registerEdge(

'line-arrow',

{

getPath(points) {

const startPoint = points[0];

const endPoint = points[1];

return [

['M', startPoint.x, startPoint.y],

['L', endPoint.x / 3 + (2 / 3) * startPoint.x, startPoint.y],

['L', endPoint.x / 3 + (2 / 3) * startPoint.x, endPoint.y],

['L', endPoint.x, endPoint.y],

];

},

getShapeStyle(cfg) {

const startPoint = cfg.startPoint;

const endPoint = cfg.endPoint;

const controlPoints = this.getControlPoints(cfg);

let points = [startPoint]; // the start point

if (controlPoints) {

points = points.concat(controlPoints);

}

points.push(endPoint);

const path = this.getPath(points);

const style = Object.assign(

{},

G6.Global.defaultEdge.style,

{

stroke: '#BBB',

lineWidth: 1,

path,

},

cfg.style,

);

return style;

},

},

'line',

);

const data = {

nodes: [

{

id: '7',

x: 150,

y: 100,

size: 40,

anchorPoints: [

[1, 0.5],

[1, 0],

],

},

{

id: '8',

x: 300,

y: 200,

size: 40,

anchorPoints: [

[0, 0.5],

[0, 1],

],

},

],

edges: [

{

source: '7',

target: '8',

sourceAnchor: 0,

targetAnchor: 0,

},

],

};

const container = document.getElementById($container);

const width = container.scrollWidth;

const height = container.scrollHeight || 500;

const graph = new G6.Graph({

container: $container,

width,

height,

fitCenter: true,

modes: {

default: ['drag-node', 'drag-canvas'],

},

defaultNode: {

type: 'circle',

style: {

fill: '#DEE9FF',

stroke: '#5B8FF9',

},

linkPoints: {

left: true,

right: true,

fill: '#fff',

stroke: '#1890FF',

size: 3,

},

},

defaultEdge: {

type: 'line-arrow',

style: {

stroke: '#F6BD16',

startArrow: {

path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',

fill: '#F6BD16',

},

endArrow: {

path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',

fill: '#F6BD16',

},

},

},

});

graph.data(data);

graph.render();

 

3.4 如何替换数据

我们可以在代码中直接引用绑定的Data,绑定数据列后,Data区域的数据格式参考上面的示例图;针对不同的图表,所需数据格式有所不同,您需要将格式转换为目标格式后使用。

1)Echart库引用方法:

直接引用列

当原始数据为data:[]格式时,如下

js32_zoom50

可以修改data部分为data:options.column1,例如我们绑定了产品种类、利润两列,要用来绘制基础柱状图,代码如下:

js11_zoom77

转换为键值对

Echarts里面部分图表示例的数据格式是键值对,漏斗图所需数据格式如下:

data: [

       { value: 60, name: 'Visit' },

       { value: 40, name: 'Inquiry' },

       { value: 20, name: 'Order' },

       { value: 80, name: 'Click' },

       { value: 100, name: 'Show' }

     ]

js25_zoom85

假设依次绑定了数据列“产品种类”“销量”,需要将数据处理成键值对的格式以实现数据引用,转换格式方法:

options.data.map(i => ({value: i.column1, name: i.column2}))

引用数据后效果:

js26_zoom81

转换为坐标点

绘制热力图时使用到的数据包含坐标点,格式如下:

js27_zoom51

假设我们想对不同省份、市场的总成本做热力渲染,可以依次绑定这3列数据,在产品中数据结构如下:

js28_zoom80

我们需要根据绑定的两个维度值自动生成坐标点,转换格式方法:

// 每个色块值是唯一的,指定数据列时需要去重

const hours = [...new Set(options.column1)];

const days = [...new Set(options.column2)];

//基于维度列将度量列转换成[0,0,1]格式的数据

const chartData = [];

hours.forEach((h, x) => {

options.column2.forEach((d, y) => {

const item = options.data.find(i => i.column1 == h && i.column2 == d);

item && chartData.push([x, y, item.column3]);

});

});

绘制效果:

js29_zoom85

完整代码:

const hours = [...new Set(options.column1)];

const days = [...new Set(options.column2)];

// 每个色块值是唯一的,指定数据列时需要去重

const chartData = [];

hours.forEach((h, x) => {

options.column2.forEach((d, y) => {

const item = options.data.find(i => i.column1 == h && i.column2 == d);

item && chartData.push([x, y, item.column3]);

});

});

option = {

tooltip: {

position: 'top'

},

grid: {

height: '70%',

top: '10%',

left:'15%',

},

xAxis: {

type: 'category',

data: hours,

splitArea: {

show: true

}

},

yAxis: {

type: 'category',

data: days,

splitArea: {

show: true

}

},

visualMap: {

min: 0,

max: 50000,

calculable: false,

orient: 'horizontal',

left: 'center',

bottom: 10

},

series: [

{

name: 'Punch Card',

type: 'heatmap',

data: chartData,

label: {

show: true

},

emphasis: {

itemStyle: {

shadowBlur:10,

shadowColor: 'rgba(0, 0, 0, 0.5)'

}

}

}

]

};

转换为二维数组

Echarts里面绘制多个度量的柱状图时,通常将数据设置在dataset中,原始格式如下:

dataset: {

   // 提供一份数据。

   source: [

     ['Matcha Latte', 43.3, 85.8, 93.7],

     ['Milk Tea', 83.1, 73.4, 55.1],

     ['Cheese Cocoa', 86.4, 65.2, 82.5],

     ['Walnut Brownie', 72.4, 53.9, 39.1]

   ]

 },

数据一共包含一个维度列、三个度量列;

转换格式方法:

先在option前面添加

const source = options.data.map(o => {return Object.values(o);});

然后把source部分改为

source: [ [ "省份","总成本","销售额","利润" ],...source]//前面依次为绑定的四列数据

绘制效果:

js30

完整代码:

//请先依次绑定一个维度、三个度量列

const source = options.data.map(o => {

return Object.values(o);

});

option = {

legend: {},

tooltip: {},

dataset: {

// 提供一份数据。

source: [ [ "省份","总成本","销售额","利润" ],...source]

},

xAxis: { type: 'category' },

yAxis: {},

series: [{ type: 'bar' }, { type: 'bar' }, { type: 'bar' }]

};

2)AntV_G2、AntV_G2Plot、AntV_G6库数据引用方法:

常见的数据格式如下:

const columnPlot = new Column('container', {

 data,

 xField: 'type',

 yField: 'sales',

 label: {

   // 可手动配置 label 数据标签位置

   position: 'middle', // 'top', 'bottom', 'middle',

   // 配置样式

   style: {

     fill: '#FFFFFF',

     opacity: 0.6,

   },

 },

直接修改data部分为data:options.data,对应轴绑定为'column1'、'column2'......

绘制效果:

js12_zoom79

完整代码:

//请先依次绑定一个维度、一个度量

import { Column } from '@antv/g2plot';

const columnPlot = new Column($container, {

data:options.data,

xField: 'column1',

yField: 'column2',

label: {

// 可手动配置 label 数据标签位置

position: 'middle', // 'top', 'bottom', 'middle',

// 配置样式

style: {

fill: '#FFFFFF',

opacity: 0.6,

},

},

xAxis: {

label: {

autoHide: true,

autoRotate: false,

},

},

meta: {

type: {

alias: '类别',

},

sales: {

alias: '销售额',

},

},

});

columnPlot.render();

其余数据格式的转换方式参考Echarts的示例这里不再赘述。

注意:

为了保证图表正常在报告画布中,保存时会自动替换DOMid为变量$container,代码编辑时这'container'为$container两种写法都支持,保存后如下:

js13

除了引用数据外,您也可以在JS中引用图片文件,常见的方法包括以下几种:

若图片存放在本地服务器上,可以使用'image://' + '网络地址'实现引用;

例如:

将柱状图的柱子设置为本地图片样式,引用后执行效果如下图:

js17_zoom79

用同样的方法可以引用其它网络图片,后面改成对应网络图片地址即可。

若图片不在服务器上,您可以先将图片转base64编码,使用'image://' + '图片路径base64'引用;

例如:

将本地茶杯图片转base64后作为标记样式,如下图:

js18_zoom79

您也可以通过 'path://' 将图标设置为任意的矢量路径,路径图形会自适应调整为合适的大小,图片矢量路径可以从 Adobe Illustrator 等工具编辑导出。

例如:

通过矢量路径引入一个图片作为标记样式,如下图:

js19_zoom80

3.5 自定义样式

您可以在代码编辑区内自定义图表样式,包括标题、图例、坐标系、缩放、提示等。

3.6 chart库版本说明

在预览区域顶部,会显示当前运行的chart库版本,低版本有时会绘制失败,您可以下载最新的jar包,前往永洪安装目录\bihome\plugins\lib进行替换;

js14

4. 扩展库引用

第三方库支持下载部署到产品中引用,有的库也支持在线直接引用。

4.1 本地部署

本地部署第三方库,需要下载对应的jar包,放到永洪安装目录\bihome\plugins\lib下,在代码内添加引用。

antV_G2的引用库下载地址:https://unpkg.com/@antv/g2@4.2.2/dist/g2.min.js

引用其他库请到对应官网下载。

示例:

1)将下载好的g2.min.js直接放到安装目录\bihome\plugins\lib下:

js20

2)引用自定义库

自定义的库需要在js代码最前面添加引用。

options.loadDepends(["g2.min.js"],false);//第一个参数为您放到lib下的js文件名,false代表引用本地库

import { Chart } from '@antv/G2'; //注意这里的G2为大写,和引用的js文件里面保持一致

绘图效果:

js21_zoom83

您在antV_G2的官网上看到好看的图表示例,可以复制相关代码,通过该方法引用本地库快速进行绘制。

4.2 在线引用

如果您不想新增引用库到本地,也可以通过URL引用在线库;

示例:

引用在线的antV_G2,直接在js代码最前面添加引用:

options.loadDepends(["https://gw.alipayobjects.com/os/lib/antv/g2/4.0.9/dist/g2.min.js"], true);

import { Chart } from '@antv/G2';

绘制效果:

js31_zoom83

说明:

引用在线库时需要保证网络连接正常,否则会绘制失败。

不同库的引用地址请前往对应官网查看。

5. 图表的其他设置

5.1 图表组件的的通用操作与设置

具体参考下表中的参考文档。

设置内容

参考文档

组件绑定字段、移除字段

绑定字段、移除字段

替换组件数据集

替换数据集

查看与设置组件层级关系

组件层级

组件全屏模式下编辑

组件全屏

设置组件格式

格式

设置图表标题

图表元素-标题

5.2 图表组件的数据处理与分析

具体参考下表中的参考文档。

设置内容

参考文档

对绑定的维度字段进行排序

数据处理与分析- 排序

设置图表过滤

数据处理分析-过滤汇总过滤

对绑定的度量字段进行计算

数据处理与分析-同环比动态计算

设置图表的高亮、超链接、预警

数据处理与分析-预警

查看图表数据

数据处理分析-查看数据

5.3 永洪全局函数与图表组件的脚本、函数

具体参考下表中的参考文档。

设置内容

参考文档

永洪脚本的全局函数

永洪脚本的全局函数-基本函数日期时间函数财务函数文本函数数学函数逻辑函数统计函数聚合函数对象自定义全局函数

组件级别的脚本

组件级别的脚本

组件通用函数

组件级别的函数-通用

图表组件的函数

组件级别的函数-图表

6. 常见问题

请尽量使用Chrome、火狐浏览器,IE浏览器可能会由于兼容问题导致绘制失败。

由于Echarts存在新旧两个版本,部分新版本的代码写法在IE浏览器会绘制失败,如果您在Chrome、火狐浏览器能够正常绘制,IE浏览器中绘制失败,请调整代码写法。

如需将图表导出为图片、CSV等,请使用组件自带的导出功能,不要在JS代码中单独定义,否则可能会导致白屏,例如下图:

js15_zoom75

如需导出,请使用组件自带的导出功能,如下图:

js16_zoom70

数据资源引用时,可能会出现跨域的情况,Echarts官网示例中常使用ROOT_PATH+相对路径来引用数据,比如引用json:$.getJSON(ROOT_PATH + '/data/asset/data/life-expectancy-table.json'),由于Echarts的限制,您需要先将json数据文件下载到本地,放到安装目录\bihome下面,引用方式: $.getJSON('?proc=2&resource=life-expectancy-table.json'),如果放在了其他文件夹,以bihome为根目录把resource后面的路径改为相对路径即可。