微信小程序之图表系列——一步步用canvas实现柱状图

一图胜千言,相信很多开发者都没有绕开过图表制作这个坑,在小程序中也是,当然可以用第三方echart等制图插件来做,但小程序要求代码量最大12M,还得分好几个包,一个echart插件就将近1M,要是只做一张表或几张表实在浪费,况且小程序的加载速度与程序包大小也是息息相关的。因此写这系列文章,目的是降低程序包大小,又能实现需要的图表。

canvas实现柱状图

为什么要使用canvas呢?直接用view控制高度不是也可以吗?
可以,只是一般涉及到图表的功能都会涉及到导出功能,使用canvas更方便导出,同时canvas在绘制上更加灵活,用view布局更容易写死。

先上效果图:

微信小程序之图表系列——一步步用canvas实现柱状图_第1张图片

体验路径:

微信小程序之图表系列——一步步用canvas实现柱状图_第2张图片
实现思路:
1、通过获得的展示数据得到需要画几根柱子
2、通过相机宽度、高度计算出每根柱子的宽度及高度
3、for循环依次绘制每根柱子
4、绘制柱子时,先绘制顶部百分比、value值,再绘制柱子,再绘制底部标题
5、文字需要居中,可绘制前丈量文字宽度再确定起始坐标

代码:

js

Page({

  /**
   * 页面的初始数据
   */
  data: {
    canvasInfo:{},
    dataList: [{ title: "17岁以下", value: 0 }, { title: "18-24岁", value: 8 }, { title: "25-29岁", value: 9 }, { title: "30-39岁", value: 7 }, { title: "40-49岁", value: 3 }]
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.messureCanvas()
    
  },

  messureCanvas(){
    let query = wx.createSelectorQuery().in(this);
    // 然后逐个取出navbar和header的节点信息
    // 选择器的语法与jQuery语法相同
    query.select('#columnarCanvas').boundingClientRect();
    // 执行上面所指定的请求,结果会按照顺序存放于一个数组中,在callback的第一个参数中返回
    var that = this
    query.exec((res) => {
      // 分别取出navbar和header的高度 
      console.log(res)
      var canvasInfo = {}
      canvasInfo.width = res[0].width
      canvasInfo.height = res[0].height
      that.setData({
        canvasInfo:canvasInfo
      })
      console.log(canvasInfo)
      that.drawColumnar()
    })
  },
  drawColumnar() {
    const ctxColumnar = wx.createCanvasContext("columnarCanvas")
    var dataList = this.data.dataList
    var canvasInfo = this.data.canvasInfo
    var columnarNum = dataList.length
    var columnarWidth = (canvasInfo.width-30)/(2*columnarNum+1)
    console.log("宽度",columnarWidth)
    var maxColumnarHeight = canvasInfo.height - 60 - 20
    var maxColumnarValue = 0
    var totalValue= 0
    for (var i = 0; i < dataList.length; i++){
      if(dataList[i].value>maxColumnarValue){
        maxColumnarValue = dataList[i].value
      }
      totalValue = totalValue+dataList[i].value
    }
    for (var i = 0; i < dataList.length;i++){
      ctxColumnar.setFontSize(15)
      var percent = parseInt(dataList[i].value * 100 / totalValue) + "%"
      var dx = columnarWidth * (2 * i + 1)
      var dy = canvasInfo.height - (maxColumnarHeight * (dataList[i].value / maxColumnarValue) + 60) + 10
      ctxColumnar.setFillStyle('#2b2b2b')
      var percentWidth = ctxColumnar.measureText(percent)
      ctxColumnar.fillText(percent, dx+columnarWidth/2-percentWidth.width/2, dy)
      ctxColumnar.setFillStyle('rgb(99, 112, 210)')
      var valueWidth = ctxColumnar.measureText(dataList[i].value+"")
      ctxColumnar.fillText(dataList[i].value+"",dx+columnarWidth/2-valueWidth.width/2,dy+20)
      ctxColumnar.fillRect(dx, dy + 22, columnarWidth, maxColumnarHeight * (dataList[i].value / maxColumnarValue))
      ctxColumnar.setFillStyle('#8a8a8a')
      var titleWidth = ctxColumnar.measureText(dataList[i].title + "")
      ctxColumnar.fillText(dataList[i].title , dx+columnarWidth/2-titleWidth.width/2, canvasInfo.height-10)
    }
    ctxColumnar.draw()
  },
 
})

wxml

<view class="container">
  <canvas style="width:100%;height:250px;margin-top:20px;" canvas-id="columnarCanvas" id="columnarCanvas"></canvas>
</view>

后语:

这是最简单的一种柱状图(难道真的需要那么复杂吗?小程序数据助手里就用的这个),可以了解一下大概思路,如果对canvas比较熟悉的话,这都不是事。

你可能感兴趣的:(图表系列,微信小程序,微信小程序,数据可视化,图表系列,柱状图,canvas实现柱状图)