一图胜千言,相信很多开发者都没有绕开过图表制作这个坑,在小程序中也是,当然可以用第三方echart等制图插件来做,但小程序要求代码量最大12M,还得分好几个包,一个echart插件就将近1M,要是只做一张表或几张表实在浪费,况且小程序的加载速度与程序包大小也是息息相关的。因此写这系列文章,目的是降低程序包大小,又能实现需要的图表。
canvas实现柱状图
为什么要使用canvas呢?直接用view控制高度不是也可以吗?
可以,只是一般涉及到图表的功能都会涉及到导出功能,使用canvas更方便导出,同时canvas在绘制上更加灵活,用view布局更容易写死。
先上效果图:

体验路径:

实现思路:
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比较熟悉的话,这都不是事。
版权声明:本文为WeiHan_Seven原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。