canvas作图系列——环图

环图

canvas制作圆形所用的方法是

ctx.arc(x,y,r,0,Math,PI*2,false)

其中的6个参数分别是圆心横坐标,圆心纵坐标,半径,起始角度,结束角度,false顺势针/true逆时针
而圆环也是用的这个方法,只不过是ctx.fill()填充,替换成了ctx.stroke()描边,利用描边我们就可以绘制出任何大小及弧度的圆环了,通过ctx.linewidth可以设置描边的粗细,也就是圆环的宽窄。
上图中其实是个统计用的图表,展示的是四个数据在这个圆环中的占比情况。由于canvas采用的是帧绘制,所以在有轮流高亮的情况下,就是定时的清除画布然后重绘,清除画布的方法是
ctx.clearRect(起始x,起始y,结束x,结束y)

图一

在这里插入图片描述

图一JS

function gague(arr, index) {
		var canvas = document.querySelector('#cav')
		var cav = canvas.getContext('2d');
		cav.clearRect(0, 0, 300, 300);	

		var wholeCircle = Math.PI * 2
		var wholeAngle = wholeCircle * 3 / 4	//圆环的全部角度是3/4个圆
		var sum = eval(arr.join('+'))		//对传入数据的处理求和

		var startAngle = wholeCircle * 3 / 8 + wholeCircle / 200	//设置圆环的初始角度
		var endAngle = startAngle + wholeAngle * (arr[0] / sum) - wholeCircle / 100		//根据数据占比设置第一个弧长的结束角度

		//绘制起始的小分割圆弧
		cav.beginPath()
		cav.lineWidth = 40
		cav.strokeStyle = 'rgb(56,64,129)';
		cav.arc(150, 150, 90, startAngle - wholeCircle / 200, startAngle, false)
		cav.stroke()

		for (let i = 0; i < arr.length; i++) {
			//getPoint是自定义的一个方法,通过传入圆弧的起始角度,结束角度,半径和圆心的横纵坐标来获得圆弧的起始和结束点坐标,返回的是一个对象集合
			var PointAssemble = getPoint(startAngle, endAngle, 110, 150, 150)
			//cav.createLinearGradient()是canvas设置渐变色的方法,这是径向渐变传入的参数是渐变起始点横纵坐标和结束点横纵坐标
			var normalColor = cav.createLinearGradient(PointAssemble.startPointX, PointAssemble.startPointY, PointAssemble
				.endPointX, PointAssemble.endPointY);
			normalColor.addColorStop(0, "rgba(68,102,244,0.2)");
			normalColor.addColorStop(1, 'rgba(68,102,244,0.4)');
			var highlightColor = cav.createLinearGradient(PointAssemble.startPointX, PointAssemble.startPointY,
				PointAssemble.endPointX, PointAssemble.endPointY);
			highlightColor.addColorStop(0, "rgba(56,64,129,0.2)");
			highlightColor.addColorStop(1, 'rgba(255,15,110,0.6)');
			
			//开始绘制圆弧
			cav.beginPath()
			cav.lineWidth = 40
			cav.strokeStyle = index == i ? highlightColor : normalColor;
			cav.arc(150, 150, 90, startAngle, endAngle, false)
			cav.stroke()
			
			//绘制每个圆弧之间的分割圆弧
			cav.beginPath()
			cav.lineWidth = 40
			cav.strokeStyle = index == i ? 'rgb(255,15,110)' : 'rgb(68,102,244)';
			cav.arc(150, 150, 90, endAngle, endAngle + wholeCircle / 100, false)
			cav.stroke()
			startAngle = startAngle + wholeAngle * (arr[i] / sum)
			endAngle = startAngle + wholeAngle * (arr[i + 1] / sum) - wholeCircle / 100
		}
	}

图二

在这里插入图片描述
上图的高亮处小圆点是个图片,要注意的是,如果canvas中出现图片,要先获取图片,等图片加载完毕之后再调用canvas的绘图方法

var img = new Image()
img.src='图片路径'
img.onload =()=>{
	//这里调用你的绘图函数
}

图二JS

function halfCircle(arr, index) {
		var canvas = document.querySelector('#cav4')
		var cav = canvas.getContext('2d');
		cav.clearRect(0, 0, 300, 300);
		//跟上面的环图一样,首先先设置的是初始值,比如第一个环的起始和结束角度以及整个圆弧的角度
		var wholeCircle = Math.PI * 2
		var wholeAngle = wholeCircle / 2
		var sum = eval(arr.join('+'))

		var startAngle = wholeCircle / 2
		var endAngle = startAngle + wholeAngle * (arr[0] / sum)

		for (let i = 0; i < arr.length; i++) {
			//这里依然需要获取到每一个圆弧的起始和结束坐标点用来定位图片的绘制位置
			var PointAssemble = getPoint(startAngle, endAngle, 90, 150, 150)

			var normalColor = cav.createLinearGradient(PointAssemble.startPointX, PointAssemble.startPointY, PointAssemble
				.endPointX, PointAssemble.endPointY);
			normalColor.addColorStop(0, "rgba(9, 9, 24,0)");
			normalColor.addColorStop(1, 'rgba(42, 81, 248,1)');
			var highlightColor = cav.createLinearGradient(PointAssemble.startPointX, PointAssemble.startPointY,
				PointAssemble.endPointX, PointAssemble.endPointY);
			highlightColor.addColorStop(0, "rgba(29, 11, 35,0)");
			highlightColor.addColorStop(1, 'rgba(228, 90, 147,1)');

			cav.beginPath()
			cav.lineWidth = 10
			cav.strokeStyle = index == i ? highlightColor : normalColor;
			cav.lineCap = 'round'
			cav.arc(150, 150, 90, startAngle, endAngle, false)
			cav.stroke()
			if (i == index) {
				cav.drawImage(imgYuan, PointAssemble.endPointX - imgYuan.width / 2, PointAssemble.endPointY - imgYuan
					.height / 2)
			}

			startAngle = startAngle + wholeAngle * (arr[i] / sum)
			endAngle = startAngle + wholeAngle * (arr[i + 1] / sum)
		}
	}

值得注意的一点是,当你的圆环半径确定的时候,不管你的圆环宽度有多宽,圆环的半径始终是从圆心到二分之一圆环宽度的距离,而不是从圆心到圆环外边或者到圆环内边的距离,所以你的圆环越宽,他的实际面积会越大在这里插入图片描述

自定义获取坐标点函数

function getPoint(startAngle, endAngle, r, circleX, circleY) {
		var startPointX, startPointY, endPointX, endPointY
		if (startAngle < Math.PI) {
			startPointX = circleX - Math.sin(startAngle - Math.PI / 2) * r
			startPointY = circleY + Math.cos(startAngle - Math.PI / 2) * r
		} else if (startAngle < Math.PI * 3 / 2) {
			startPointX = circleX - Math.cos(startAngle - Math.PI) * r
			startPointY = circleY - Math.sin(startAngle - Math.PI) * r
		} else if (startAngle < Math.PI * 2) {
			startPointX = circleX + Math.sin(startAngle - Math.PI * 3 / 2) * r
			startPointY = circleY - Math.cos(startAngle - Math.PI * 3 / 2) * r
		} else {
			startPointX = circleX + Math.cos(startAngle - Math.PI * 2) * r
			startPointY = circleY + Math.sin(startAngle - Math.PI * 2) * r
		}
		if (endAngle < Math.PI) {
			endPointX = circleX - Math.sin(endAngle - Math.PI / 2) * r
			endPointY = circleY + Math.cos(endAngle - Math.PI / 2) * r
		} else if (endAngle < Math.PI * 3 / 2) {
			endPointX = circleX - Math.cos(endAngle - Math.PI) * r
			endPointY = circleY - Math.sin(endAngle - Math.PI) * r
		} else if (endAngle < Math.PI * 2) {
			endPointX = circleX + Math.sin(endAngle - Math.PI * 3 / 2) * r
			endPointY = circleY - Math.cos(endAngle - Math.PI * 3 / 2) * r
		} else {
			endPointX = circleX + Math.cos(endAngle - Math.PI * 2) * r
			endPointY = circleY + Math.sin(endAngle - Math.PI * 2) * r
		}

		return {
			startPointX,
			startPointY,
			endPointX,
			endPointY
		}
	}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IsQtion

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

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

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

打赏作者

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

抵扣说明:

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

余额充值