canvas作图系列——仪表盘图

仪表盘图

仪表盘其实也是环图的一种,但是比环图多的是一个指针,指针需要根据环图的进度调整位置,而这其中主要用到的就是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)
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IsQtion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值