<!DOCTYPE html> <html lang="cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>html5 canvas半圓環百分比進度條動畫特效</title> <style> .ring { width: 300px; height: 300px; display: flex; align-items: center; justify-content: center; flex-direction: column; position: relative; } .fraction { position: absolute; font-size: 30px; font-weight: bold; color: #00ABEB; } .small { font-size: 12px; font-weight: lighter; } .title { font-size: 20px; color: #00ABEB; bottom: 40px; position: absolute; } </style> </head> <body> <div class="ring"> <canvas id="tutorial"></canvas> <span class="fraction"><span class="number">0</span> <span class="small">%</span> </span> <span class="title">已領優惠券</span> </div> <script> let radius = 95 //外環半徑 let thickness = 10 //圓環厚度 let innerRadius = radius - thickness //內環半徑 let startAngle = -90 //開始角度 let endAngle = 180 //結束角度 let x = 0 //圓心x坐標 let y = 0 //圓心y坐標 let canvas = document.getElementById('tutorial'); canvas.width = 300; canvas.height = 300; let ctx = canvas.getContext('2d'); ctx.translate(canvas.width / 2, canvas.height / 2); //將繪圖原點移到畫布中央 ctx.rotate(angle2Radian(225)) //將畫布旋轉225度 ctx.fillStyle = "#eee"; //初始填充顏色 renderRing(startAngle, endAngle) //渲染函數 function renderRing(startAngle, endAngle) { ctx.beginPath(); //繪制外環 ctx.arc(x, y, radius, angle2Radian(startAngle), angle2Radian(endAngle)) //計算外環與內環第一個連接處的中心坐標 let oneCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, endAngle) //繪制外環與內環第一個連接處的圓環 ctx.arc(oneCtrlPoint.x, oneCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270)) // //繪制內環 ctx.arc(x, y, innerRadius, angle2Radian(endAngle), angle2Radian(startAngle), true) //計算外環與內環第二個連接處的中心坐標 let twoCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, startAngle) //繪制外環與內環第二個連接處的圓環 ctx.arc(twoCtrlPoint.x, twoCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270)) ctx.fill() // ctx.stroke() } //計算圓環上點的坐標 function calcRingPoint(x, y, radius, angle) { let res = {} res.x = x + radius * Math.cos(angle * Math.PI / 180) res.y = y + radius * Math.sin(angle * Math.PI / 180) return res } //弧度轉角度 function radian2Angle(radian) { return 180 * radian / Math.PI } //角度轉弧度 function angle2Radian(angle) { return angle * Math.PI / 180 } //進度條顏色 var lingrad = ctx.createLinearGradient(0, 0, 150, 0); lingrad.addColorStop(0, '#00ABEB'); lingrad.addColorStop(1, '#fff'); ctx.fillStyle = lingrad //開始繪畫 let tempAngle = startAngle let total = 1000 //總分 let now = 900 //當前分數 let percent = now / total //百分比 let twoEndAngle = percent * 270 + startAngle let step = (twoEndAngle - startAngle) / 80 let numberSpan = document.querySelector('.number') let inter = setInterval(() => { if (tempAngle > twoEndAngle) { clearInterval(inter) } else { numberSpan.innerText = percent * 100 tempAngle += step } renderRing(startAngle, tempAngle) }, 20) </script> </body> </html>
<!DOCTYPE html> <html lang="cn"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>html5 canvas半圓環百分比進度條動畫特效</title> <style> .ring { width: 300px; height: 300px; display: flex; align-items: center; justify-content: center; flex-direction: column; position: relative; } .fraction { position: absolute; font-size: 30px; font-weight: bold; color: #00ABEB; } .small { font-size: 12px; font-weight: lighter; } .title { font-size: 20px; color: #00ABEB; bottom: 40px; position: absolute; } </style> </head> <body> <div class="ring"> <canvas id="tutorial"></canvas> <span class="fraction"><span class="number">0</span> <span class="small">%</span> </span> </div> <script> let radius = 95 //外環半徑 let thickness = 10 //圓環厚度 let innerRadius = radius - thickness //內環半徑 let startAngle = 0 //開始角度 let endAngle = 360 //結束角度 let x = 0 //圓心x坐標 let y = 0 //圓心y坐標 let canvas = document.getElementById('tutorial'); canvas.width = 300; canvas.height = 300; let ctx = canvas.getContext('2d'); ctx.translate(canvas.width / 2, canvas.height / 2); //將繪圖原點移到畫布中央 ctx.rotate(angle2Radian(225)) //將畫布旋轉225度 ctx.fillStyle = "#eee"; //初始填充顏色 renderRing(startAngle, endAngle) //渲染函數 function renderRing(startAngle, endAngle) { ctx.beginPath(); //繪制外環 ctx.arc(x, y, radius, angle2Radian(startAngle), angle2Radian(endAngle)) //計算外環與內環第一個連接處的中心坐標 let oneCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, endAngle) //繪制外環與內環第一個連接處的圓環 ctx.arc(oneCtrlPoint.x, oneCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270)) // //繪制內環 ctx.arc(x, y, innerRadius, angle2Radian(endAngle), angle2Radian(startAngle), true) //計算外環與內環第二個連接處的中心坐標 let twoCtrlPoint = calcRingPoint(x, y, innerRadius + thickness / 2, startAngle) //繪制外環與內環第二個連接處的圓環 ctx.arc(twoCtrlPoint.x, twoCtrlPoint.y, thickness / 2, angle2Radian(-90), angle2Radian(270)) ctx.fill() // ctx.stroke() } //計算圓環上點的坐標 function calcRingPoint(x, y, radius, angle) { let res = {} res.x = x + radius * Math.cos(angle * Math.PI / 180) res.y = y + radius * Math.sin(angle * Math.PI / 180) return res } //弧度轉角度 function radian2Angle(radian) { return 180 * radian / Math.PI } //角度轉弧度 function angle2Radian(angle) { return angle * Math.PI / 180 } //進度條顏色 var lingrad = ctx.createLinearGradient(0, 0, 150, 0); lingrad.addColorStop(0, '#00ABEB'); lingrad.addColorStop(1, '#fff'); ctx.fillStyle = lingrad //開始繪畫 let tempAngle = startAngle let total = 1000 //總分 let now = 1000 //當前分數 let percent = now / total //百分比 let twoEndAngle = percent * 360 + startAngle let step = (twoEndAngle - startAngle) / 80 let numberSpan = document.querySelector('.number') let inter = setInterval(() => { if (tempAngle > twoEndAngle) { clearInterval(inter) } else { numberSpan.innerText = percent * 100 tempAngle += step } renderRing(startAngle, tempAngle) }, 20) </script> </body> </html>