# 二次绘制
创建实例后,实例的canvas属性、ctx属性分别对应canvas实例的canvas及其画布context,因此可通过画布以及开放的数据方法进行再次绘制(装饰绘制),以满足特殊定制化的需求。
注:小程序端需要调用ctx.draw(true) (opens new window)方法才能绘制。
# 开放数据集
如果将FundCharts的实例打印出来,可以看到如下的实例字段:
这些开放的字段便是进行二次绘制的主要参数来源,下面是字段的相关说明:
字段 | 格式 | 说明 |
---|---|---|
$el | DOM Object | 实例附属的DOM元素(容器)/canvas元素 |
canvas | Object | 实例对应的canvas |
ctx | Object | 实例对应的canvas二维画布(canvas.getContent('2d') ) |
dataset(0.9.1起废弃 )/datasets | Array | 数据点坐标集 |
drawer | Object | 画图核心数据集,包含主要坐标以及换算公式,详细见下表instance.drawer |
opts | Object | 实例的实际配置参数 |
pixelRatio | Number | 屏幕像素比 |
_chart | Object | 包含画布宽高属性width/height |
barWidth | Number | (柱状图bar)柱形宽度 |
side | Number | (雷达图radar)边数 |
rangeMax | Number | (雷达图radar)最大数值 |
# instance.drawer —— line/scatter/kline
在折线图、K线图和散点图中,各单位点在画布上的位置计算来源于下列换算公式。轴数值坐标换算公式,假设数值分别为indexX
(xaxis的索引)/numberY
(对应的data值):
- 坐标
x = xRate * indexX + xBasic
- 坐标
y = yRate * numberY + yBasic
字段 | 格式 | 说明 |
---|---|---|
chartjs | Object | 指向本实例 |
xBasic | Number | x轴换算公式的基础值 |
xRate | Number | x轴换算公式的导数 |
xaxis | Object | x轴数值参数:max 最高索引,min 最小索引,range 跨度范围,unit 单位间隔 |
yBasic | Number | y轴换算公式的基础值 |
yRate | Number | y轴换算公式的导数 |
yaxis | Object | y轴数值参数:max 数字最高值,min 数值最小值,range 跨度范围,unit 单位间隔 |
# instance.drawer —— bar
在柱状图中,各柱状图终点位置可计算可位置计算来源于下列公式。轴数值坐标换算公式,假设数值分别为indexX
(xaxis的索引)/numberY
(对应的data值):
- 坐标
x = xRate * indexX + xBasic
- 坐标
y = yRate * numberY + yBasic
- 基准值:
zeroY
字段 | 格式 | 说明 |
---|---|---|
chartjs | Object | 指向本实例 |
xBasic | Number | x轴换算公式的基础值 |
xRate | Number | x轴换算公式的导数 |
xaxis | Object | x轴数值参数:max 最高索引,min 最小索引,range 跨度范围,unit 单位间隔 |
yBasic | Number | y轴换算公式的基础值 |
yRate | Number | y轴换算公式的导数 |
yaxis | Object | y轴数值参数:max 数字最高值,min 数值最小值,range 跨度范围,unit 单位间隔 |
zeroY | Number | 零刻度线的y坐标 |
# instance.drawer - pie
饼图/环形图较为简单
字段 | 格式 | 说明 |
---|---|---|
centerArr(0.9.1起新增 ) | Number[] | 饼图各区域中心点角度 |
origin | Object | 圆心坐标:x横坐标,y纵坐标 |
radius | Number | 环形/饼图半径 |
radiusWhite | Number | 环形空白区域半径 |
# instance.drawer - radar
雷达图边角坐标位置的计算
- 坐标
x = origin.x + rangeMax * radius * sideArrItem.x
- 坐标
y = origin.y - rangeMax * radius * sideArrItem.y
字段 | 格式 | 说明 |
---|---|---|
origin | Object | 中心坐标:x横坐标,y纵坐标 |
radius | Number | 环形/饼图半径 |
sideArr | Array | 对应中心坐标集合 |
# 配置参数onAnimation/onFinish
为保证二次绘制与原图形动画保持同步,FundCharts开出了onAnimation
以及onFinish
配置字段,分别在动画过程中以及动画完成时切入执行。
# options.onAnimation(process)
动画执行时回调函数。传入参数process
为动画执行率(0~1)。
使用如
// for example: pie chart weapp
const testpie = new pie({
id: 'pie',
datas: [0.5, 0.2, 0.2, 0.1],
onAnimation (process) { // 跟随动画绘制
let ctx = testpie.ctx;
ctx.fillStyle = '#fff';
ctx.font = 'bold 22px consolas';
ctx.textAlign = 'center';
ctx.fillText('FundChart', 100, 90);
ctx.fillText((process * 100).toFixed(2) + '%', 100, 120);
ctx.draw(true); // weapp
}
});
testpie.init();
效果如:
# options.onFinish()
动画结束后回调函数。
使用如
// for example: radar chart web
const testradar = new RadarChart({
id: 'radar1',
colors: ['#009966'],
radius: 70, // 半径
origin: { // 中心
x: 120,
y: 100
},
data: [1, 2, 3, 4, 3.5],
onFinish () {
let tits = ['吃', '喝', '住', '睡', '玩'];
let ctx = testradar.ctx;
ctx.lineWidth = 1;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = '$12px Arial';
ctx.fillStyle = '#000';
testradar.drawer.sideArr.map((item, index) => {
ctx.fillText(
tits[index],
testradar.drawer.origin.x + item.x * testradar.drawer.radius * 1.2,
testradar.drawer.origin.y + item.y * testradar.drawer.radius * 1.2
);
});
}
});
testradar.init();
效果如:
# 配置参数handleTextX/handleTextY
为自定义控制x轴文案以及y轴坐标文案的绘制,FundCharts给表列类型的图表(line/bar/scatter/kline)开出了handleTextX
以及handleTextY
配置字段方法。
# options.handleTextX(func(ctx, xaxis))
控制x轴文案的显示,其中func
为回调函数,传参为实例画布ctx
,x轴数据集xaxis
;
使用如
// for example: line chart web
const testline = new LineChart({
id: 'line1',
xaxis: ['03-11', '04-11', '05-11', '06-11', '07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
data: [4, 3, 4, 2, 1, 2, 3, 4, 3.5, 3, 4],
handleTextX: (ctx, xArr) => { // 处理x轴文字
// 增加x轴刻度
let _chartWidth = testline._chart.width - testline.opts.chartLeft - testline.opts.chartRight;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = '10px Arial';
ctx.fillStyle = '#333';
for (let i in xArr) {
ctx.fillText(xArr[i], (_chartWidth / (xArr.length - 1) * i) + testline.opts.chartLeft, testline._chart.height - 13);
}
}
});
testline.init();
效果如:
# options.handleTextY(func(ctx, yaxis))
控制y轴文案的显示,其中func
为回调函数,传参为实例画布ctx
,y轴数据集yaxis
(min、max、unit);
使用如
// for example: scatter chart web
// 模拟数据
let _arr1 = [],
_arr2 = [],
_arr3 = [];
for (let i = 0; i < 60; i++) {
if (i % 3 === 0) _arr1.push([Math.random() * 100, Math.random() * 100]);
if (i % 2 === 0) _arr2.push([Math.random() * 80 + 5, Math.random() * 80 + 5]);
_arr3.push([Math.random() * 50, Math.random() * 50]);
}
// 使用
const testscatter = new ScatterChart({
id: 'scatter3',
datas: [
_arr1,
_arr2,
_arr3
],
range: {
x: [0, 120],
y: [0, 200]
},
noPointSide: true, // 无描边
chartLeft: 25,
chartRight: 1,
backgroundColor: '#000',
colors: ['#00f', '#0f0', '#f00'],
pointWidths: [2, 2, 2],
noDash: true,
handleTextY: (ctx, yaxis) => {
console.log(yaxis);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = '10px Arial';
ctx.fillStyle = '#fff';
ctx.fillText(yaxis.min.toFixed(0), 10, testscatter._chart.height - 30);
ctx.fillText(yaxis.max.toFixed(0), 10, testscatter.opts.chartTop + 10);
ctx.fillText(((yaxis.max + yaxis.min) / 2).toFixed(0), 10, (testscatter._chart.height - testscatter.opts.chartTop) / 2 - 10);
}
});
testscatter.init();
效果如:
# 配置参数hover
折线图,柱状图、k线图、饼图/环形图、雷达图自
0.9.1
版本起支持option.hover
配置交互反馈。
为帮助处理触控事件时的图形反馈,FundCharts开出了hover
配置字段,具体参数可见对应图表配置文档。
如折线图line,它的回调函数接受以下几个参数:
- 第一个参数为索引,Number;
- 第二个参数为对应数值集合,Array;
- 第三个参数为x轴标签值,String;
- 第四个参数为触控点的水平x坐标,Number
- 第五个参数为触控点的水平x坐标,Number
通过以上参数便可以绘制tooltip,可以通过数据回调在节点中进行处理和展示,如
// for example: line chart web
const testline = new LineChart({
id: 'line2',
xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
datas: [
[6, 2, 3, 4, 3.5, 3, 4],
[4, 3, 4, 2, 3, 5, 6]
],
hover(index, values, xaxis, _x) {
console.log(values[0], xaxis);
/** 自定义添加label */
// rect
let ctx = testline.ctx;
ctx.fillStyle = '#9d9d9d';
let _rectX = _x - 32;
_rectX = _rectX < 50 ? 50 : _rectX > 300 ? 300 : _rectX;
ctx.fillRect(_rectX, 26, 64, 15);
// text
ctx.fillStyle = '#fff';
ctx.font = '10px Arial';
ctx.textAlign = 'center';
ctx.fillText(xaxis + ':' + values, _rectX + 32, 35);
ctx.closePath();
ctx.stroke();
ctx.draw(true); // for weapp
}
});
testline.init();
效果如:
其他图形的hover
回调传参内容可见对应图形配置>>
# 模拟hover效果
除了通过交互控制hover效果外,我们可以通过直接调用实例的drawer.drawHover(x坐标, y坐标)
模拟触发hover效果,如
// 上例的折线demo
testline.drawer.drawHover(100, 100);
# 实现图形合并
v0.9.3起支持折线图line和K线图kline的图形合并,折线图line和柱状图bar的图形合并。
合并思路:
- 1.在第一张图表chart1初始化(init)完成时或在chart1配置项的onAnimation/onFinish切片中注册第二张图表chart2。
- 2.配置chart2参数,注意chartLeft/chartTop/range的控制。
- 3.进行手动绘制,其中DOM节点($el)绑定为chart1.$el,画布canvas/ctx分别绑定为chart1.canvas/chart2.ctx。
- 4.调用坐标计算函数chart2.setDataset(),完成坐标的计算与存储。
- 5.调用绘制函数,如折线chart2.drawLine()。
例:柱状图与折线图合并
let _xaxis = ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'];
let bardata = [1, 2, 3, 4, 3.5, 3, 4];
const chart1 = new BarChart({ // bar chart
id: 'bar1',
grid: {
showGrid: true
},
xaxis: _xaxis,
chartTop: 10,
chartLeft: 30,
chartRight: 10,
data: bardata,
events: [],
onFinish () {
let drawer = chart1.drawer,
yaxis = drawer.yaxis;
let _chart2 = new LineChart({ // line chart
id: 'kline1Canvas',
xaxis: _xaxis,
chartLeft: 55,
chartRight: 40,
chartTop: 10,
noGradient: true,
noAnimation: true,
range: {
min: yaxis.min,
max: yaxis.max
},
data: bardata,
colors: ['#71b7f9']
});
_chart2.init(true)
_chart2._chart = chart1._chart;
_chart2.$el = chart1.$el;
_chart2.canvas = chart1.canvas;
_chart2.ctx = chart1.ctx;
_chart2.drawer.setDataset();
_chart2.drawer.drawLine();
chart1._chart2 = _chart2;
}
});
chart1.init();
# 常见绘制
# 图形
- 1.line取消默认面积图效果:config.noGradient为true。
- 2.line设置为全部面积图效果:config.allGradient为true。
- 3.line折线留白,如定时追加数据场景:数据项留空,如
[1, 2, 3, , , ,]
。 - 4.line/bar绘制每个数据点:实例的datasets即各数据点坐标集,通过实例的画布ctx及坐标集进行绘制,可在onAnimation/onFinish生命周期或init后执行。
- 5.line绘制曲线:config.curveLine为true。
- 6.bar单数据用多颜色区分:config.singleColorful为true。
- 7.pie展示为饼图、扇形图:设置实心效果config.annularRate为false,设置widthRates为各区域半径比例。
- 8.radar背景用颜色区间替代网格:设置背景颜色config.fillGrid。
- 9.kline设置up空心展示:config.upHollow为true。
- 10.重置图形界面,如清除效果展示效果:调用实例的update()方法,不传参数。 ...
# 交互
- 1.line/kline实现水平拖拽交互展示效果:容器绑定touchmove事件并控制update数据的取值区间。
- 2.模拟(触发)交互事件效果:调用实例的drawer.drawHover(x坐标,y坐标)方法。
- 3.处理PC端鼠标交互:config.events为鼠标事件,如
['mousemove']
。 ...
部分常见tooltip的绘制可见demo (opens new window)。
← 交互提示ToolTips 小程序端 →