# 开始

# 引导

现在有很多成熟的可视化库,为何重复造轮子?

确实,现在可视化库丰富多样,能满足绝大多数的开发需求。但是在部分需求中存在以下几个问题:

  • 首先,在一些特殊的可视化需求中,现有的库很难满足完全定制需求,或者定制成本过高。这是FundCharts主要解决的问题。FundCharts只注重图形的实现,对于tooltip、文案等内容并不处理,前端同学可完全通过FundCharts抛出的图像实例进行自定义canvas绘制。
  • 对于小程序和服务端,现有的库无论配置文档还是实际使用体验目前都不够细致。FundCharts满足小程序和服务端与web端几乎相同的开发体验,并提供说明以及跟踪维护。
  • 仅注重图形的可视化库注定带来轻量的优点。FundCharts全量引用30k,开启gzip仅10.8k。如按需引用和打包则占用空间更小。

# 安装和使用

# 第一步,预留容器

# browser web

先准备容器节点并设置容器宽高。如:

<div id="testline" style="width: 100vw; height: 5rem">
  <!-- 图形占位 -->
</div>

v0.9.1起支持直接设置canvas标签容器,如:

<canvas id="testbar" width="375" height="200"></canvas>

# weapp

先准备canvas节点并设置宽高。如

<!-- wxml -->
<canvas
  style="width: 750rpx; height: 50vw"
  canvas-id="testline"
></canvas>

# 服务端nodejs的容器即canvas环境

nodejs服务端需安装node-canvas及其环境(https://www.npmjs.com/package/canvas (opens new window))。

const Canvas = require('canvas');

# 第二步,引用FundChartJS

*历史版本可访问FundCharts-versions (opens new window)

# 全量引用

全量引用将导入所有的图形库,使用最简单的方式就是直接引用FundCharts.min.js (opens new window),如

# browser web(FundCharts.min.js)
<div style="width: 100vw; height: 5rem">
  <!-- 图形占位 -->
</div>
<script src="./FundCharts.min.js"></script>	

使用webpack的话可通过npm安装(npm i -D fundcharts)并引用

// i need line chart
import { line } from 'fundcharts'
# weapp(FundCharts.min.js)
const FundCharts = require('./FundCharts.min.js');
// i need line chart
const LineChart = FundCharts.line;
# nodejs(FundCharts-node.js)
const FundCharts = require('./FundCharts-node.js');
// i need line chart
const LineChart = FundCharts.line;

或通过npm(npm i -D fundcharts)并引用

const { line } = require('fundcharts');

# 按需引用(web/weapp)

某些时候,不需要引入全部库,这时候可以根据需要按需引用相应图形库

// i need line chart
import line from 'fundcharts/LineChart'
// i need bar chart
import bar from 'fundcharts/BarChart'
// i need pie chart
import pie from 'fundcharts/PieChart'
// i need radar chart
import radar from 'fundcharts/RadarChart'
// i need scatter chart
import scatter from 'fundcharts/ScatterChart'
// i need k-line chart
import kline from 'fundcharts/KlineChart'

可以将常用的图表按需引用后重新打包,生成的新库可重复使用并缓存。

# 第三步,配置参数

// for example: line chart
const testline = new line({
  id: 'testline',
  xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
  data: [1, 2, 3, 4, 3.5, 3, 4]
});

# *使用ToolTips

v0.9.7版本起支持FundCharts-ToolTips (opens new window),如果是直接引用打包后的fundchart-tooltips.js,则可引用全局变量下的ToolTip,如:

const chart1 = new BarChart({
  id: 'bar1',
  xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11', '12-12'],
  data: [1, 3, 2, 3, 3.2, 4, 5],
  hover: window.FundChartsToolTips.ArrowToolTip,	// 引用ToolTip
  toolTip: {	// 配置ToolTIp
  	// ...
  }
});

chart1.init();

如果引入源码(如小程序),则可以通过require()进行引用,如:

const {
  ArrowToolTip
} = require('../js/FundCharts-ToolTips');

const chart1 = new BarChart({
  id: 'bar1',
  xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11', '12-12'],
  data: [1, 3, 2, 3, 3.2, 4, 5],
  hover: ArrowToolTip
});

chart1.init();

v0.9.10版本起支持组件引用,包含 'fundcharts/tooltips/grid'BasicToolTipArrowToolTipKlineToolTip,适用于折线/柱状图/K线图可用) 和 'fundcharts/tooltips/shape'PieCenterToolTipPieLabelToolTipLabelsToolTip,饼图/雷达图可用),注册hover事件即可(注意不要改变this指向),如React:

import { Pie } from 'fundcharts/react';
import { PieCenterToolTip } from 'fundcharts/tooltips/shape';

export function Demo () {
  return (
  <Pie
    options={{
      datas: [0.1, 0.2, 0.3, 0.4],
      toolTip: {
        showTip(index) {
          return ['吃', '喝', '玩', '乐', '代码', '书'][index];
        },
      },
    }}
    hover={PieCenterToolTip}
  />
  )
}

# 最后,图形注入

// for example: line chart
testline.init();

# React/Vue使用

v0.9.5版本起新增了React/Vue组件。

# React(v16.7+, hook)

引用:

import {
	Line,	// 折线
	Bar,	// 柱状
	Pie,	// 饼图
	Radar,	// 雷达
	Scatter,	// 散点
	Kline,	// K线
} from 'fundcharts/react'

props参数:

  • options: object,非hover事件外配置参数;
  • hover: Function, hover事件(可选)

*注意datas修改会执行FundCharts update()更新试图,所以options不要在render函数下定义。

example:

import React, { Component } from 'react';
import { Line } from 'fundcharts/react'

export default class LineShow extends Component {
  state = {
    index: '--',	// show hover index
    options: {		// chart options
      xaxis: ['1-11', '2-11', '3-11', '4-11', '5-11'],
      datas: [
        [1, 2, 3, 4, 5],
        [5, 3, 4, 2, 4]
      ]
    }
  };

  componentDidMount () {
    setTimeout(() => {
      this.setState({
        options: {
          ...this.state.options,
          datas: [
            [3, 5, 6, 4, 2],
            [3, 4, 3, 3, 5]
          ]
        }
      })
    }, 5000);
  }

  setIndex (index) {
    this.setState({
      index
    })
  }

  render() {
    const {
      options,
      index,
    } = this.state;
    return (
      <div className="m-app">
        <p>{index}</p>
          <Line
            options={options}
            hover={this.setIndex.bind(this)}
          />
        </div>
    );
  }
}

# Vue

引用:

import {
  Line,	// 折线
  Bar,	// 柱状
  Pie,	// 饼图
  Radar,	// 雷达
  Scatter,	// 散点
  Kline,	// K线
} from 'fundcharts/vue'

props参数:

  • options: object,配置参数;
<template>
  <section>
    <p class='f-tc'>{{index}}</p>
      <v-line
        prefix="aaa"
        :options="options"
      />
  </section>
</template>
<script>
import { Line } from 'fundcharts/vue';

export default {
  name: "lineshow",
  data () {
      return {
        options: {		// chart options
          datas: [
            [1, 2, 3, 4, 5],
            [4, 2, 5, 5, 1]
          ],
          xaxis: ['1-11', '2-11', '3-11', '4-11', '5-11'],
          hover: this.handleHover
        },
        index: '--',	// show hover index
      }
  },
  components: {
    'v-line': Line,
  },
  methods: {
    handleHover (index) {
      console.log(index)
      this.show = index;
    }
  },
  mounted() {
      setTimeout(() => {
        this.options = {
          ...this.options,
          datas: [
            [6, 3, 5, 3, 2],
            [4, 5, 6, 4, 3]
          ]
        }
      }, 5000);
  }
}
</script>

# TypeScript 中使用

v0.9.10版本起直接使用即可;v0.9.10以下版本需要在类型声明文件里声明 fundcharts 模块:

// golbal.t.ts

declare module 'fundcharts';

# PC端使用

如果是绘图可直接设置,与移动端无异;如果需要鼠标交互,当前各版本需要设置events事件:如['mousemove']

// for example: pc line chart
const testline = new line({
  id: 'testline',
  xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
  data: [1, 2, 3, 4, 3.5, 3, 4],
  events: ['mousemove'],
});

# 小程序使用

与 web 使用方式基本相同,区别在于如果要设置交互事件需要手动绑定,如:

<!-- wxml -->
<canvas
  style="width: 375px; height: 212px;"
  canvas-id="chart"
  bindtouchstart="chartTouchstart"
  bindtouchmove="chartTouchmove"
></canvas>
//...
    onLoad () {
      chartInit = new LineChart({
        id: 'chart',
        xaxis: ['09-11', '09-22', '10-11'],
        yaxisfunc(data) {
        return (data * 100).toFixed(2) + '%'
        },
        Ctx: ctx,
        width: 375,
        height: 212,
        xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
        data: [1, 2, 3, 4, 3.5, 3, 4]
      });

      chartInit.init();
    },
    
    // touch start
    chartTouchstart: function (e) {
      if (e) {
        let event = e.touches[0];
        chartInit.drawer.drawHover(event.x, event.y);    // 折线图的hover处理
      }
    },
    // touch move
    chartTouchmove: function (e) {
      if (e) {
        let event = e.touches[0];
      chartInit.drawer.drawHover(event.x, event.y);
    }
  },
//...

可见:《小程序端与web端处理的不同点》

# Nodejs绘制

使用fundcharts-node (opens new window),注意主要安装node-canvas (opens new window)画布。

npm package

如:

const fs = require('fs');
const path = require('path');
const Canvas = require('canvas');
const {FundCharts} = require('fundcharts-node');	// import {FundCharts} from 'fundcharts-node'

// chart 1
const chart1 = new FundCharts.line({
  id: 'line1',
  width: 750,
  height: 375,
  xaxis: ['07-11', '08-11', '09-11', '09-22', '10-11', '11-11', '12-11'],
  data: [1, 2, 3, 4, 3.5, 3, 4],
  Canvas: Canvas,
  handleOut: canvas => {
    const out = fs.createWriteStream(path.join(__dirname, './line1.jpg'));
    const stream = canvas.createJPEGStream();

    stream.on('data', function(chunk) {
      out.write(chunk);
    });
  }
});

chart1.init();

有关图形及其配置的更多内容请见下一节图形及其配置