示例
思路整理
用canvas绘制一个环形
在把一个 标注定位在canvas上方 (也可以用canvas绘制)
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>环形进度条-canvas-函数封装</title>
<style>
._con_{
width: 300px;
height: 300px;
outline: 1px solid;
position: relative;
}
._con_ > .text{
height: 100%;
text-align: center;
position: absolute;
top: 0;
width: 100%;
line-height: 300px;
}
</style>
</head>
<body>
<div class="_con_">
<canvas id="mycanvas" width="300" height="300"></canvas>
<div class="text"> </div>
</div>
<script>
// 宽高直接写在标签上
const ctx = document.getElementById("mycanvas").getContext("2d");
//外圆环
ctx.beginPath();
// 中心坐标 x y 半径 起始角(弧的圆形的三点钟位置是 0 度) 结束角 counterclockwise:False = 顺时针,true = 逆时针。
ctx.arc(150, 150, 100, 0, 2 * Math.PI); //
ctx.strokeStyle = "#fff"; // 边界颜色 类似 border
ctx.fillStyle = "#EDEDED"; // 填充色
ctx.fill(); // 进行填充
ctx.stroke();
//内圆环
// ctx.beginPath();
// ctx.arc(150, 150, 90, 0, 2 * Math.PI);
// ctx.strokeStyle = "#fff";
// ctx.fillStyle = "#fff";
// ctx.fill();
// ctx.stroke();
var text = document.getElementsByClassName("text")[0]
console.log(text)
var press = 0.9,percent = 0
function animate(){
requestAnimationFrame(function (){ //屏幕刷新频率
fun()
text.innerText = (percent * 100).toFixed(0) + "%"
percent += 0.05
if (percent < press) {
animate();
}
});
}
animate()
// 圆环
function fun(){
// 1.5 -0.5 1 -0.5
// 1.5*Math.PI 正上方
// 画圆 填充边界线 内部填充 Math.PI = 180度
ctx.beginPath();
// 顺时针 -Math.PI / 2,-Math.PI / 2 + percent * (Math.PI * 2),false)
// 逆时针 1.5*Math.PI, (1.5-(percent*2))
ctx.arc( 150,150, 96, 1.5*Math.PI, (1.5-(percent*2))*Math.PI ,true);
ctx.lineWidth = 8;
ctx.lineCap = "round"; // lineCap 属性设置或返回线条末端线帽的样式。
ctx.strokeStyle = "#19c6c1"//"rgb(255, 127, 105)";
ctx.stroke();
}
</script>
</body>
</html>
效果
封装
代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>环形进度条-canvas-函数封装</title>
</head>
<body>
<div class="con"></div>
<script>
function LoopProgress(obj){
this.container = obj.container; // 进度条放置容器
this.gress = obj.gress; // 初始进度
this.width = parseInt(obj.width || '400px');
this.height = parseInt(obj.height || '400px');
this.lineColor = obj.lineColor || "#00fd54"; //进度条颜色
this.lineWidth = parseInt(obj.lineWidth || 15), //进度条宽度
// this.animationTime = obj.animationTime || 1; //进度条时间
this.textDom = obj.textDom // 中间文本对象
this.textDomFun = obj.textDomFun // 中间文本对象更新回调函数
this.dom;
this.canvas;
this.ctx;
this.text;
}
var container = document.getElementsByClassName("con")[0]
LoopProgress.prototype.init = function(){
this.dom = this.createDom()
this.container.appendChild(this.dom)
this.canvasInit()
this.textInit(0)
this.setPerss()
}
// 生成dom节点
LoopProgress.prototype.createDom = function(){
var con = document.createElement("div")
var canvas = document.createElement("canvas")
var text = document.createElement("div")
con.style.width = this.width + "px"
con.style.height = this.height + "px"
con.style.position = "relative"
canvas.setAttribute("width",this.width)
canvas.setAttribute("height",this.height)
text.style.width = this.width + "px"
text.style.height = this.height + "px"
text.style.lineHeight = this.height + "px"
text.style.position = "absolute"
text.style.top = "0"
text.style.textAlign = "center"
con.appendChild(canvas)
con.appendChild(text)
this.canvas = canvas
this.text = text
return con
}
// canvas 初始化 文字初始化
LoopProgress.prototype.canvasInit = function(){
var ctx = this.canvas.getContext("2d");
ctx.beginPath();
// 中心坐标 x y 半径 起始角(弧的圆形的三点钟位置是 0 度) 结束角 counterclockwise:False = 顺时针,true = 逆时针。
ctx.arc(this.width/2, this.height/2, this.height/2, 0, 2 * Math.PI); //
ctx.strokeStyle = "#fff"; // 边界颜色 类似 border
ctx.fillStyle = "#EDEDED"; // 填充色
ctx.fill(); // 进行填充
ctx.stroke();
this.ctx = ctx
this.setAnnulus(0)
}
// 绘制圆环
LoopProgress.prototype.setAnnulus = function(percent){
// 1.5*Math.PI 正上方
// 画圆 填充边界线 内部填充 Math.PI = 180度
this.ctx.beginPath();
// 顺时针 -Math.PI / 2,-Math.PI / 2 + percent * (Math.PI * 2),false)
// 逆时针 1.5*Math.PI, (1.5-(percent*2))
this.ctx.arc(this.width/2,this.height/2, this.height/2 - this.lineWidth/2, 1.5*Math.PI, (1.5-(percent*2))*Math.PI ,true);
this.ctx.lineWidth = this.lineWidth;
this.ctx.lineCap = "round"; // lineCap 属性设置或返回线条末端线帽的样式。
this.ctx.strokeStyle = this.lineColor;
this.ctx.stroke();
}
LoopProgress.prototype.textInit = function(num){
!this.textDom ? this.text.innerText = num + "%" : this.text.innerHTML = this.textDom,this.textDomFun(this.text.children)
}
// 动态更新
LoopProgress.prototype.setPerss = function(){
var _this = this,
percent = 0;
var time = new Date().getTime()
animate()
function animate(){
requestAnimationFrame(function (){ //屏幕刷新频率
// console.log("percent:",percent,(percent * 100).toFixed(0))
_this.setAnnulus(percent)
_this.textInit((percent * 100).toFixed(0))
percent += 0.05
if (percent <= parseInt(_this.gress)*0.01) {
animate();
}
});
}
}
// 销毁
LoopProgress.prototype.close = function(obj){
this.dom.remove()
obj = null
}
var img = document.getElementsByClassName("img")[0]
var loop = new LoopProgress({
container:container,
gress:"70",
width:"400",
height:"400",
lineWidth:"15",
textDom:'<div class="img" style="width: 200px;height: 200px;" alt="">xxx</div>',// 是否设置中间部分
textDomFun:function(e){ // 设置之后的回调
console.log("textDomFun",e[0])
}
})
loop.init()
var loop2 = new LoopProgress({
container:container,
gress:"40",
width:"100",
height:"100",
lineWidth:"10",
textDom:"" ,// 是否设置中间部分
textDomFun:function(){ // 设置之后的回调
}
})
loop2.init()
var loop3 = new LoopProgress({
container:container,
gress:"30",
width:"200",
height:"200",
lineWidth:"45",
textDom:"" ,// 是否设置中间部分
textDomFun:function(){ // 设置之后的回调
}
})
loop3.init()
</script>
</body>
</html>