效果图:
实现思路:
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.width
canvasInfo.height = res.height
this.canvasInfo = canvasInfo
// 调用方法画图
this.drawColumnar()
}).exec();
},
/** 画图 **/
drawColumnar() {
const ctxColumnar = uni.createCanvasContext("columnarCanvas")
var dataList = this.dataList
var canvasInfo = this.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)')
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.dataList
let x = 20, y = 0, w = 40, h = 20
for (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>