一個非常漂亮的圓形滑塊Round Slider,可修改成圓形進度條!
阿新 • • 發佈:2021-01-23
技術標籤:javascriptcanvasjavascript
滑塊效果圖
改動百分比效果圖
思路
首先繪製一個灰色邊框的圓
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>