<< Click to Display Table of Contents >> 自定义绘图复制链接 |
1. 概述
1.1 应用场景
产品内置的图表类型和样式虽然丰富,但在某些特定场景或样式需求下可能无法满足用户的全部要求。自定义绘图组件的引入,正是为了填补这一空白,使得用户能够根据自己的需求进行图表的定制。
1.2 功能简介
自定义绘图组件支持用户通过编写JS代码,直接调用内置的Echarts、AntV_G2、AntV_G2Plot、AntV_G6等图表库,实现图表的完全自定义绘制。用户可以自由配置图表样式、布局、交互等属性,打造独一无二的视觉化效果。
2. 应用举例
用户在制作报告时,需要做一个各产品种类销售额的环形图。产品自带的图表样式无法满足可视化需求,在Echarts中找到了对应的图表样式。如下图,
这个时候就可以使用自定义绘图功能,详细操作步骤如下,
1)新建自定义绘图组件:从右侧【组件】区域拖拽自定义绘图组件到画布中。
2)给组件绑定数据:从数据列表中拖拽所需的数据列(产品种类、销售额)到数据绑定区,数据列会按照绑定顺序依次定义为column1、column2等,并显示在Data区域。
3)点击Echarts图表,复制JS代码。
4)点击数据绑定区的“自定义JS代码”,进入代码编辑区。选择Echarts库,代码格式选择“option”。
5)粘贴复制的JS代码,并替换数据,即data部分。这里需要将数据转换为特定的数组或键值对格式。如下图,
原始代码:
替换为:
data: options.data.map(o => ({value: o.column2, name: o.column1}))
6)执行与预览:编写完JS代码后,点击代码编辑区右上角的“执行”按钮,系统会在右侧预览区域绘制图表。若代码存在错误,会给出相应的提示信息。
7)点击“确定”,再点击“保存”报告即可。
3. 功能说明
自定义绘图组件支持多种图表库,包括 Echarts、AntV_G2、 AntV_G2Plot、AntV_G6,您可以直接调用代码库,相关代码的配置属性以及图表示例请前往官网查看。
•Echarts:支持丰富的图表类型和高度可定制的样式,适用于大多数基础图表和复杂图表的绘制。
•AntV_G2:一套简洁的渐进式可视化语法,用于报表搭建、数据探索以及可视化叙事。
•AntV_G2Plot:专为数据可视化设计的图表库,提供简洁易用的API和强大的数据处理能力。现已被AntV_G2替代,AntV官方不再主推。
•AntV_G6:专注于图网络的可视化,支持复杂的图结构展示和丰富的交互功能。
3.1 数据绑定说明
图表 |
数据 |
---|---|
自定义绘图 |
0个或多个 |
3.2 自定义JS代码说明
绑定完数据后,我们需要给组件自定义JS代码,以定义图表绘制规则,点击数据绑定区的“自定义JS代码”,在弹窗中进行配置:
自定义JS代码配置:
【chart库】默认可以选择Echarts、AntV_G2、AntV_G2Plot、AntV_G6,选择以后,在绘制时会直接调用对应代码库绘制图表。
【代码格式】选择完chart库后,需要选择JS代码格式,Echarts仅支持option格式,AntV_G2、AntV_G2Plot、AntV_G6仅支持完整代码,为保证正常绘图,代码格式与所选格式需保持一致。
【Data】绑定的数据列会展示在Data区域,并按照绑定的顺序依次定义为column1、column2......,可以直接在代码中引用,例如绑定了市场级别、产品种类2列数据,如下图:
【执行】输入完JS代码之后,点击代码编辑区右上角的“执行”按钮,会在右侧预览区域绘制图表,若代码存在错误会给出提示。
3.3 JS代码示例
3.3.1 Echarts
Echarts可以复制option的代码,也可以复制完整代码。
•options代码
代码示例如下图:
3D地球类图表,需要定义路径,如下图:
•完整代码
如果是复制完整代码,请不要定义chartDom变量,产品已经定义了DOMid为$container,可能会都导致无法绘制到报告画布中。因此需要去掉或者注释以下两行代码,
正确写法如下图:
或者如下:
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需要输入完整代码,可以参考官网文档说明,格式如下:
基础条形图示例代码:
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需要输入完整代码,可以参考官网文档说明,格式如下:
自定义边示例代码:
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:[]格式时,如下
可以修改data部分为data:options.column1,例如我们绑定了产品种类、利润两列,要用来绘制基础柱状图,代码如下:
•转换为键值对
Echarts里面部分图表示例的数据格式是键值对,漏斗图所需数据格式如下:
data: [
{ value: 60, name: 'Visit' },
{ value: 40, name: 'Inquiry' },
{ value: 20, name: 'Order' },
{ value: 80, name: 'Click' },
{ value: 100, name: 'Show' }
]
假设依次绑定了数据列“产品种类”“销量”,需要将数据处理成键值对的格式以实现数据引用,转换格式方法:
options.data.map(i => ({value: i.column1, name: i.column2}))
引用数据后效果:
•转换为坐标点
绘制热力图时使用到的数据包含坐标点,格式如下:
假设我们想对不同省份、市场的总成本做热力渲染,可以依次绑定这3列数据,在产品中数据结构如下:
我们需要根据绑定的两个维度值自动生成坐标点,转换格式方法:
// 每个色块值是唯一的,指定数据列时需要去重
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]);
});
});
绘制效果:
完整代码:
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]//前面依次为绑定的四列数据
绘制效果:
完整代码:
//请先依次绑定一个维度、三个度量列
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'......
绘制效果:
完整代码:
//请先依次绑定一个维度、一个度量
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两种写法都支持,保存后如下:
除了引用数据外,您也可以在JS中引用图片文件,常见的方法包括以下几种:
•若图片存放在本地服务器上,可以使用'image://' + '网络地址'实现引用;
➢例如:
将柱状图的柱子设置为本地图片样式,引用后执行效果如下图:
用同样的方法可以引用其它网络图片,后面改成对应网络图片地址即可。
•若图片不在服务器上,您可以先将图片转base64编码,使用'image://' + '图片路径base64'引用;
➢例如:
将本地茶杯图片转base64后作为标记样式,如下图:
您也可以通过 'path://' 将图标设置为任意的矢量路径,路径图形会自适应调整为合适的大小,图片矢量路径可以从 Adobe Illustrator 等工具编辑导出。
➢例如:
通过矢量路径引入一个图片作为标记样式,如下图:
3.5 自定义样式
您可以在代码编辑区内自定义图表样式,包括标题、图例、坐标系、缩放、提示等。
3.6 chart库版本说明
在预览区域顶部,会显示当前运行的chart库版本,低版本有时会绘制失败,您可以下载最新的jar包,前往永洪安装目录\bihome\plugins\lib进行替换;
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下:
2)引用自定义库
自定义的库需要在js代码最前面添加引用。
options.loadDepends(["g2.min.js"],false);//第一个参数为您放到lib下的js文件名,false代表引用本地库
import { Chart } from '@antv/G2'; //注意这里的G2为大写,和引用的js文件里面保持一致
绘图效果:
您在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';
绘制效果:
➢说明:
引用在线库时需要保证网络连接正常,否则会绘制失败。
不同库的引用地址请前往对应官网查看。
5. 图表的其他设置
5.1 图表组件的的通用操作与设置
具体参考下表中的参考文档。
设置内容 |
参考文档 |
---|---|
组件绑定字段、移除字段 |
|
替换组件数据集 |
|
查看与设置组件层级关系 |
|
组件全屏模式下编辑 |
|
设置组件格式 |
|
设置图表标题 |
图表元素-标题 |
5.2 图表组件的数据处理与分析
具体参考下表中的参考文档。
5.3 永洪全局函数与图表组件的脚本、函数
具体参考下表中的参考文档。
设置内容 |
参考文档 |
---|---|
永洪脚本的全局函数 |
永洪脚本的全局函数-基本函数、日期时间函数、财务函数、文本函数、数学函数、逻辑函数、统计函数、聚合函数、对象、自定义全局函数。 |
组件级别的脚本 |
|
组件通用函数 |
组件级别的函数-通用 |
图表组件的函数 |
组件级别的函数-图表 |
6. 常见问题
•请尽量使用Chrome、火狐浏览器,IE浏览器可能会由于兼容问题导致绘制失败。
•由于Echarts存在新旧两个版本,部分新版本的代码写法在IE浏览器会绘制失败,如果您在Chrome、火狐浏览器能够正常绘制,IE浏览器中绘制失败,请调整代码写法。
•如需将图表导出为图片、CSV等,请使用组件自带的导出功能,不要在JS代码中单独定义,否则可能会导致白屏,例如下图:
如需导出,请使用组件自带的导出功能,如下图:
•数据资源引用时,可能会出现跨域的情况,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后面的路径改为相对路径即可。