canvas+JS如何实现可拖拽并且显示百分比的环形进度条
思维导图:
HTML部分:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
</head>
<body>
<canvas id="test" width="200" height="200"></canvas>
<script src="js/drafting.js"></script>
<script type="text/javascript">
var canvasId = document.getElementById("test");
var drag1 = new DraftingByZM({
//必传参数,注意此处必须传原生对象,不能是jQuery对象
canvasByZM: canvasId
});
</script>
</body>
</html>
js组件:
/**
*
* @authors ZM
* @date 2017-09-05 18:42:09
* @version 1.0
*/
DraftingByZM = (function(){
var Obj = function(options){
this._setPara(options);
this.init();
};
Obj.prototype = {
constructor: Obj,
author: "ZM",
version: 1.0,
//入口方法
init: function(){
this._check();
this._eventListen();
},
//画圆
_check: function(){
//简单校验,查看是否支持HTML5<canvas></canvas>标签
if(this.canvasByZM.getContext){
this._circlePara();
//var _this = this;
this._drawCircle(this.$Begin);//传入参数为起始位置(0到1)
}else{
alert('Your browser does not support this function temporarily. Please upgrade your browser version as soon as possible.');
}
},
//圆的参数
_circlePara: function(){
this.context = this.canvasByZM.getContext('2d');//调用getContext方法,返回一个画布环境
this.ox = 100;//圆环在画布上的x轴坐标
this.oy = 100;//圆环在画布上的y轴坐标
this.or = 70;//圆环半径
this.br = 15;//圆珠半径
},
//根据弧度与距离计算偏移坐标
_calOffset: function(r,d){
return {x: -Math.sin(r)*d, y: Math.cos(r)*d};
},
_drawCircle: function(n){
var ctx = this.context;
//console.log(this.canvasByZM.width);
ctx.clearRect(0,0,this.canvasByZM.width,this.canvasByZM.height);
//clearRect()==>HTML5中的方法,用于擦除指定区域
//底环
ctx.strokeStyle = this.$acrossColor;//底色
ctx.lineWidth = this.$circleThinkness;//底环粗细
ctx.beginPath();//起始一条路径,或重置当前路径
ctx.arc(this.ox,this.oy,this.or,0,2*Math.PI,true);
ctx.stroke();
//有色环
ctx.strokeStyle = this.$fillColor;//颜色
ctx.lineWidth = this.$circleThinkness;//宽度
ctx.beginPath();
ctx.arc(this.ox,this.oy,this.or,0.5*Math.PI,(n*2+0.5)*Math.PI,false);
//arc(x, y, radius, startAngle, endAngle, anticlockwise):
//画一个以(x,y)为圆心的以radius为半径的圆弧(圆),
//从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成
ctx.stroke();
//中间文字
ctx.fillStyle = this.$fillColor;//颜色
ctx.font = this.$FontSize +"px Arial";//字号
ctx.textAlign = "center";
ctx.textBaseline = "middle";
//计算数值的取值区间
ctx.fillText(Math.round(n*100)+this.$FontUnit,this.ox,this.oy);
//圆珠
ctx.fillStyle = this.$fillColor;
ctx.beginPath();
var d = this._calOffset(n*2*Math.PI,this.or);
console.log(d);
ctx.arc(this.ox+d.x,this.oy+d.y,this.br,0,2*Math.PI,true);
ctx.fill();
},
//获取鼠标当前坐标
_getXY: function(e) {
var _this = this;
var et = e.touches? e.touches[0] : e;
var x = et.clientX;
var y = et.clientY;
console.log(x);
console.log(y);
return {
x : x - _this.canvasByZM.getBoundingClientRect().left + (document.body.scrollLeft || document.documentElement.scrollLeft),
y : y - _this.canvasByZM.getBoundingClientRect().top + (document.body.scrollTop || document.documentElement.scrollTop)
// x : x - _this.canvasByZM.offsetLeft + (document.body.scrollLeft || document.documentElement.scrollLeft),
// y : y - _this.canvasByZM.offsetTop + (document.body.scrollTop || document.documentElement.scrollTop)
//offsetLeft存在一定兼容性问题,其在有些浏览器中是根据父元素获取其偏移值,
//有些却是根据body元素获取偏移值。
//这里可以使用getBoundingClientRect获取对应元素到视窗的距离
}
},
//监听事件
_eventListen: function(){
//是否支持触屏
var on = ("ontouchstart" in document)? {
start: "touchstart", move: "touchmove", end: "touchend"
} : {
start: "mousedown", move: "mousemove", end: "mouseup"
};
var _this = this;
this.canvasByZM.addEventListener(on.end, function(e) {
_this.moveFlag = false;
}, false);
this.canvasByZM.addEventListener(on.start, function(e) {
_this.moveFlag = true;
}, false);
this.canvasByZM.addEventListener(on.move, function(e) {
if (_this.moveFlag) {
//获取坐标
var k = _this._getXY(e);
//计算弧度
var r = Math.atan2(k.x-_this.ox,_this.oy-k.y);
//画圆
_this._drawCircle((Math.PI+r)/(2*Math.PI));
}
}, false);
},
//设置参数
_setPara: function(option){
this.canvasByZM = option.canvasByZM;
this.$circleThinkness = option.$circleThinkness || 10;
this.$acrossColor = option.$acrossColor || "#ccc";
this.$fillColor = option.$fillColor || "#ff5151";
this.$FontUnit = option.$FontUnit || "%";
this.moveFlag = false;//开关
this.$Begin = parseFloat(option.$Begin) || 0.5;
this.$FontSize = option.$FontSize || 50;
},
remove: function(){ // 移除组件
//清除事件
this.canvasByZM.onmousedown = null;
this.canvasByZM.onmousemove = null;
this.canvasByZM.onmouseup = null;
// 释放内存
for (var i in this){
this[i] = null;
}
}
};
return Obj;
})();
//调用示例
// var drag1 = new DraftingByZM({
// //必传参数,注意此处必须传原生对象,不能是jQuery对象
// canvasByZM: $("#canvas1")[0],
// //可选参数
// $circleThinkness:10, //元环粗细
// $acrossColor:"#ccc", //底环颜色
// $fillColor:"#ff5151", //顶环颜色
// $FontUnit:"°", //数字单位
// $Begin:0.7,//(0-1) //起始位置
// $FontSize:70 //文字大小
// });
使用方法,将js组件部分存为后缀为.js的文件,引入到HTML文档中,按调用示例调用。