仪表盘图
仪表盘其实也是环图的一种,但是比环图多的是一个指针,指针需要根据环图的进度调整位置,而这其中主要用到的就是canvas的旋转,但是注意的是canvas的旋转是以画布原点为旋转中心旋转的,因此,我们需要将旋转中心调整到我们需要的位置,再对画布进行旋转,要记得旋转完成之后,需要逆向旋转并平移复位,不然之后会错位的
js
有一点需要注意的是,如果其中有一段描边使用了ctx.setLineDash([])设置描边样式为虚线了,那么之后的所有描边都有可能会变成虚线,因此,在此后如果有实线的话需要通过ctx.setLineDash([1,0])的方法设置回来。
其中的两个参数分别是实线的像素长度,空位置的像素长度,比如[3,2]就是实线3像素,空2像素所以[1,0]就是实线1像素,空0像素也就是全都是实线
function DrawDoubleHalfCircle(data) {
var canvas = document.querySelector('#cav6')
var circlePoint = [canvas.clientWidth / 2, canvas.clientHeight / 2]
var cav = canvas.getContext('2d')
cav.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
var startAngle = Math.PI
//圆圈中心文字
cav.textAlign = 'center'
cav.textBaseline = 'middle'
cav.font = '24px MeicrosoftYahei'
cav.fillStyle = '#fff'
cav.fillText('营销', circlePoint[0], circlePoint[1])
//文字外部圆环
var circleLine = cav.createLinearGradient(circlePoint[0], circlePoint[1] - 46, circlePoint[0], circlePoint[1] +
46);
circleLine.addColorStop(0, "#FCECF4");
circleLine.addColorStop(0.4, '#0D135F');
circleLine.addColorStop(0.6, '#0D135F');
circleLine.addColorStop(1, '#FCECF4');
cav.beginPath()
cav.lineWidth = 3
cav.arc(circlePoint[0], circlePoint[1], 46, 0, Math.PI * 2, true)
cav.strokeStyle = circleLine
cav.stroke()
//文字外部圆环外部的圆圈
var circlePie = cav.createLinearGradient(circlePoint[0], circlePoint[1] - 67, circlePoint[0], circlePoint[1] + 67);
circlePie.addColorStop(0, "rgba(255,255,255,0)");
circlePie.addColorStop(0.5, 'rgba(255,255,255,0.2)');
circlePie.addColorStop(1, 'rgba(255,255,255,0)');
cav.beginPath()
cav.arc(circlePoint[0], circlePoint[1], 67, 0, Math.PI * 2, true)
cav.fillStyle = circlePie
cav.fill()
//上半圆底纹
var topHalf = cav.createLinearGradient(circlePoint[0] - 94, circlePoint[1], circlePoint[0] + 94, circlePoint[1]);
topHalf.addColorStop(0, "rgba(17, 6, 67,0)");
topHalf.addColorStop(1, 'rgba(17, 6, 67,1)');
cav.beginPath()
cav.lineWidth = 16
cav.arc(circlePoint[0], circlePoint[1], 94, startAngle, Math.PI * 2, false)
cav.strokeStyle = topHalf
cav.setLineDash([1, 0]);
cav.stroke()
//下半圆底纹
cav.beginPath()
cav.lineWidth = 16
cav.arc(circlePoint[0], circlePoint[1], 94, startAngle, 0, true)
cav.strokeStyle = 'rgb(235, 73, 86)'
cav.setLineDash([1, 5]);
cav.stroke()
//水平虚线及初始和饱和值
var lineDash1 = cav.createLinearGradient(0, circlePoint[1], circlePoint[0] - 48, circlePoint[1]);
lineDash1.addColorStop(0, "rgba(255, 255, 255,0)");
lineDash1.addColorStop(1, 'rgba(255, 255, 255,1)');
cav.beginPath()
cav.moveTo(0, circlePoint[1])
cav.lineTo(circlePoint[0] - 48, circlePoint[1])
cav.strokeStyle = lineDash1
cav.setLineDash([4, 2])
cav.lineWidth = 1
cav.stroke()
var lineDash2 = cav.createLinearGradient(circlePoint[0] + 48, circlePoint[1], canvas.clientWidth, circlePoint[1]);
lineDash2.addColorStop(0, "rgba(255, 255, 255,1)");
lineDash2.addColorStop(1, 'rgba(255, 255, 255,0)');
cav.beginPath()
cav.moveTo(circlePoint[0] + 48, circlePoint[1])
cav.lineTo(canvas.clientWidth, circlePoint[1])
cav.strokeStyle = lineDash2
cav.setLineDash([4, 2])
cav.lineWidth = 1
cav.stroke()
cav.textAlign = 'right'
cav.textBaseline = 'middle'
cav.font = '26px MeicrosoftYahei'
cav.fillStyle = '#fff'
cav.fillText('0', circlePoint[0] - 110, circlePoint[1])
cav.textAlign = 'start'
cav.textBaseline = 'middle'
cav.font = '26px MeicrosoftYahei'
cav.fillStyle = '#fff'
cav.fillText('100', circlePoint[0] + 110, circlePoint[1])
//上半圆数据显示
var PointAssemble = getPoint(startAngle, parseFloat(data[0]) * Math.PI + startAngle, 94, circlePoint[0],
circlePoint[1])
var topHalfData = cav.createLinearGradient(circlePoint[0] - 94, circlePoint[1], PointAssemble.endPointX,
PointAssemble.endPointY);
topHalfData.addColorStop(0, "rgba(245, 75, 82,0)");
topHalfData.addColorStop(1, 'rgba(245, 75, 82,1)');
cav.beginPath()
cav.lineWidth = 16
cav.arc(circlePoint[0], circlePoint[1], 94, startAngle, parseFloat(data[0]) * Math.PI + startAngle, false)
cav.setLineDash([1, 0]);
cav.strokeStyle = topHalfData
cav.stroke()
cav.drawImage(chartBall, PointAssemble.endPointX - chartBall.width / 2, PointAssemble.endPointY - chartBall
.height / 2)
//下半圆数据显示
var PointAssemble2 = getPoint(startAngle, startAngle - parseFloat(data[1]) * Math.PI, 94, circlePoint[0],
circlePoint[1])
var bottomHalfData = cav.createLinearGradient(circlePoint[0] - 94, circlePoint[1], PointAssemble2.endPointX,
PointAssemble2.endPointY);
bottomHalfData.addColorStop(0, "rgba(255,255,255,0)");
bottomHalfData.addColorStop(1, 'rgba(255,255,255,1)');
cav.beginPath()
cav.lineWidth = 16
cav.arc(circlePoint[0], circlePoint[1], 94, startAngle, startAngle - parseFloat(data[1]) * Math.PI, true)
cav.setLineDash([1, 0]);
cav.strokeStyle = bottomHalfData
cav.stroke()
//上半圆箭头指示
cav.translate(circlePoint[0], circlePoint[1])
cav.rotate(parseFloat(data[0]) * Math.PI)
cav.drawImage(needle, -40 - needle.width, -needle.height / 2)
cav.rotate(-parseFloat(data[0]) * Math.PI)
cav.translate(-circlePoint[0], -circlePoint[1])
//下半圆箭头指示
cav.translate(circlePoint[0], circlePoint[1])
cav.rotate(-parseFloat(data[1]) * Math.PI)
cav.drawImage(needle, -40 - needle.width, -needle.height / 2)
cav.rotate(parseFloat(data[1]) * Math.PI)
cav.translate(-circlePoint[0], -circlePoint[1])
//上半圆具体数据
//判断数据提示框的显示位置数据占比大于50%就靠右显示,否则靠左显示
if (parseFloat(data[0]) < 0.5) {
cav.drawImage(activeBar, PointAssemble.endPointX - 22 * ((data[0] * 100).toFixed(1) + '%').length - 10,
PointAssemble.endPointY - 35)
} else {
cav.drawImage(activeBar, PointAssemble.endPointX + 10, PointAssemble.endPointY - 35)
}
cav.textAlign = parseFloat(data[0]) < 0.5 ? 'right' : 'start'
cav.textBaseline = 'bottom'
cav.font = 'bold 36px Akrobat-Black'
cav.fillStyle = '#fff'
if (parseFloat(data[0]) < 0.5) {
cav.fillText((data[0] * 100).toFixed(1) + '%', PointAssemble.endPointX - 10, PointAssemble.endPointY - 20)
} else {
cav.fillText((data[0] * 100).toFixed(1) + '%', PointAssemble.endPointX + 10, PointAssemble.endPointY - 20)
}
//下半圆具体数据
if (parseFloat(data[1]) < 0.5) {
cav.drawImage(norBar, PointAssemble2.endPointX - 22 * ((data[1] * 100).toFixed(1) + '%').length - 10,
PointAssemble2.endPointY + 45)
} else {
cav.drawImage(norBar, PointAssemble2.endPointX + 10, PointAssemble2.endPointY + 45)
}
cav.textAlign = parseFloat(data[1]) < 0.5 ? 'right' : 'start'
cav.textBaseline = 'top'
cav.font = 'bold 36px Akrobat-Black'
cav.fillStyle = '#fff'
if (parseFloat(data[1]) < 0.5) {
cav.fillText((data[1] * 100).toFixed(1) + '%', PointAssemble2.endPointX - 10, PointAssemble2.endPointY + 25)
} else {
cav.fillText((data[1] * 100).toFixed(1) + '%', PointAssemble2.endPointX + 10, PointAssemble2.endPointY + 25)
}
}