画圆形进度条图

1.用css实现。

前言:只适用于两种颜色,多种颜色使用canvas

原理:将块元素分为左右两半,在里面画一个圆分别显示左右进度,圆中border对应设置两个颜色,通过rorate(45deg),来让上下左右边框变成四个圆弧,再通过rorate来显示左右各占多少。

实现效果:

代码:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style>
			.area {
				width: 300px;
				height: 300px;
			}
			.circle-pic {
				width: 60px;
				height: 60px;
				position: relative;
				overflow: hidden;
			}

			.circle-l {
				position: absolute;
				width: 50%;
				height: 100%;
				overflow: hidden;
				right: 0;
			}

			.circle-r {
				position: absolute;
				width: 50%;
				height: 100%;
				overflow: hidden;
				left: 0;
			}

			.circle-l .txt {
				/* width:50%; */
				position: absolute;
				top: 0;
				right: 0;
				width: 200%;
				height: 100%;
				border: 5px solid red;
				border-radius: 50%;
				transform: rotate(45deg);
				transition: all .3s ease;
				box-sizing: border-box;
				border-left-color: blue;
				border-bottom-color: blue;
				transform: rotate(106deg);
			}

			.circle-r .txt {
				position: absolute;
				top: 0;
				width: 200%;
				height: 100%;
				border: 5px solid blue;
				border-radius: 50%;
				transform: rotate(45deg);
				transition: all .3s ease;
				box-sizing: border-box;
				border-right-color: red;
				border-top-color: red;
				transform: rotate(106deg);
			}
		</style>
	</head>
	<body>
		<div class="area">
			<div class="circle-pic">
				<div class="circle-l">
					<span class="txt"></span>
				</div>
				<div class="circle-r">
					<span class="txt"></span>
				</div>
			</div>
		</div>
	</body>
</html>

2.用canvas实现

原理:直接通过百分比画圆弧的方式实现

实现效果:与上图类似

代码:以下为项目uniapp中的组件

<template>
	<view class="c-circle">
		<canvas  style="width:60px;height:60px;" :canvas-id="'homeownerCanvas'+index" class="c-can homeowner-canvas_charts"></canvas>
	</view>
</template>

<script>
	export default{
		data(){
			return {
				dataList : [{
				    "value": 0.3,
				    "color": "#2445A1"
				},
				{
				    "value": 0.2,
				    "color": "#EA4747"
				}
				]
			}
		},
		created(){
			
		},
		props:{
			hNum: [String,Number],
			aNum: [String,Number],
			index: [String,Number]
		},
		watch:{
		},
		mounted(){
			this.drawCanvas();
			// hNum,aNum是数据的数值,index用来区分多个canvas
			let p1=(parseInt(this.aNum/(this.aNum+this.hNum)*100)/100).toFixed(2);
			let p2 = 1-p1;
			this.$set(this.dataList[0],'value',p1);
			this.$set(this.dataList[1],'value',p2);
			this.canvasGraph('homeownerCanvas'+this.index,this.dataList,100)
		},
		methods:{
			canvasGraph(canvasID,data,summation){
			    function PieChart(ctx,radius){
			         //定义起始角度
			        let tempAngle=270;
			        //定圆心位置
			        let x0=30,y0=30;
					let outLine = 10;
			        PieChart.prototype.init = function(data){
			            this.drawPie(data);
			        };    
			        // 绘画扇形 及中心圆
			        PieChart.prototype.drawPie = function(data){
			            for (let i = 0; i < data.length; i++) {
			                // 开始一个新路径
			                ctx.beginPath();
			                // 移动到中心点
			                ctx.moveTo(x0,y0);
			                //计算当前扇形角度   所占比例*360
			                let angle = data[i].value*360;
			                //当前扇形起始绘制弧度   360 = 2π  等于6.28
			                let startAngle = tempAngle*Math.PI/180;
			                //当前扇形借结束绘制弧度
			                let endAngle = (tempAngle + angle)*Math.PI/180;
			                //绘制扇形  x y中心  半径  开始弧度  结束弧度
			                ctx.arc(x0,y0,radius,startAngle,endAngle);
			                //填充扇形
			                ctx.fillStyle = data[i].color;
			                // 填充
			                ctx.fill();
			                // 调用添加标题解释方法
			                // this.drawTitle(startAngle,angle,data[i].color, data[i].title + data[i].money)
			                //当前扇形结束绘制角度,即下一个扇形开始绘制角度
			                tempAngle += angle;
			            }
			            // 开始一个新路径
			            ctx.beginPath();
			            // 开始画圆
			            ctx.arc(x0, y0, 19, 0, 2 * Math.PI)
			            // 填充颜色 白色
			            ctx.setFillStyle('white')
			            // 调用绘制中心圆文字方法
			            this.drawCenterTitle()
			        }
			        // 伸出线条方法
			        PieChart.prototype.drawTitle = function(startAngle,angle,color,title){
			            // 伸出去的长度 斜边长度 等于半径加上定义好的长度  
			            let out = radius;
			            // 当前弧度的二分之一
			            let du = startAngle+(angle/2)*Math.PI/180;
			            // 计算伸出的点x坐标
			            let outX = x0+out*Math.cos(du);
			            // 计算伸出的点y坐标
			            let outY = y0+out*Math.sin(du);
			            // 开始一个新路径
			            ctx.beginPath();
			            // 移动到中心点
			            ctx.moveTo(x0,y0);
			            // 画出点到伸出点的一条线
			            ctx.lineTo(outX,outY);
			            // 线条颜色
			            ctx.strokeStyle = color;
			            //设置标题
			            ctx.font = 'bold 14px Microsoft Yahei';
			            // 计算出标题文字宽度
			            let textWidth = ctx.measureText(title).width;
			            // 计算标题样式
			            ctx.textBaseline = "bottom";
			            // 刷新配置项  象限判断 与 对应符号
			            let optionArr=[
			                {
			                    quadrant:outX>x0 && outY<y0,
			                    symbol:['+','-','left']
			                },
			                {
			                    quadrant:outX<x0 && outY<y0,
			                    symbol:['-','-','right']
			                },
			                {
			                    quadrant:outX<x0 && outY>y0,
			                    symbol:['-','+','right']
			                },
			                {
			                    quadrant:outX>x0 && outY>y0,
			                    symbol:['+','+','left']
			                }
			            ]
			            // 渲染的配置项
			            let {symbol} = optionArr.find(el=>el.quadrant&&el.symbol)
			            // 斜线起始点
			            let slashState = eval(outX+symbol[0]+outLine)
			            // 横线起始点
			            let lineState = eval(outX+symbol[0]+textWidth+symbol[0]+outLine)
			            // 终点
			            let lineEnd = eval(outY+symbol[1]+outLine)
			            // 标题文字样式
			            ctx.textAlign = symbol[2];
			            // 画出伸出的斜线
			            ctx.lineTo(slashState,lineEnd);
			            // 接上斜线画出标题下面的直线
			            ctx.lineTo(lineState,lineEnd);
			            // 填充标题
			            ctx.fillText(title,slashState,lineEnd);
			            // 填充
			            ctx.stroke();
			        }
			        // 绘制中心文字
			        PieChart.prototype.drawCenterTitle = function(){
			            // 填充
			            ctx.fill();
			            // 开始画图
			            ctx.draw()
			        }
			    
				}
			    var ctx = uni.createCanvasContext(canvasID) 
			    var PieChart = new PieChart(ctx,25)
			    PieChart.init(data)
			},
			drawCanvas(){
				let context = uni.createCanvasContext('myCanvas'+this.index,this);
				context.lineWidth = 10;   
				context.beginPath();
				context.arc(100, 100, 50, 0, Math.PI/2 , true);
				context.strokeStyle = '#0f0';
				context.stroke();
				context.beginPath();
			}
		}
	}
</script>

<style lang="scss" scope>
	.c-circle{
		.c-can{
			width:300upx;
			height:300upx;
			margin: 0 auto;
		}
	}
</style>

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值