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>