小程序-Canvas绘制折线图

小程序-Canvas绘制折线图

自己在一个小程序项目中,希望通过绘制折线图展示不同时间的数值变化趋势,搜索了一番后没找到特别好的第三方库,故打算自己实现一个简单的绘制折线图方法,本文记录自己如何在小程序中通过canvas绘制折线图。

目标

最终目标是达到官方小程序数据助手中折线图的效果:

除了UI目标外,还要便于在小程序其他地方使用或者在其他小程序中使用,所以API要有适当的通用性。

实现

实现的思路是在页面上放置指定大小的canvas,然后调用API传递’canvas id’与配置选项完成绘制,配置选项主要用来指定绘制数据、有关颜色、绘制大小等,绘制的API可以封装到一个单独的模块中便于公用。

接口

暂时设计了4个接口:init、draw、showLine、hideLine,分别用来初始化、绘制、显示和隐藏某条线,具体API描述如下所示:

  • init(ctx: string|CanvasContext, options: object): LineChart

init,返回一个LineChart实例,可以调用LineChart原型上的三个方法,其中:

  • ctx: 'canvas id’或通过wx.createCanvasContext得到的CanvasContext对象
  • options:
{
    width: 320,                     // canvas的宽度
    height: 200,                    // canvas的高度
    labelColor: '#888888',          // label的颜色
    axisColor: '#d0d0d0',           // 轴的颜色
    xUnit: '',                      // x轴label的单位
    yUnit: '',                      // y轴label的单位
    xAxis: [1, 2, 3, 4],            // x轴label数组
    lines: [{                       // 需要绘制的线
        color: '#1296db',           // 线的颜色
        points: [10, 29, 18, 20],   // 线的y轴值
    }],                     
    margin: 20,                     // 内容与边界的距离
    fontSize: 12                    // 文字大小
}
  • LineChart.prototype.draw()

draw,按初始化给定的ctx和options绘制折线图

  • LineChart.prototype.showLine(index: number)

showLine,显示options.lines[index]中的该条线

  • LineChart.prototype.hideLine(index: number)

hideLine,隐藏options.lines[index]中的该条线

代码

完整代码移步Github,这里只描述一下自己用canvas绘制折线图的主要思路:

  • 绘制x轴与label

绘制x轴相对简单,但所有x轴label都绘制可能导致空间不一够,所以这里要依据label数量与宽度计算能够绘制的个数,然后按等步长的方式从中挑选。同时因为ctx.fillText的绘制位置是从左上角计算,为避免溢出,x轴label绘制位置在x轴方向要有适当的偏移

  • 绘制y轴label以及水平标度线

y轴label数可以根据cavans高度与希望的标度线间距计算,而每条水平标度线的取值则需要考虑options.lines在y轴的最大值。数量与取值决定后,绘制就相对容易

  • 绘制线

绘制轴与label需要收集4个信息:xOffset、yOffset、xStep、yStep,分别表示原点的偏移量(座标)和单位步长,此时线上的点:(index, value)对应到的canvas中座标为:(xOffset + index * xStep, yOffset - value * yStep),最后再使用ctx.moveTo结合ctx.lineTo将所有点连起来即可

  • 绘制线与x轴的阴影面积

将需要绘制的区域连接成一个闭合区域再使用ctx.fill填充即可,在绘制线的起点前添加其在x轴的投影点作为新起点,以及在绘制线的终点后添加其在x轴的投影点作为新终点,最后使用ctx.closePath串联起来并fill

  • 绘制空心数据点

在每个点的位置使用ctx.arc绘制

绘制效果

最后通过LineChart绘制出来的折线图效果如下:

总结

目前的折线图还差一个重要的交互功能:“根据触摸位置,显示临近点的y轴取值”,这个功能晚点补上。

博客原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章