柱图
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
]
var Xpoint
= [zeroPoint
[0] + Xwidth
, zeroPoint
[1]]
var Xpatition
= Xwidth
* 0.95 / nameArr
.length
var namePoint
= [Xpatition
/ 2 + zeroPoint
[0], zeroPoint
[1] + 15]
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
var dataPoint
= [zeroPoint
[0] - 15, zeroPoint
[1] - Ypatition
/ 2]
var YdataLabel
= []
var dataLabel
= max
/ 5
for (let i
= 0; i
< 5; i
++) {
YdataLabel
.push(dataLabel
)
dataLabel
+= max
/ 5
}
var barWidth
= 10
var linePoint
= []
var tipsPoint
= []
cav
.beginPath()
cav
.moveTo(zeroPoint
[0], zeroPoint
[1])
cav
.lineTo(Ypoint
[0], Ypoint
[1])
cav
.strokeStyle
= 'red'
cav
.closePath()
cav
.stroke()
cav
.beginPath()
cav
.moveTo(zeroPoint
[0], zeroPoint
[1])
cav
.lineTo(Xpoint
[0], Xpoint
[1])
cav
.strokeStyle
= 'red'
cav
.closePath()
cav
.stroke()
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()
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()
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)
}