В новой записи мы с вами рассмотрим как сделать круглый анимированный progressbar с использованием JavaScript. Здесь мы будет использовать canvas для создания анимации. Прогресс бар очень простой с возможностью изменения размера и цвета через дополнительные атрибуты.
HTML
Элементы прогрессбаров добавляются с помощью элемента div
и классом counter
. Здесь же мы передаем специальные атрибуты для наших элементов. data-cp-percentage
указывает процент который будет показывать progress bar, второй атрибут data-cp-color
- задает цвет.
<div class="bg-style">
<div>
<div class="counter" data-cp-percentage="45" data-cp-color="#00bfeb"> </div>
</div>
<div>
<div class="counter" data-cp-percentage="85" data-cp-color="#00bfeb"></div>
</div>
</div>
CSS
.bg-style {
display: flex;
flex-direction: row;
}
.counter {
display: inline-flex;
cursor:pointer;
width:150px;
height:150px;
max-width:100%;
position:relative;
justify-content:center;
align-items:center;
font-size: 25px;
font-weight: 500;
transition: height .2s ease-in-out;
background: #fff;
border-radius:50%;
}
.percentage {
position:absolute;
text-align:center;
top:50%;
left:0;
right:0;
vertical-align:middle;
transform:translate3d(0,-50%,0);
}
canvas {
position:absolute;
top:0;
left:0;
}
body {
text-align:center;
}
JavaScript
document.addEventListener("DOMContentLoaded", function() {
var circleProgress = (function(selector) {
var wrapper = document.querySelectorAll(selector);
Array.prototype.forEach.call(wrapper, function(wrapper, i) {
var wrapperWidth,
wrapperHeight,
percent,
innerHTML,
context,
lineWidth,
centerX,
centerY,
radius,
newPercent,
speed,
from,
to,
duration,
start,
strokeStyle,
text;
var getValues = function() {
wrapperWidth = parseInt(window.getComputedStyle(wrapper).width);
wrapperHeight = wrapperWidth;
percent = wrapper.getAttribute('data-cp-percentage');
innerHTML = '<span class="percentage"><strong>' + percent + '</strong> %</span><canvas class="circleProgressCanvas" width="' + (wrapperWidth * 2) + '" height="' + wrapperHeight * 2 + '"></canvas>';
wrapper.innerHTML = innerHTML;
text = wrapper.querySelector(".percentage");
canvas = wrapper.querySelector(".circleProgressCanvas");
wrapper.style.height = canvas.style.width = canvas.style.height = wrapperWidth + "px";
context = canvas.getContext('2d');
centerX = canvas.width / 2;
centerY = canvas.height / 2;
newPercent = 0;
speed = 1;
from = 0;
to = percent;
duration = 3000;
lineWidth = 40;
radius = canvas.width / 2 - lineWidth;
strokeStyle = wrapper.getAttribute('data-cp-color');
start = new Date().getTime();
};
function animate() {
requestAnimationFrame(animate);
var time = new Date().getTime() - start;
if (time <= duration) {
var x = easeInOutQuart(time, from, to - from, duration);
newPercent = x;
text.innerHTML = Math.round(newPercent) + " %";
drawArc();
}
}
function drawArc() {
var circleStart = 1.5 * Math.PI;
var circleEnd = circleStart + (newPercent / 50) * Math.PI;
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.arc(centerX, centerY, radius, circleStart, 4 * Math.PI, false);
context.lineWidth = lineWidth;
context.strokeStyle = "#ddd";
context.stroke();
context.beginPath();
context.arc(centerX, centerY, radius, circleStart, circleEnd, false);
context.lineWidth = lineWidth;
context.strokeStyle = strokeStyle;
context.stroke();
}
var update = function() {
getValues();
animate();
}
update();
var resizeTimer;
window.addEventListener("resize", function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
clearTimeout(resizeTimer);
start = new Date().getTime();
update();
}, 250);
});
});
//
// http://easings.net/#easeInOutQuart
// t: current time
// b: beginning value
// c: change in value
// d: duration
//
function easeInOutQuart(t, b, c, d) {
if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
});
circleProgress('.counter');
// Gibt eine Zufallszahl zwischen min (inklusive) und max (exklusive) zurück
function getRandom(min, max) {
return Math.random() * (max - min) + min;
}
});