canvas作图系列——柱图

mac2024-05-26  34

柱图

canvas画图最主要的就是把一张图分成各个部分,然后一块一块的去进行绘制,比如柱图,在绘制的过程中就可以分成x轴,x轴的label,y轴,y轴的label,平行于x轴的分割线,以及每个柱体等等和一些细节。 柱图的x轴就是等分嘛,有几个数据就等分成几块,y轴就是先得出数据的最大值,然后看你想把这最大值均分成几份嘛,比如把1200分成4份,那y轴就是被均分成四份,每个刻度就是300

还是要强调一点,以为上面这个图片中的柱图用的是svg,所以一定要先加载图片,等图片加载完了之后再调用绘制函数

js

function DrawRect(dataArr1, dataArr2, nameArr, index) { var canvas = document.querySelector('#cav5') var cav = canvas.getContext('2d'); cav.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight); var width = canvas.clientWidth var height = canvas.clientHeight var zeroPoint = [width * 0.1, height * 0.9] //柱图图表零点坐标 var Yheight = height * 0.5 //图表高度 var Xwidth = width * 0.8 //图表宽度 var Ypoint = [zeroPoint[0], zeroPoint[1] - Yheight] //Y轴顶点坐标 var Xpoint = [zeroPoint[0] + Xwidth, zeroPoint[1]] //X轴右端坐标 var Xpatition = Xwidth * 0.95 / nameArr.length //第一个柱图的横坐标 var namePoint = [Xpatition / 2 + zeroPoint[0], zeroPoint[1] + 15] //X轴第一个label的坐标 //数据处理获取两个数组中的最大值 var max = dataArr1[0] for (let i = 0; i < dataArr1.length; i++) { if (max <= dataArr1[i]) { max = dataArr1[i] } } for (let i = 0; i < dataArr2.length; i++) { if (max <= dataArr2[i]) { max = dataArr2[i] } } var Ypatition = Yheight * 0.95 / 5 //Y轴分隔距离 var dataPoint = [zeroPoint[0] - 15, zeroPoint[1] - Ypatition / 2] //Y轴label的坐标 var YdataLabel = [] //Y轴label数组 var dataLabel = max / 5 //Y轴分割的倍数 for (let i = 0; i < 5; i++) { YdataLabel.push(dataLabel) dataLabel += max / 5 } var barWidth = 10 //柱体宽度 var linePoint = [] //柱图连线的端点坐标数组 var tipsPoint = [] //提示框的坐标数组 //Y轴 cav.beginPath() cav.moveTo(zeroPoint[0], zeroPoint[1]) cav.lineTo(Ypoint[0], Ypoint[1]) cav.strokeStyle = 'red' cav.closePath() cav.stroke() //X轴 cav.beginPath() cav.moveTo(zeroPoint[0], zeroPoint[1]) cav.lineTo(Xpoint[0], Xpoint[1]) cav.strokeStyle = 'red' cav.closePath() cav.stroke() //Y轴端点箭头 cav.beginPath() cav.moveTo(Ypoint[0], Ypoint[1]) cav.lineTo(Ypoint[0] - 3, Ypoint[1] + 3) cav.strokeStyle = 'red' cav.stroke() cav.save() cav.restore() cav.lineTo(Ypoint[0] + 3, Ypoint[1] + 3) cav.strokeStyle = 'red' cav.stroke() cav.closePath() cav.fillStyle = 'red' cav.fill() //X轴端点箭头 cav.beginPath() cav.moveTo(Xpoint[0], Xpoint[1]) cav.lineTo(Xpoint[0] - 3, Xpoint[1] - 3) cav.strokeStyle = 'red' cav.stroke() cav.save() cav.restore() cav.lineTo(Xpoint[0] - 3, Xpoint[1] + 3) cav.strokeStyle = 'red' cav.stroke() cav.closePath() cav.fillStyle = 'red' cav.fill() //Y轴文字及分割线 for (let i = 0; i < YdataLabel.length; i++) { cav.textAlign = 'end' cav.textBaseline = 'middle' cav.font = '14px' cav.fillStyle = 'red' cav.fillText(parseInt(YdataLabel[i]) + '', dataPoint[0], dataPoint[1]) cav.beginPath() cav.moveTo(zeroPoint[0], dataPoint[1]) cav.lineTo(Xpoint[0], dataPoint[1]) cav.strokeStyle = 'red' cav.closePath() cav.stroke() dataPoint[1] -= Ypatition } //高亮框 var lightHeightColor = cav.createLinearGradient(Xpatition * index + zeroPoint[0] + 15, zeroPoint[1] - Yheight, Xpatition * (index + 1) + zeroPoint[0] - 15, zeroPoint[1]); lightHeightColor.addColorStop(0, "rgba(53,103,235,1)"); lightHeightColor.addColorStop(1, 'rgba(53,103,235,0.3)'); cav.beginPath() cav.rect(Xpatition * (index) + zeroPoint[0], zeroPoint[1] - Yheight, Xpatition, Yheight) cav.fillStyle = lightHeightColor cav.fill() for (let i = 0; i < nameArr.length; i++) { //文字 cav.textAlign = 'center' cav.textBaseline = 'top' cav.font = '14px' cav.fillStyle = 'red' cav.fillText(nameArr[i], namePoint[0], namePoint[1]) //柱图 var barHeight1 = dataArr1[i] / max * 0.95 * Yheight - Ypatition / 2 var barHeight2 = dataArr2[i] / max * 0.95 * Yheight - Ypatition / 2 cav.drawImage(img, namePoint[0] - barWidth, zeroPoint[1] - barHeight1, barWidth, barHeight1) cav.drawImage(img3, namePoint[0] - barWidth, zeroPoint[1] - barHeight1 - img3.height / 2, barWidth, img3 .height) cav.drawImage(img2, namePoint[0], zeroPoint[1] - barHeight2, barWidth, barHeight2) cav.drawImage(img4, namePoint[0], zeroPoint[1] - barHeight2 - img4.height / 2, barWidth, img4.height) linePoint.push({ startX: namePoint[0] - barWidth / 2, startY: zeroPoint[1] - barHeight1, endX: namePoint[0] + barWidth / 2, endY: zeroPoint[1] - barHeight2 }) namePoint[0] += Xpatition } //连线 cav.beginPath() cav.setLineDash([2]); cav.strokeStyle = "#fff" cav.moveTo(linePoint[index].startX, linePoint[index].startY) cav.lineTo(linePoint[index].endX, linePoint[index].endY) cav.closePath() cav.stroke() //连线端点圆点 cav.beginPath() cav.arc(linePoint[index].startX, linePoint[index].startY, 2, 0, Math.PI * 2, false) cav.fillStyle = '#fff' cav.closePath() cav.fill() cav.beginPath() cav.arc(linePoint[index].endX, linePoint[index].endY, 2, 0, Math.PI * 2, false) cav.fillStyle = '#fff' cav.closePath() cav.fill() //文字框 if (dataArr1[index] > dataArr2[index]) { if(index==dataArr2.length-1) { tipsPoint[0] = linePoint[index].startX-tipsImg.width }else { tipsPoint[0] = linePoint[index].startX } tipsPoint[1] = linePoint[index].startY - tipsImg.height } else { if(index==dataArr2.length-1) { tipsPoint[0] = linePoint[index].endX-tipsImg.width }else { tipsPoint[0] = linePoint[index].endX } tipsPoint[1] = linePoint[index].endY - tipsImg.height } cav.drawImage(tipsImg, tipsPoint[0], tipsPoint[1]) cav.textAlign = 'start' cav.textBaseline = 'middle' cav.font = '14px' cav.fillStyle = 'red' cav.fillText('独立用户', tipsPoint[0] + 10, tipsPoint[1] + tipsImg.height / 3) cav.textAlign = 'right' cav.textBaseline = 'middle' cav.font = '14px' cav.fillStyle = '#fff' cav.fillText(dataArr1[index], tipsPoint[0] + tipsImg.width - 12, tipsPoint[1] + tipsImg.height / 3) cav.textAlign = 'start' cav.textBaseline = 'middle' cav.font = '14px' cav.fillStyle = 'red' cav.fillText('浏览量', tipsPoint[0] + 10, tipsPoint[1] + tipsImg.height - 15) cav.textAlign = 'right' cav.textBaseline = 'middle' cav.font = '14px' cav.fillStyle = '#fff' cav.fillText(dataArr2[index], tipsPoint[0] + tipsImg.width - 12, tipsPoint[1] + tipsImg.height - 15) }
最新回复(0)