canvas实现圆饼图

  • 前言
  • 作法
  • canvas
  • 圆饼制作


前言

最近,跟人讨论怎么在前端页面画圆饼图,想来想去,这难度不高,毕竟网上挺多的,像用伪元素伪装然后旋转出来部分等等,今天就来试试用canvas来话,试着弄了一下,效果图

html5饼状图调试 饼状图前端_html5饼状图调试

作法

首先是有这么一组模拟数据,我根据数据来弄成一个饼图

var can = [{
				id: 'can-file-other',
				color: 'red',
			},
			{
				id: 'can-file-img',
				color: 'blue',
			},
			{
				id: 'can-file-tar',
				color: 'orange',
			},
			{
				id: 'can-file-vi',
				color: 'green',
			},
			{
				id: 'can-file-au',
				color: 'pink',
			}
		]
		var File = {
			total: 100,
			data: [
				{type:'other',size: 5},
				{type:'img',size: 10},
				{type:'tar',size: 10},
				{type:'vi',size: 10},
				{type:'au',size: 20}
			]
		}

咋一看,数据格式还挺好懂,
废话不多说,首先来定义框架,

<div id="bu">
			<canvas  id="can-file" width="300" height="300">
			</canvas>
			<div id="cir-dir">
				<label v-for="(val , index) in file" v-if="val.size > 0">
					{{val.type}}
					<span :style="{background:can[index].color}"></span>
				</label>
			</div>
		</div>

后面的lable用到了vue来进行构造,当然是用js来构造也是简单的,这里就不详细解析了,
然后稍微解析一下,canvas标签

canvas

canvas标签用于绘制图像,但是本身没用绘制功能,绘制能力都是有js脚本来操作,也就是图像并不能用纯css来构造,要借助js来实现,由于属性挺多的,就不一一列举,这里说一下我这次用到的属性


描述

getcontxt

配置当前绘制环境,目前了解来看似乎只有个‘2d’这个属性,也就是2d空间,也就是说在未来可能会有3d的绘画环境

beginPath

重置路径,canvas配置有路径记录,也就说,可以用其中的某些方法,比如arcTo等,连续绘画 ,这个方法就是来重置当前路径的

arc

画弧线或者曲线,共有6个属性,下面再行介绍

createLinearGradient

设置渐变样式

addColorStop

设置渐变颜色,和 位置

fillStyle

设置填充图形样式,也就是选颜色,可以单颜色也可以是渐变颜色

strokeStyle

设置填充边线样式,也就是选颜色,可以单颜色也可以是渐变颜色

fill

应用样式填充图形

stroke

也是填充,但是不同的是填充的是边线

lineWidth

设置边线厚度

一般来说,在canvas配置环境后再进行绘画,才能用其他方法.
arc属性如下


描述

x

中心x坐标

y

中心y坐标

sAngle

起始角度

eAngle

结束角度

counterclockwise

选择反向,false为顺时针,true为逆时针,默认是顺时针

圆饼制作

首先,饼图是根据上面的数据做的,所以上面数据,也是对图的操作,要取得他的颜色,起始和结束位置,角度就可以用size来计算,但是要注意的一点就是每一次的起始角设置上上一次的起始角,并且角的单位是弧度制,所以得出
html5饼状图调试 饼状图前端_javascript_02
html5饼状图调试 饼状图前端_canvas_03
所以定义个方法

draw: function(index, val) {
					var color = val.color
					var c = document.getElementById('can-file')
					var ctx = c.getContext('2d')
					ctx.beginPath()
					var x = 150
					var y = 150
					var radius = 50; 
					var startAngle = this.start
					var endAngle =startAngle+2*Math.PI * this.file[index].size / 100
					this.start = endAngle
					ctx.arc(x, y, radius, startAngle, endAngle)
					ctx.strokeStyle = color
					ctx.lineWidth = 50
					ctx.stroke()
				}

最后定义循环来进行绘画

this.can.forEach(function(val,index){
					this.draw(index,val)
				})
//进行最后的填充补充
var c = document.getElementById('can-file')
					var ctx = c.getContext('2d')
					ctx.beginPath()
					var startAngle = this.start
					ctx.arc(150, 150, 50, startAngle, 2*Math.PI);
					ctx.strokeStyle = 'black'
					ctx.lineWidth = 50
					ctx.stroke()

设置css和高宽后,得出图形

html5饼状图调试 饼状图前端_html5饼状图调试_04


然后设置一下div的伪类装饰,

#bu:after,#bu:before{
				position: absolute;
				content: "";
				width: 90px;
				height: 90px;
				border-radius: 50%;
				top: calc(50% - 45px);
				left: calc(50% - 45px);
				background: white;
				z-index: 2;
				border: 1px solid black;
			}
			#bu:before{
				width: 160px;
				height: 160px;
				border-radius: 50%;
				top: calc(50% - 80px);
				left: calc(50% - 80px);
				background: transparent;
				border: 1px solid black;
				z-index: -1;
			}

并循环添加lable标签,这里用的是vue来进行添加,也很简单

<label v-for="(val , index) in file" v-if="val.size > 0">
					{{val.type}}
					<span :style="{background:can[index].color}"></span>

最后得出效果图

html5饼状图调试 饼状图前端_html5饼状图调试_05