滑块效果图
改动百分比效果图
思路
首先绘制一个灰色边框的圆
ctx.translate(150,150);//坐标定位至150,150处
ctx.beginPath();
ctx.lineWidth='20';
ctx.strokeStyle='#EEEEEE';
ctx.arc(0,0,radius,0,2*Math.PI);//绘制一个完整的圆
ctx.stroke();
再绘制一个半径一样、圆心一样蓝色的圆
ctx.beginPath();
ctx.rotate(-Math.PI);//逆时针选择一个π
ctx.lineWidth='20';
ctx.strokeStyle='#6699FF';
ctx.arc(0,0,radius,0,move/180*Math.PI);//根据move的大小绘制圆弧
ctx.stroke();
在圆弧上绘制一个小圆作为指示器
//绘制指针小圆
ctx.save();
ctx.rotate(move/180*Math.PI);//根据move的大小旋转
ctx.beginPath();
ctx.strokeStyle='gray';
ctx.lineWidth='2';
ctx.arc(radius,0,11,0,2*Math.PI);
ctx.fillStyle='white';
ctx.fill();
ctx.stroke();
ctx.restore();
在圆心出放置一个DIV,可以做为百分比显示器
<div id='percent'>
<input type='text' value=50 oninput="doInput(this)" style="display:none;" >
<p style="text-align: center;color:#66AFFF;">50</p>
</div>
设置这个百分比的样式
#percent{
width: 50px;
height: 50px;
position: absolute;
left: 130px;
top: 130px;
font-size: 30px;
cursor: pointer;
}
#percent input{
width: 50px;
height: 50px;
border-radius: 10px;
border: 1px solid #EEEEEE;
text-align:center;
font-size: 30px;
}
如何来做到点击
首先给canvas画布添加一个点击事件,当鼠标点击的时候,我们可以得到一个坐标X,Y,根据勾股定理可以算出这个点到圆心的距离,如果在一定的范围呢,则认为是点击到圆弧上,否则不触发。
//根据勾股定理计算半径
var conputedRadius = Math.sqrt((e.clientX-tranX)*(e.clientX-tranX)+(e.clientY-tranY)*(e.clientY-tranY));
//处于90-110的被认为是有效点击
if(conputedRadius>90 && conputedRadius<110){//点击的有效性
//计算角度
var jiaodu=Math.round(Math.asin((e.clientY-tranY)/conputedRadius)/Math.PI*180);//asin
var jiaodu1=Math.round(Math.acos((e.clientX-tranX)/conputedRadius)/Math.PI*180);//acos
var jiaodu2 = jiaodu>0?jiaodu1:(360-jiaodu1); //最终角度
//因为已经逆时针旋转了180度,所以还要处理
jiaodu2 = jiaodu2<180?(jiaodu2+180):(jiaodu2-180);
end=jiaodu2;//最终计算的鼠标点击位置的正真角度
//显示指数
percent.children[1].innerText=Math.round(end/360*100);
percent.children[0].value=Math.round(end/360*100);
//执行动画
doAnimate();
}else{
return;
}
完整代码
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="GBK">
<title></title>
<style>
*{
margin: 0;
padding: 0;
}
canvas{
border:1px solid ;
}
#percent{
width: 50px;
height: 50px;
position: absolute;
left: 130px;
top: 130px;
font-size: 30px;
cursor: pointer;
}
#percent input{
width: 50px;
height: 50px;
border-radius: 10px;
border: 1px solid #EEEEEE;
text-align:center;
font-size: 30px;
}
</style>
</head>
<body>
<canvas id='canvas'></canvas>
<div id='percent'>
<input type='text' value=50 oninput="doInput(this)" style="display:none;" >
<p style="text-align: center;color:#66AFFF;">50</p>
</div>
<script type="text/javascript">
var percent = document.getElementById('percent');
var canvas = document.getElementById('canvas');
canvas.width='600';
canvas.height='400';
var ctx = canvas.getContext("2d");
var raf,
timmer,//定时函数的计数器
move=180,//移动的位置,开始默认180度
end=360,//结束位置,最大360
radius=100,//半径
dis=10,//每次动画执行转动的角度
dir=1, //方向,负1表示逆时针
tranX=150,//圆心位置X
tranY=150;//圆心位置Y
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);//清理画布
ctx.save();
ctx.translate(tranX,tranY);//坐标定位至150,150处
ctx.beginPath();
ctx.lineWidth='20';
ctx.strokeStyle='#EEEEEE';
ctx.arc(0,0,radius,0,2*Math.PI);//绘制一个完整的圆
ctx.stroke();
//绘制可以点击变化的圆
ctx.beginPath();
ctx.rotate(-Math.PI);//逆时针选择一个π
ctx.lineWidth='20';
ctx.strokeStyle='#6699FF';
ctx.arc(0,0,radius,0,move/180*Math.PI);//根据move的大小绘制圆弧
ctx.stroke();
//绘制指针小圆
ctx.save();
ctx.rotate(move/180*Math.PI);//根据move的大小旋转
ctx.beginPath();
ctx.strokeStyle='gray';
ctx.lineWidth='2';
ctx.arc(radius,0,11,0,2*Math.PI);
ctx.fillStyle='white';
ctx.fill();
ctx.stroke();
ctx.restore();
ctx.restore();
raf = window.requestAnimationFrame(draw);
}
canvas.addEventListener('click',function(e){
//根据勾股定理计算半径
var conputedRadius = Math.sqrt((e.clientX-tranX)*(e.clientX-tranX)+(e.clientY-tranY)*(e.clientY-tranY));
//处于90-110的被认为是有效点击
if(conputedRadius>90 && conputedRadius<110){//点击的有效性
//计算角度
var jiaodu=Math.round(Math.asin((e.clientY-tranY)/conputedRadius)/Math.PI*180);//asin
var jiaodu1=Math.round(Math.acos((e.clientX-tranX)/conputedRadius)/Math.PI*180);//acos
var jiaodu2 = jiaodu>0?jiaodu1:(360-jiaodu1); //最终角度
//因为已经逆时针旋转了180度,所以还要处理
jiaodu2 = jiaodu2<180?(jiaodu2+180):(jiaodu2-180);
end=jiaodu2;//最终计算的鼠标点击位置的正真角度
//显示指数
percent.children[1].innerText=Math.round(end/360*100);
percent.children[0].value=Math.round(end/360*100);
//执行动画
doAnimate();
}else{
return;
}
})
var flag=false;//动画执行标示
function doAnimate(){
//判断动画方向
dir=end>move?1:-1;
//执行动画
if(flag) return;//如果正在执行动画,不做处理
flag=true;//设置为执行动画
timmer=setInterval(function(){
if(end==move){//当执行到预定位置,则清除定时器
clearInterval(timmer);
flag=false;//取消执行状态
return;
}
if(Math.abs(end-move)<dis){//如果距离目标位置的角度不足一次递增了,就直接就move设置为最终位置
move = end;
return ;
}
move+=dir*dis;//每次定时任务的执行将增加一定的角度
},10)
raf = window.requestAnimationFrame(draw);
}
function doClick(e){
var p=percent.children[1],input=percent.children[0];
var e=e||window.event;
var target=e.currentTarget;
e.stopPropagation();//阻止冒泡
if(target.tagName&&target.tagName.toUpperCase()==='DIV'){
if(input.style.display==''){
return;
}
//显示input
input.style.display='';
p.style.display='none';
input.value=p.innerText;
input.focus();
}else{
if(input.style.display==''){
p.style.display='';
//隐藏input
input.style.display='none';
p.innerText=input.value;
//处理百分比
editPercent();
}
}
}
function editPercent(){
var p=percent.children[1],input=percent.children[0];
//设置动画的end
end = p.innerText/100*360;
//执行动画
doAnimate();
}
//控制文本输入
function doInput(obj){
obj.value=obj.value.replace(/[^\d]/g,'');
var value = parseInt(obj.value);
if(value>100){
obj.value=100;
}else if(value<0){
obj.value=0;
}
}
percent.addEventListener('click',doClick);
document.addEventListener('click',doClick);
</script>
</body>
</html>