效果图:
实现思路:
1、通过展示数据计算需要画几根柱子;
2、通过组件宽度、高度计算出每根柱子的宽度及高度;
3、for循环依次绘制每根柱子;
4、绘制柱子时,先绘制顶部百分比、value值,再绘制柱子,再绘制底部标题;
5、文字需要居中,可绘制前丈量文字宽度再确定起始坐标。
<template><view class="container"><canvas canvas-id="columnarCanvas" id="columnarCanvas" style="width:750rpx; height:500rpx; margin-top:20px;" ></canvas><canvas canvas-id="testCanvas" style="width:750rpx; height:400rpx; background-color: #f8f8f8;"></canvas></view>
</template><script>export default {data() {return {canvasInfo: { },dataList: [{title: "玛莎拉蒂",value: 2}, {title: "奥迪",value: 8}, {title: "奔驰",value: 9}, { title: "奔奔",value: 6}, {title: "保时捷",value: 4}, {title: "宝马",value: 7}, {title: "凯迪拉克",value: 3}]}},onReady() {this.getCanvasInfo()this.drawTest()},methods: {/** 获取节点信息,动态得到组件的宽度,高度 **/getCanvasInfo() {var view = uni.createSelectorQuery().in(this).select("#columnarCanvas"); view.fields({ size: true, rect: true }, res => {// console.log("得到节点信息" + JSON.stringify(res))var canvasInfo = {}canvasInfo.width = res.widthcanvasInfo.height = res.heightthis.canvasInfo = canvasInfo// 调用方法画图this.drawColumnar()}).exec();},/** 画图 **/drawColumnar() {const ctxColumnar = uni.createCanvasContext("columnarCanvas")var dataList = this.dataListvar canvasInfo = this.canvasInfovar columnarNum = dataList.lengthvar columnarWidth = (canvasInfo.width - 30) / (2 * columnarNum + 1)// console.log("宽度", columnarWidth)var maxColumnarHeight = canvasInfo.height - 60 - 20var maxColumnarValue = 0var totalValue = 0for (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) + 10ctxColumnar.setFillStyle('#2b2b2b')var percentWidth = ctxColumnar.measureText(percent)ctxColumnar.fillText(percent, dx + columnarWidth / 2 - percentWidth.width / 2, dy)// ctxColumnar.setFillStyle('rgb(99, 112, 210)')ctxColumnar.setFillStyle(this.randomColor(i)) //指定每条柱子不同颜色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()},/**随机指定颜色**/randomColor(index) {let colorList = ["#63b2ee","#76da91","#f8cb7f","#7cd6cf","#f89588","#9192ab","#efa666","#7898e1","#eddd86","#9987ce","#76da91","#63b2ee"]// let index = Math.floor(Math.random() * colorList.length)return colorList[index]},/**画图测试**/drawTest() {const ctx = uni.createCanvasContext('testCanvas')let dataList = this.dataListlet x = 20, y = 0, w = 40, h = 20for (var i = 0; i < dataList.length; i++) {// 矩形ctx.fillStyle = this.randomColor(i)ctx.fillRect(x, y, w, h) // x,y,w,h// 设置字体样式ctx.font = 'bold 10px Arial'// 设置文本颜色ctx.fillStyle = this.randomColor(i)// 文本ctx.fillText(dataList[i].title, x+w+10, y+15)// 每行偏离距离y = y + 25}// 线条ctx.beginPath()ctx.moveTo(1, 1) //起点坐标ctx.lineTo(400, 1) //终点坐标ctx.stroke()// 进行绘制ctx.draw()}}}
</script><style></style>