# 二次绘制

创建实例后,实例的canvas属性、ctx属性分别对应canvas实例的canvas及其画布context,因此可通过画布以及开放的数据方法进行再次绘制(装饰绘制),以满足特殊定制化的需求

main

注:小程序端需要调用ctx.draw(true) (opens new window)方法才能绘制。

# 开放数据集

如果将FundCharts的实例打印出来,可以看到如下的实例字段:
FundCharts instance

这些开放的字段便是进行二次绘制的主要参数来源,下面是字段的相关说明:

字段 格式 说明
$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();

效果如:
pie chart weapp demo

# 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();

效果如:
radar chart web demo

# 配置参数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();

效果如:
line chart web demo

# 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();

效果如:
scatter chart web demo

# 配置参数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();

效果如:
line chart web demo

其他图形的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)