Animating a circular border using Javascript/jQuery [duplicate] - javascript

I have searched this website to find progress bars, but the ones I have been able to found show animated circles that go to the full 100%.
I would like it to stop at certain percentages like in the screenshot below. Is there any way I can do that using only CSS?

I created a fiddle using only CSS.
.wrapper {
width: 100px; /* Set the size of the progress bar */
height: 100px;
position: absolute; /* Enable clipping */
clip: rect(0px, 100px, 100px, 50px); /* Hide half of the progress bar */
}
/* Set the sizes of the elements that make up the progress bar */
.circle {
width: 80px;
height: 80px;
border: 10px solid green;
border-radius: 50px;
position: absolute;
clip: rect(0px, 50px, 100px, 0px);
}
/* Using the data attributes for the animation selectors. */
/* Base settings for all animated elements */
div[data-anim~=base] {
-webkit-animation-iteration-count: 1; /* Only run once */
-webkit-animation-fill-mode: forwards; /* Hold the last keyframe */
-webkit-animation-timing-function:linear; /* Linear animation */
}
.wrapper[data-anim~=wrapper] {
-webkit-animation-duration: 0.01s; /* Complete keyframes asap */
-webkit-animation-delay: 3s; /* Wait half of the animation */
-webkit-animation-name: close-wrapper; /* Keyframes name */
}
.circle[data-anim~=left] {
-webkit-animation-duration: 6s; /* Full animation time */
-webkit-animation-name: left-spin;
}
.circle[data-anim~=right] {
-webkit-animation-duration: 3s; /* Half animation time */
-webkit-animation-name: right-spin;
}
/* Rotate the right side of the progress bar from 0 to 180 degrees */
#-webkit-keyframes right-spin {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
}
}
/* Rotate the left side of the progress bar from 0 to 360 degrees */
#-webkit-keyframes left-spin {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
/* Set the wrapper clip to auto, effectively removing the clip */
#-webkit-keyframes close-wrapper {
to {
clip: rect(auto, auto, auto, auto);
}
}
<div class="wrapper" data-anim="base wrapper">
<div class="circle" data-anim="base left"></div>
<div class="circle" data-anim="base right"></div>
</div>
Also check this fiddle here (CSS only)
#import url(http://fonts.googleapis.com/css?family=Josefin+Sans:100,300,400);
.arc1 {
width: 160px;
height: 160px;
background: #00a0db;
-webkit-transform-origin: -31% 61%;
margin-left: -30px;
margin-top: 20px;
-webkit-transform: translate(-54px,50px);
-moz-transform: translate(-54px,50px);
-o-transform: translate(-54px,50px);
}
.arc2 {
width: 160px;
height: 160px;
background: #00a0db;
-webkit-transform: skew(45deg,0deg);
-moz-transform: skew(45deg,0deg);
-o-transform: skew(45deg,0deg);
margin-left: -180px;
margin-top: -90px;
position: absolute;
-webkit-transition: all .5s linear;
-moz-transition: all .5s linear;
-o-transition: all .5s linear;
}
.arc-container:hover .arc2 {
margin-left: -50px;
-webkit-transform: skew(-20deg,0deg);
-moz-transform: skew(-20deg,0deg);
-o-transform: skew(-20deg,0deg);
}
.arc-wrapper {
width: 150px;
height: 150px;
border-radius:150px;
background: #424242;
overflow:hidden;
left: 50px;
top: 50px;
position: absolute;
}
.arc-hider {
width: 150px;
height: 150px;
border-radius: 150px;
border: 50px solid #e9e9e9;
position:absolute;
z-index:5;
box-shadow:inset 0px 0px 20px rgba(0,0,0,0.7);
}
.arc-inset {
font-family: "Josefin Sans";
font-weight: 100;
position: absolute;
font-size: 413px;
margin-top: -64px;
z-index: 5;
left: 30px;
line-height: 327px;
height: 280px;
-webkit-mask-image: -webkit-linear-gradient(top, rgba(0,0,0,1), rgba(0,0,0,0.2));
}
.arc-lowerInset {
font-family: "Josefin Sans";
font-weight: 100;
position: absolute;
font-size: 413px;
margin-top: -64px;
z-index: 5;
left: 30px;
line-height: 327px;
height: 280px;
color: white;
-webkit-mask-image: -webkit-linear-gradient(top, rgba(0,0,0,0.2), rgba(0,0,0,1));
}
.arc-overlay {
width: 100px;
height: 100px;
background-image: linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%);
background-image: -o-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%);
background-image: -moz-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%);
background-image: -webkit-linear-gradient(bottom, rgb(217,217,217) 10%, rgb(245,245,245) 90%, rgb(253,253,253) 100%);
padding-left: 32px;
box-sizing: border-box;
-moz-box-sizing: border-box;
line-height: 100px;
font-family: sans-serif;
font-weight: 400;
text-shadow: 0 1px 0 #fff;
font-size: 22px;
border-radius: 100px;
position: absolute;
z-index: 5;
top: 75px;
left: 75px;
box-shadow:0px 0px 20px rgba(0,0,0,0.7);
}
.arc-container {
position: relative;
background: #e9e9e9;
height: 250px;
width: 250px;
}
<div class="arc-container">
<div class="arc-hider"></div>
<div class="arc-inset">
o
</div>
<div class="arc-lowerInset">
o
</div>
<div class="arc-overlay">
35%
</div>
<div class="arc-wrapper">
<div class="arc2"></div>
<div class="arc1"></div>
</div>
</div>
Or this beautiful round progress bar with HTML5, CSS3 and JavaScript.

What about that?
HTML
<div class="chart" id="graph" data-percent="88"></div>
Javascript
var el = document.getElementById('graph'); // get canvas
var options = {
percent: el.getAttribute('data-percent') || 25,
size: el.getAttribute('data-size') || 220,
lineWidth: el.getAttribute('data-line') || 15,
rotate: el.getAttribute('data-rotate') || 0
}
var canvas = document.createElement('canvas');
var span = document.createElement('span');
span.textContent = options.percent + '%';
if (typeof(G_vmlCanvasManager) !== 'undefined') {
G_vmlCanvasManager.initElement(canvas);
}
var ctx = canvas.getContext('2d');
canvas.width = canvas.height = options.size;
el.appendChild(span);
el.appendChild(canvas);
ctx.translate(options.size / 2, options.size / 2); // change center
ctx.rotate((-1 / 2 + options.rotate / 180) * Math.PI); // rotate -90 deg
//imd = ctx.getImageData(0, 0, 240, 240);
var radius = (options.size - options.lineWidth) / 2;
var drawCircle = function(color, lineWidth, percent) {
percent = Math.min(Math.max(0, percent || 1), 1);
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2 * percent, false);
ctx.strokeStyle = color;
ctx.lineCap = 'round'; // butt, round or square
ctx.lineWidth = lineWidth
ctx.stroke();
};
drawCircle('#efefef', options.lineWidth, 100 / 100);
drawCircle('#555555', options.lineWidth, options.percent / 100);
and CSS
div {
position:relative;
margin:80px;
width:220px; height:220px;
}
canvas {
display: block;
position:absolute;
top:0;
left:0;
}
span {
color:#555;
display:block;
line-height:220px;
text-align:center;
width:220px;
font-family:sans-serif;
font-size:40px;
font-weight:100;
margin-left:5px;
}
http://jsfiddle.net/Aapn8/3410/
Basic code was taken from Simple PIE Chart http://rendro.github.io/easy-pie-chart/

Check this out :)
I made this one using conic-gradient.
background: conic-gradient(
SomeColor1 80%,
SomeColor2 80%
);
You can create a pie chart using conic-gradient.
div {
background: conic-gradient(
red 36deg, orange 36deg 170deg, yellow 170deg);
border-radius: 50%
}
I select only two colors for the pie chart.
background: conic-gradient(
rgb(3, 133, 255) 80%,
rgb(242, 242, 242) 80%
);
then place a div on top of the pie chart to make it looks like a circular progress indicator. Then set progress using HTML DOM innerHTML option.
Then you can use incrementProgress() and decrementProgress() fuctions to change progress dynamically.
Follow my complete example to get some idea :)
You can make upload/download progress indicators, charts for dashboards, etc. using this.
<html>
<head>
<style>
body {
display: flex;
align-items: center;
justify-content: center;
}
#progress-spinner {
border-radius: 50%;
height: 100px;
width: 100px;
}
#middle-circle {
position: absolute;
border-radius: 50%;
height: 80px;
width: 80px;
background-color: rgb(248, 248, 248);
display: flex;
align-items: center;
justify-content: center;
font-size: large;
font-weight: bold;
}
</style>
</head>
<body>
<div
style="
position: relative;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
"
>
<div
style="
position: relative;
display: flex;
justify-content: center;
align-items: center;
"
>
<div id="middle-circle"></div>
<div id="progress-spinner"></div>
</div>
<div style="margin-top: 30px">
<button type="button" id="incbtn">+</button>
<button type="button" id="decbtn">-</button>
</div>
</div>
<script>
var progress = 0;
document
.getElementById("incbtn")
.addEventListener("click", incrementProgress);
document
.getElementById("decbtn")
.addEventListener("click", decrementProgress);
function incrementProgress() {
if (progress != 100) {
progress = progress + 10;
console.log(progress);
setProgress();
}
}
function decrementProgress() {
if (progress != 0) {
progress = progress - 10;
console.log(progress);
setProgress();
}
}
function setProgress() {
document.getElementById("progress-spinner").style.background =
"conic-gradient(rgb(3, 133, 255) " +
progress +
"%,rgb(242, 242, 242) " +
progress +
"%)";
document.getElementById("middle-circle").innerHTML =
progress.toString() + "%";
}
window.onload = function () {
setProgress();
};
</script>
</body>
</html>

Another pure css based solution that is based on two clipped rounded elements that i rotate to get to the right angle:
http://jsfiddle.net/maayan/byT76/
That's the basic css that enables it:
.clip1 {
position:absolute;
top:0;left:0;
width:200px;
height:200px;
clip:rect(0px,200px,200px,100px);
}
.slice1 {
position:absolute;
width:200px;
height:200px;
clip:rect(0px,100px,200px,0px);
-moz-border-radius:100px;
-webkit-border-radius:100px;
border-radius:100px;
background-color:#f7e5e1;
border-color:#f7e5e1;
-moz-transform:rotate(0);
-webkit-transform:rotate(0);
-o-transform:rotate(0);
transform:rotate(0);
}
.clip2
{
position:absolute;
top:0;left:0;
width:200px;
height:200px;
clip:rect(0,100px,200px,0px);
}
.slice2
{
position:absolute;
width:200px;
height:200px;
clip:rect(0px,200px,200px,100px);
-moz-border-radius:100px;
-webkit-border-radius:100px;
border-radius:100px;
background-color:#f7e5e1;
border-color:#f7e5e1;
-moz-transform:rotate(0);
-webkit-transform:rotate(0);
-o-transform:rotate(0);
transform:rotate(0);
}
and the js rotates it as required.
quite easy to understand..
Hope it helps,
Maayan

A minimalistic approach using just one element and a couple of attributes:
Use data-progress to define the internal label and --progress to define the progress from 0deg to 360deg.
<div data-progress="36" style="--progress: 36deg;">36%</div>
div {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
background: conic-gradient(red var(--progress), gray 0deg);
font-size: 0;
}
div::after {
content: attr(data-progress) '%';
display: flex;
justify-content: center;
flex-direction: column;
width: 100%;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
<div data-progress="36" style="--progress: 36deg;">36%</div>
Here's a naïve approach to the animation, again all CSS, no JS and just one element:
div {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
background: conic-gradient(red var(--progress), gray 0deg);
font-size: 0;
animation: .4s ease-out turn_in reverse;
}
div::after {
content: attr(data-progress);
display: flex;
justify-content: center;
flex-direction: column;
width: 100%;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
#keyframes turn_in {
5% {
background: conic-gradient(red calc(var(--progress) * .95), gray 0deg);
}
10% {
background: conic-gradient(red calc(var(--progress) * .9), gray 0deg);
}
15% {
background: conic-gradient(red calc(var(--progress) * .85), gray 0deg);
}
20% {
background: conic-gradient(red calc(var(--progress) * .8), gray 0deg);
}
25% {
background: conic-gradient(red calc(var(--progress) * .75), gray 0deg);
}
30% {
background: conic-gradient(red calc(var(--progress) * .7), gray 0deg);
}
35% {
background: conic-gradient(red calc(var(--progress) * .65), gray 0deg);
}
40% {
background: conic-gradient(red calc(var(--progress) * .6), gray 0deg);
}
45% {
background: conic-gradient(red calc(var(--progress) * .55), gray 0deg);
}
50% {
background: conic-gradient(red calc(var(--progress) * .5), gray 0deg);
}
55% {
background: conic-gradient(red calc(var(--progress) * .45), gray 0deg);
}
60% {
background: conic-gradient(red calc(var(--progress) * .4), gray 0deg);
}
65% {
background: conic-gradient(red calc(var(--progress) * .35), gray 0deg);
}
70% {
background: conic-gradient(red calc(var(--progress) * 0.3), gray 0deg);
}
75% {
background: conic-gradient(red calc(var(--progress) * 0.25), gray 0deg);
}
80% {
background: conic-gradient(red calc(var(--progress) * .2), gray 0deg);
}
85% {
background: conic-gradient(red calc(var(--progress) * .15), gray 0deg);
}
90% {
background: conic-gradient(red calc(var(--progress) * .1), gray 0deg);
}
95% {
background: conic-gradient(red calc(var(--progress) * .05), gray 0deg);
}
100% {
background: conic-gradient(gray 0deg);
}
}
<div data-progress="85%" style="--progress: 85%;">85%</div>
Disclaimer: cross-browsing not tested.

A different idea with new #property. See the support table
#property --a {
syntax: '<angle>';
inherits: false;
initial-value: 90deg;
}
.circle {
width: 120px;
height: 120px;
padding: 12px;
box-sizing: border-box;
-webkit-mask:
conic-gradient(#000 var(--a), transparent var(--a)),
linear-gradient(#000, #000) content-box;
-webkit-mask-composite: source-out;
mask-composite: subtract;
background: tomato;
border-radius: 50%;
animation: progress 1s .3s linear forwards;
}
#keyframes progress {
to {
--a: 250deg;
}
}
<div class="circle"></div>
And I saw a more powerful example by Alvaro Montoro. Be sure to check this out.

acceding your data you can change process like <div ... data-num="50"> output 50% that go to the show fully animated circles and number.
change in data-num="/* 0-100 */".
you can add multiple process like 5,10.
using Javascript,CSS,Html with animated circle and number.
Output
Code
let items = document.querySelectorAll('.progress-item');
const counters = Array(items.length);
const intervals = Array(items.length);
counters.fill(0);
items.forEach((number,index) => {
intervals[index] = setInterval(() => {
if(counters[index] == parseInt(number.dataset.num)){
clearInterval(intervals[index]);
}else{
counters[index] += 1;
number.style.background = "conic-gradient(red calc(" + counters[index] + "%), gray 0deg)";
number.setAttribute('data-value', counters[index] + "%");
number.innerHTML = counters[index] + "%";
}
}, 15);
});
#progress{
display: flex;
justify-content: space-around;
}
.progress-item {
display: flex;
width: 100px;
height: 100px;
border-radius: 50%;
font-size: 0;
animation: .4s ease-out reverse;
}
.progress-item::after {
content: attr(data-value);
display: flex;
justify-content: center;
flex-direction: column;
width: 100px;
margin: 10px;
border-radius: 50%;
background: white;
font-size: 1rem;
text-align: center;
}
<div id="progress" >
<div data-num="40" class="progress-item">sd</div>
<div data-num="80" class="progress-item">sd</div>
<div data-num="57" class="progress-item">sd</div>
<div data-num="83" class="progress-item">sd</div>
<div data-num="90" class="progress-item">ds</div>
</div>

Flexible SVG solution for radial progress-bar (CSS only): the solution in calculating(via calc) border length of circle inside SVG.
Progress-circle in samples is overlay on element, and may be transparent.
jQuery(function($){
setTimeout(() => $('#element1 [data-role="radial-progress"]').css('--progress-percent', '100'), 1000);
$('#element2 [data-role="radial-progress"]').css('--progress-percent', '80');
$('#element3 [data-role="radial-progress"]').css('--progress-percent', '100');
let progress4 = 0;
let progress4incrementor = setInterval(() => {
progress4++;
$('#element4 .value').html(progress4 + '%');
$('#element4 [data-role="radial-progress"]').css('--progress-percent', progress4.toString());
if (progress4 >= 100) clearInterval(progress4incrementor);
}, 100);
});
.element
{
position: relative;
}
[data-role="radial-progress"]
{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 1;
--progress-percent: 0;
--progress-color: #CC000077;
--progress-bar-width: 100%;
}
[data-role="radial-progress"] > circle
{
stroke-width: var(--progress-bar-width);
stroke-dasharray: calc(100% * 3.141592);
stroke-dashoffset: calc(100% * (100 - var(--progress-percent))/100 * 3.141592);
stroke: var(--progress-color);
}
/*Just for animate --data-percent */
#element1 [data-role="radial-progress"] > circle
{
transition: stroke-dashoffset 4s linear;
}
#element2 [data-role="radial-progress"] > circle
{
transition: stroke-dashoffset 2s linear;
}
#element3 [data-role="radial-progress"] > circle
{
transition: stroke-dashoffset 6s linear;
}
#element4 [data-role="radial-progress"] > circle
{
transition: stroke-dashoffset 0.1s linear;
}
/*Сode that does not depend on radial-progress*/
.element
{
background-image: url(https://static.wikia.nocookie.net/dune/images/2/2f/Duneii-wind-trap.jpg/revision/latest);
background-size: 100% 100%;
display: inline-block;
width: 180px;
height: 110px;
border: 2px solid red;
text-align: center;
color: red;
}
#element3
{
width: 110px;
}
#element3 [data-role="radial-progress"]
{
transform: rotate(-90deg);
}
#element4
{
display: inline-flex;
align-items: center;
justify-content: center;
}
#element4 .value
{
font-size: 2em;
font-weight: bold;
z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="element1" class="element">
Content
<svg data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>
<div id="element2" class="element">
Content
<svg style="--progress-percent:30" data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>
<div id="element3" class="element">
Content
<svg style="--progress-bar-width:10px;--progress-color:red;" data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="44%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>
<div id="element4" class="element">
<span class="value">0%</span>
<svg data-role="radial-progress" width="100%" height="100%" viewPort="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg"><circle r="50%" cx="50%" cy="50%" fill="transparent"></circle></svg>
</div>

Related

How to create a square box in which the border of the box will be filled by color depending on the value given on the box?

Just like the above image or an idea or reference to achieve this design, I appreciate the help or suggestion given by community thank you
I have got reference of progress bar which is circular but not able find an approach to solve it.
const boxes = document.querySelectorAll(".box");
const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'violet']
boxes.forEach((box) => {
const insideContent = box.innerText;
box.style.border = `6px solid ${colors[insideContent]}`
})
#app {
display: flex;
}
.box {
width: 50px;
height: 50px;
margin: 10px;
background-color: cyan;
display: flex;
justify-content: center;
align-items: center;
}
<div id="app">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
</div>
As per your question I think this is what you are trying to achieve.
First define a pseudo class root
:root {
--color-val: blue;
}
Note: In order to use the --color-val you need to write it as color: var(--color-var) in CSS
Second use JavaScript to update the variable --color-val
let colors =
var root = document.querySelector(':root');
const delay = ms => new Promise(res => setTimeout(res, ms));
const colorChange = async () => {
await delay(1000);
color = colors[Math.floor(Math.random() * colors.length)]
console.log(color)
root.style.setProperty('--color-val', color);
};
colorChange()
Note:
Add the color list you want to select from or go to CodePen for a list of 1000+ hex codes.
Promise are used for asynchronous function and can be skipped by using setTimeOut for a delayed loop or if used with another eventlistener.
I apologize if I misunderstood the question. Wrote in a hurry and without beautyful visualisation, if you disassemble the principle, you can customize it.
h1 {
display: block;
margin:0 auto;
text-align: center;
padding-top:20%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
z-index: 110;
margin:0;
margin: -10px;
}
.top {
display:block;
background-color: green;
height: 24px;
width: 150px; /* gorizontal top */
animation: top 1s linear;
animation-fill-mode: forwards;
}
#keyframes top {
0% {
width: 0px;
}
100% {
width: 150px;
}
}
.right {
background-color: green;
height: 0%;/* right */
width: 32px;
animation: right 1s linear;
animation-fill-mode: forwards;
animation-delay: 1s;
z-index: 10;
}
#keyframes right {
0% {
height: 0%;
}
100% {
height: 100%;
}
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.bottom {
position: absolute;
top: 123px;
left: 150px;
background-color: green;
width: 0px;
height: 27px;
z-index: 10;
animation: bottom 1s linear;
animation-fill-mode: forwards;
animation-delay: 2s;
/* animation-direction: reverse; */
}
#keyframes bottom {
0% {
transform: translate(0,0);
}
100% {
transform: translate(-250px,0);
-webkit-transform: translate(-250px,0); /** Safari & Chrome **/
-o-transform: translate(-250px,0); /** Opera **/
-moz-transform: translate(-250px,0); /** Firefox **/
width: 250px;
}
}
.left {
position: absolute;
top: 122px;
background-color: green;
width: 25px;
height: 0px;
animation: left 1s linear;
animation-fill-mode: forwards;
animation-delay: 3s;
}
#keyframes left {
0% {
transform: translate(0,0);
}
100% {
transform: translate(0,-250px);
-webkit-transform: translate(0,-250px); /** Safari & Chrome **/
-o-transform: translate(0,-250px); /** Opera **/
-moz-transform: translate(0,-250px); /** Firefox **/
height: 277px;
}
}
<div class='head'>
<div class='container'>
<div class='top'></div>
<div class='box'>
<h1 id='timer'>
1
</h1>
</div>
<div class='right'></div>
<div class='bottom'></div>
<div class='left'></div>
</div>
</div>
<script type="text/javascript">
init()
function init()
{
sec = 0;
setInterval(tick, 1000);
}
function tick()
{ if (sec<3) { sec++
document.getElementById("timer").
childNodes[0].nodeValue = sec;
} else {
clearInterval(0);
}
}
</script>
Also, instead of the SetInterval script, you can take values from your block width and height styles and output a mathematical calculation in h1 instead of a stopwatch.
upd: After your comment, I decided to do what I wrote about above. You can play with values and math, I add a snippet of another solution that changes the progress bar from the entered values within the entered range. (of course, it would be easier on react than on pure js)
function grade () {
let grade = +document.getElementById("grade").value;
let range = +document.getElementById("range").value;
document.getElementById("timer").innerHTML = `${grade}/${range}`;
progress(grade,range)
}
function progress (value, grade) {
document.getElementById('1').style.backgroundColor = `white`
document.getElementById("left").className = "noactive";
document.getElementById('top').style.width = `0%`
document.getElementById('right').style.height = `0%`
document.getElementById('bottom').style.width = `0%`
let GradeValuSide = grade/4;
if (value <= GradeValuSide) {
document.getElementById('top').style.width =
`${value/GradeValuSide*100}%`
} else if (value > GradeValuSide && value <= (GradeValuSide*2)) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height =
`${(value-GradeValuSide)/GradeValuSide*100}%`
} else if (value >= grade/2 && value < (grade/4)*3) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width =
`${((((value-(GradeValuSide*2)) / GradeValuSide) *100) / 100) *27}%`
} else if (value >= grade-(grade/4) /* && value < value + 1 */) {
document.getElementById('top').style.width = `100%`
document.getElementById('right').style.height = `100%`
document.getElementById('bottom').style.width = `100%`
document.getElementById('1').style.backgroundColor = `green`
document.getElementById("left").className = "left";
document.getElementById('left').style.height =
`${(40 - (40 * ((((value-(GradeValuSide*3)) * 100) / GradeValuSide)/ 100)))}%`
}
}
h1 {
font-size:20px;
position: absolute;
left: 40px;
display: block;
margin: 0 auto;
align-items: center;
padding-top:10%;
}
.container {
display:flex;
width: 150px;
height: 150px;
border: 1px solid black;
margin:0;
margin: -10px;
}
div.top {
display:block;
background-color: green;
height: 24px;
width: 0%; /* gorizontal top */
z-index:999;
}
div.right {
position:relative;
background-color: green;
height: 0%;/* right */
width: 32px;
z-index: 9999;
}
.box {
position: fixed;
top: 32.5px;
left: 32.5px;
background-color:white;
width: 100px;
height: 100px;
border: 1px solid black;
margin: auto;
z-index: 120;
margin: -10px -10px;
}
.wrap{
position: relative;
}
div.bottom {
position: absolute;
top: 123px;
background-color: green;
width: 0%; /* 27 = 100% */
height: 27px;
float: right;
right: 78vw;
z-index: 100;
}
div.left {
position: absolute;
background-color: white;
width: 23px;
height: 40%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
div.noactive {
position: absolute;
background-color: white;
width: 23px;
height: 0%;
top: 23px;
bottom: 10px;
left: 0;
float: top;
}
.items {
margin-top: 50px;
text-align: center;
}
.grade,
.value {
height: 15px;
width: 50px;
align-items: center;
}
<div class='head'>
<div id='1' class='container'>
<div id='top' class='top'></div>
<div class='box'>
<h1 id='timer'>1</h1>
<div class='items'>
value<input id='grade' class='grade' type=number oninput="grade()"/>
range<input id='range' class='value' type=number oninput="grade()"/>
</div>
</div>
<div id='right' class='right'></div>
<div id='bottom' class='bottom'></div>
<div id='left' class='noactive'></div>
</div>
</div>
<script src='app.js'></script>

Why I can't show a div?

I am trying to show a heart of id heart when the button of id botao2 is clicked, but when I try to set display = "visible" the value of it didn´t change.
I also don't know why, but when I try to get the height, width or set the value of x and y of any button I can't, the return is just none.
function move(el){
let div = document.getElementsByClassName("container-button");
let width = Math.ceil(el.clientWidth);
let height = Math.ceil(el.clientHeight);
let wdh = Math.floor(div[0].clientHeight);
let wdw = Math.floor(div[0].clientWidth);
var changeTop = Math.floor((Math.random() * (wdh - height + 1)));
var changeLeft = Math.floor((Math.random() * (wdw - width + 1))) ;
console.log("Height: " + changeTop + " Width: " + changeLeft);
el.style.marginTop = changeTop + "px";
el.style.marginLeft = changeLeft + "px";
}
function setHeart(element){
document.getElementById("botao").style.display = "none";
document.getElementById("botao2").style.display = "none";
document.getElementById("heart").style.display = "visible";
}
body{
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
background-image: linear-gradient(to top left, rgba(255,0,0,0), rgba(255,0,0,1));
}
.container {
flex-direction: row;
justify-content: center;
align-items: center;
width: 700px;
margin: 0 auto;
display: flex;
}
.wrap {
/* Quebra a linha assim que um dos flex itens não puder mais ser compactado. */
flex-wrap: wrap;
}
.item {
/* O flex: 1; é necessário para que cada item se expanda ocupando o tamanho máximo do container. */
flex: 1;
background: white;
font-size: 1.5em;
border-radius: 10px;
width: 80px;
height: 40px;
border: none;
color: red;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
top: 50%;
}
.container-button {
align-content: center;
width: 500px;
height: 500px;
display: flex;
margin-top: 25%;
margin-left: 35%;
}
h1 {
text-align: center;
color: white;
}
.heart {
background: red;
position: relative;
height: 100px;
width:100px;
/* Animation */
transform: rotate(-45deg) scale(1);
animation: pulse 2s linear infinite;
}
#heart {
display: none;
}
.heart::after {
/* background:blue; */
background:inherit;
border-radius: 50%; /* To make circle */
content:'';
position:absolute;
/* top: -100px;*/
top: -50%; /* Inherit properties of parent */
/* left: -100px; */
left:0;
height: 100px;
width:100px;
}
.heart::before {
/* background:green; */
background:inherit;
border-radius: 50%; /* To make circle */
content:'';
position:absolute;
top:0;
right:-50%; /* Inherit properties of parent */
height: 100px;
width:100px;
}
#keyframes pulse{
0% {
transform: rotate(-45deg) scale(1);
opacity: 0;
}/*
10% {
transform: rotate(-45deg) scale(1.3);
}
20% {
transform: rotate(-45deg) scale(0.9);
}
30% {
transform: rotate(-45deg) scale(1.2);
}
40% {
transform: rotate(-45deg) scale(0.9);
}*/
50% {
transform: rotate(-45deg) scale(1.3);
opacity: 1;
}/*
60% {
transform: rotate(-45deg) scale(0.95);
}
70% {
transform: rotate(-45deg) scale(1);
} */
100% {
transform: rotate(-45deg) scale(1);
opacity: 1;
}
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" type="text/css">
<script src="script.js"></script>
</head>
<body>
<div class="container wrap">
<div class="container-title">
<h1>Quer sair comigo?</h1>
</div>
<div class="container-button">
<div class = "heart" id="heart"></div>
<script type="text/javascript">
document.getElementById("heart").style.display = "none";
</script>
<div class="botao">
<button class="item" type="button" id="botao2" onclick="setHeart(this)">SIM</button>
</div>
<div class="botao">
<button type="button" class="item" id="botao" onmouseover="move(this)">NÃO</button>
</div>
</div>
</div>
</body>
</html>
Couple things:
Visible is not a valid display value (see options here), I have set block instead in your setHeart function:
document.getElementById("heart").style.display = "block";
Also edited your console.log inside of move() to include both width & height values, while X & Y coordinates are already shown with your changeTop & changeLeft (you can see these in the fiddle's console at the bottom when you hover over NÃO button triggering move())
console.log("botao width: " + width + " botao height: " + height + " Height: " + changeTop + " Width: " + changeLeft);
See working snippet below:
function move(el) {
let div = document.getElementsByClassName("container-button");
let width = Math.ceil(el.clientWidth);
let height = Math.ceil(el.clientHeight);
let wdh = Math.floor(div[0].clientHeight);
let wdw = Math.floor(div[0].clientWidth);
var changeTop = Math.floor((Math.random() * (wdh - height + 1)));
var changeLeft = Math.floor((Math.random() * (wdw - width + 1)));
console.log("botao width: " + width + " botao height: " + height + " Height: " + changeTop + " Width: " + changeLeft);
el.style.marginTop = changeTop + "px";
el.style.marginLeft = changeLeft + "px";
}
function setHeart(element) {
document.getElementById("botao").style.display = "none";
document.getElementById("botao2").style.display = "none";
document.getElementById("heart").style.display = "block";
}
body {
align-items: center;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
background-image: linear-gradient(to top left, rgba(255, 0, 0, 0), rgba(255, 0, 0, 1));
}
.container {
flex-direction: row;
justify-content: center;
align-items: center;
width: 700px;
margin: 0 auto;
display: flex;
}
.wrap {
/* Quebra a linha assim que um dos flex itens não puder mais ser compactado. */
flex-wrap: wrap;
}
.item {
/* O flex: 1; é necessário para que cada item se expanda ocupando o tamanho máximo do container. */
flex: 1;
background: white;
font-size: 1.5em;
border-radius: 10px;
width: 80px;
height: 40px;
border: none;
color: red;
-ms-transform: translateY(-50%);
transform: translateY(-50%);
top: 50%;
}
.container-button {
align-content: center;
width: 500px;
height: 500px;
display: flex;
margin-top: 25%;
margin-left: 35%;
}
h1 {
text-align: center;
color: white;
}
.heart {
background: yellow;
position: relative;
height: 100px;
width: 100px;
/* Animation */
transform: rotate(-45deg) scale(1);
animation: pulse 2s linear infinite;
}
#heart {
display: none;
}
.heart::after {
/* background:blue; */
background: inherit;
border-radius: 50%;
/* To make circle */
content: '';
position: absolute;
/* top: -100px;*/
top: -50%;
/* Inherit properties of parent */
/* left: -100px; */
left: 0;
height: 100px;
width: 100px;
}
.heart::before {
/* background:green; */
background: inherit;
border-radius: 50%;
/* To make circle */
content: '';
position: absolute;
top: 0;
right: -50%;
/* Inherit properties of parent */
height: 100px;
width: 100px;
}
#keyframes pulse {
0% {
transform: rotate(-45deg) scale(1);
opacity: 0;
}
50% {
transform: rotate(-45deg) scale(1.3);
opacity: 1;
}
100% {
transform: rotate(-45deg) scale(1);
opacity: 1;
}
}
<div class="container wrap">
<div class="container-title">
<h1>Quer sair comigo?</h1>
</div>
<div class="container-button">
<div class="heart" id="heart"></div>
<script type="text/javascript">
document.getElementById("heart").style.display = "none";
</script>
<div class="botao">
<button class="item" type="button" id="botao2" onclick="setHeart(this)">SIM</button>
</div>
<div class="botao">
<button type="button" class="item" id="botao" onmouseover="move(this)">NÃO</button>
</div>
</div>
</div>
You need to set display: block instead of visible:
document.getElementById("heart").style.display = "block";
Because they're not the same:
visibility:hidden has visibility:visible and it will keep the element on the page and occupies that space but does not show it to the user.
display:none has display:block and it will not be available on the page and does not occupy any space.
Try to set dispay to block, maybe you can create a jsfiddle so it's easier to debug the second part of your question

How to draw image on wheel of fortune?

I have used the wheel of fortune code from how to draw a wheel of fortune?
I've modified function drawSector(sector,i) to drawImage on each sector like this:
function drawSector(sector, i) {
const ang = arc * i;
ctx.save();
// COLOR
ctx.beginPath();
ctx.fillStyle = sector.color;
ctx.moveTo(rad, rad);
ctx.arc(rad, rad, rad, ang, ang + arc);
ctx.lineTo(rad, rad);
ctx.fill();
// TEXT
ctx.translate(rad, rad);
ctx.rotate(ang + arc / 2);
if(!sector.label.includes('<img')){
ctx.textAlign = "right";
ctx.fillStyle = "#fff";
ctx.fillText(sector.label, rad-10, txtPositionY);
}
else{
// IMG
const div = document.createElement('div')
div.innerHTML = sector.label
const img = div.querySelector('img');
const ratio = img.width/img.height;
let imgMinH = (2*PI*55)/sectors.length; // // r=110/2
let imgMaxW = (rad-15) - 55;
let imgW = imgMinH*ratio;
let imgH = imgMinH;
let imgX = (rad-15)-imgW;
let imgY = (-imgH)/2;
let LX = (2*PI*imgX)/sectors.length;
if(imgW<imgMaxW){
while( (imgX>55) && (imgH<LX) && (imgW<imgMaxW) ){
imgW += 1;
imgH = imgW/ratio;
imgX = (rad-15)-imgW;
imgY = (-imgH)/2;
LX = (2*PI*imgX)/sectors.length;
}
}
else{
while( (imgX<55) || (imgH>LX) || (imgW>imgMaxW) ){
imgW -= 1;
imgH = imgW/ratio;
imgX = (rad-15)-imgW;
imgY = (-imgH)/2;
LX = (2*PI*imgX)/sectors.length;
}
}
console.log("ratio:"+ratio+'\n orgH:'+imgMinH+'\n imgW:'+imgW+'\nimgH:'+imgH+'\nLX:'+LX+'\nimgX:'+imgX+'\nimgY:'+imgY+'\nimgMaxW:'+imgMaxW);
ctx.drawImage(img, imgX, imgY, imgW, imgH);
}
ctx.restore();
};
but i can not calculate exactly about image width, height and position. Please see the images below:
How to calculate exactly image width, height, position to drawImage like this image below?
Thank you!
const button = document.querySelector('.ring__button');
const ring = document.querySelector('.ring__wrapper');
button.addEventListener('click', () => {
ring.classList.add('ring__wrapper--rotate')
})
:root {
--size: 300px;
}
.ring {
width: var(--size);
height: var(--size);
position: relative;
z-index: 1;
}
.ring__wrapper {
display: flex;
flex-wrap: wrap;
border-radius: 100%;
overflow: hidden;
transform-origin: 50% 50%;
position: relative;
width: inherit;
height: inherit;
}
.ring__wrapper--rotate {
animation: rotate 3s;
transform: rotate(990deg)
}
.ring__button {
position: absolute;
z-index: 1;
border: none;
width: calc(var(--size) / 3);
height: calc(var(--size) / 3);
border-radius: 100%;
background: red;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-weight: bold;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.ring__button:after {
position: absolute;
z-index: 3;
display: block;
content: '';
left: 50%;
bottom: 100%;
border-bottom: 20px solid red;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
transform: translate(-50%, 5%);
}
.ring__part {
width: calc(var(--size) / 2);
height: var(--size);
overflow: hidden;
}
.ring__part img {
width: inherit;
height: inherit;
object-fit: contain;
}
.ring__part--1 {background: aquamarine;}
.ring__part--1 img {transform: rotate(180deg);}
.ring__part--2 {background: antiquewhite;}
#keyframes rotate {
from {transform: rotate(0)}
to {transform: rotate(990deg)}
}
<div class="ring">
<button class="ring__button">QUAY</button>
<div class="ring__wrapper">
<div class="ring__part ring__part--1"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--2"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
</div>
</div>
canvas is cool, but what about css?
const button = document.querySelector('.ring__button');
const ring = document.querySelector('.ring__wrapper');
button.addEventListener('click', () => {
ring.classList.add('ring__wrapper--rotate')
})
:root {
--size: 300px;
}
.ring {
width: var(--size);
height: var(--size);
position: relative;
z-index: 1;
}
.ring__wrapper {
display: flex;
flex-wrap: wrap;
border-radius: 100%;
overflow: hidden;
transform-origin: 50% 50%;
position: relative;
width: inherit;
height: inherit;
}
.ring__wrapper--rotate {
animation: rotate 3s;
transform: rotate(855deg)
}
.ring__button {
position: absolute;
z-index: 1;
border: none;
width: calc(var(--size) / 3);
height: calc(var(--size) / 3);
border-radius: 100%;
background: red;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
font-weight: bold;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.ring__button:after {
position: absolute;
z-index: 3;
display: block;
content: '';
left: 50%;
bottom: 100%;
border-bottom: 20px solid red;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
transform: translate(-50%, 5%);
}
.ring__part {
width: calc(var(--size) / 2);
height: calc(var(--size) / 2);
overflow: hidden;
}
.ring__part img {
width: inherit;
height: inherit;
object-fit: contain;
}
.ring__part--1 {background: aquamarine;}
.ring__part--1 img {transform: rotate(225deg);}
.ring__part--2 {background: antiquewhite;}
.ring__part--2 img {transform: rotate(-45deg);}
.ring__part--3 {background: brown;}
.ring__part--3 img {transform: rotate(135deg);}
.ring__part--4 {background: burlywood;}
.ring__part--4 img {transform: rotate(45deg);}
#keyframes rotate {
from {transform: rotate(0)}
to {transform: rotate(855deg)}
}
<div class="ring">
<button class="ring__button">QUAY</button>
<div class="ring__wrapper">
<div class="ring__part ring__part--1"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--2"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--3"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
<div class="ring__part ring__part--4"><img src="https://images.unsplash.com/photo-1655810120657-9ce44d2f9e6c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxOXx8fGVufDB8fHx8&auto=format&fit=crop&w=800&q=60" alt=""></div>
</div>
</div>

How to hide the scrollbar on pre-loader screen?

I want to hide the y-axis scrollbar on the preloader screen.
As you can see on the far right, I want to hide that scrollbar on my preloader screen. To do this, would I need to add a overflow-y: hidden; on the preloader css? I tried doing that but it still did not work.
Here is the code of the preloader:
$(window).on('DOMContentLoaded', function() {
if ($('#preloader').length) {
$('#preloader').delay(2000).fadeOut('slow');
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
#import url('https://fonts.googleapis.com/css2?family=Montserrat+Alternates:wght#500;700&family=Montserrat:wght#400;600&family=Oswald:wght#500&family=Pacifico&family=Roboto:ital,wght#0,400;0,900;1,500&display=swap');
.svg-file path {
fill: transparent;
stroke-width: 3;
stroke: rgb(1, 36, 133);
}
.svg-file.z-logo path {
stroke-dasharray: 550;
stroke-dashoffset: 0;
}
.svg-file.z-logo path {
animation: animate-zlogo 2s linear infinite;
}
.svg-file.z-logo svg {
filter: drop-shadow(2px 2px 3px rgba(0, 0, 0, 1));
transform: scale(2);
}
.svg-file h2 {
font-family: "Roboto", cursive;
transform: translate(0, 50px) skewX(-210deg) rotate(-6deg);
font-size: 3em;
color: #044d77;
}
.svg-file span {
animation: dots 2.5s steps(6, end) infinite;
font-size: 5em;
display: block;
transform: translate(0, 65px) skewX(-210deg) rotate(-6deg);
background-color: rgb(5, 46, 80);
width: 8px;
height: 5px;
}
#keyframes fadein-fadeout {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes animate-zlogo {
0% {
stroke-dashoffset: -50;
}
20% {
stroke-dashoffset: 550;
fill: transparent;
}
40% {
fill: transparent;
stroke-dashoffset: 1100;
}
60% {
stroke-dashoffset: 1100;
fill: #05f7f9;
}
80% {
stroke-width: 0;
fill: #05f7f9;
}
100% {
/* stroke-dashoffset: 0; */
stroke-width: 3;
fill: transparent;
}
}
#preloader {
position: fixed;
z-index: 9999;
overflow: hidden;
background: white;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
}
.z-logo svg {
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
margin: auto;
justify-content: center;
align-items: center;
align-content: center;
position: relative;
display: flex;
width: 50%;
}
.z-logo::before {
content: "";
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
margin: auto;
background: black;
position: absolute;
display: inline-flex;
border: 1px solid black;
width: 200px;
height: 200px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<div id="preloader">
<div class="svg-file z-logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 133 133" width="133" height="133">
<g id="H">
<path d="M45.33 78.22L87.67 78.22L87.67 133L121.05 133L121.05 0L87.67 0L87.67 49.33L45.33 49.33L45.33 0L11.95 0L11.95 133L45.33 133L45.33 78.22Z"
fill="#47AF9A" />
</g>
</svg>
</div>
</div>
Where should I add the overflow-y: hidden; in the above code, I tired adding it to the main *{ but it hid the y-axis scroll bar for my whole website, but I only want it to hide for the preloader screen.
You need to remove the overflow from the body of the page so nothing can be scrolled.
$(window).on('DOMContentLoaded', function() {
if ($('#preloader').length) {
$('#preloader').delay(2000).fadeOut('slow');
document.body.style.overflowY = "hidden"; // remove overflow from body
$('body').addClass('preload_active'); // add preload_active class
}
});
If using the addClass option then you'll need
.preload_active {
overflow-y: hidden;
}
in your CSS.
You will need something to remove the hidden value though. You can also add a class to the body and in the CSS declare overflow-y: hidden on this class. Again, you will need some logic that removes the class when the preloader.length === 0.

Create a Button that's border incrementally diminishes onClick and fires an event on time '0'

I found this great tool but it's awkward to implement in my project: https://github.com/vydimitrov/react-countdown-circle-timer
I want to create a reusable button component that onClick, starts a similar countdown effect with its border, giving the user a chance to 'undo' their decision (similar to forwarding a message in fb messenger). I can figure out the react logic but no clue where to start with css
Thanks in advance
Browsing the code of the component you mention, I noticed it uses an SVG element with animated stroke to create and animate the circular progress bar.
This article is my favourite one about this specific problem:
https://css-tricks.com/building-progress-ring-quickly/
Here is the code from that article for future reference. This is not my code, kudos to the original author of the article:
var circle = document.querySelector('circle');
var radius = circle.r.baseVal.value;
var circumference = radius * 2 * Math.PI;
circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = `${circumference}`;
function setProgress(percent) {
const offset = circumference - percent / 100 * circumference;
circle.style.strokeDashoffset = offset;
}
const input = document.querySelector('input');
setProgress(input.value);
input.addEventListener('change', function(e) {
if (input.value < 101 && input.value > -1) {
setProgress(input.value);
}
})
html, body {
background-color: #2962FF;
display: flex;
align-items: center;
justify-content: center;
height: 100%;
position: relative;
}
.progress-ring {
}
.progress-ring__circle {
transition: 0.35s stroke-dashoffset;
// axis compensation
transform: rotate(-90deg);
transform-origin: 50% 50%;
}
input {
position: fixed;
top: 10px;
left: 10px;
width: 80px;
}
<svg
class="progress-ring"
width="120"
height="120">
<circle
class="progress-ring__circle"
stroke="white"
stroke-width="4"
fill="transparent"
r="52"
cx="60"
cy="60"/>
</svg>
<input
value="35"
type="number"
step="5"
min="0"
max="100"
placeholder="progress"
>
This is a pure css pie timer which looks pretty similar to one of your timers mentioned in the link.
See it in full screen
var time = 11;
{
var func = setInterval(function() {
if (time != 0) {
document.getElementsByClassName('time')[0].innerHTML = time;
time--;
if (time < 5) {
document.getElementsByClassName('warning')[0].style.display = "block";
}
} else {
document.getElementsByClassName('time')[0].innerHTML = "0";
document.getElementsByClassName('warning')[0].style.display = "none";
clearInterval(func);
}
}, 1000);
}
.timer {
height: 200px;
width: 200px;
border-radius: 50%;
background-color: black;
animation: time 5s infinite;
margin-left: 570px;
margin-top: 200px;
}
.bar {
position: absolute;
}
.left_progress {
position: absolute;
height: 200px;
width: 200px;
background: linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%);
border-radius: 50%;
clip: rect(0px 100px 200px 0px);
animation: rotate_right 6s 6s linear both;
}
#keyframes rotate_right {
100% {
transform: rotateZ(180deg);
}
}
.left_progress_bar {
position: absolute;
height: 200px;
width: 200px;
background-color: #E9E9E9;
border-radius: 50%;
clip: rect(0px 100px 200px 0px);
z-index: 1;
animation: mid-way 4s linear both;
}
.right_progress {
position: absolute;
height: 200px;
width: 200px;
background-color: #E9E9E9;
border-radius: 50%;
clip: rect(0px 100px 200px 0px);
transform: rotateZ(180deg);
animation: rotate_left 6s linear both;
}
#keyframes rotate_left {
100% {
transform: rotateZ(360deg);
}
}
.right_progress_bar {
position: absolute;
height: 200px;
width: 200px;
background: linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%);
border-radius: 50%;
clip: rect(0px 100px 200px 0px);
transform: rotateZ(180deg);
z-index: 1;
}
.main_content {
position: absolute;
height: 180px;
width: 180px;
border-radius: 50%;
background-color: white;
z-index: 4;
margin-top: 10px;
margin-left: 10px;
font-family: 'arial';
text-align: center;
}
.timer_content {
position: absolute;
margin-top: 40px;
margin-left: 45px;
}
.content {
font-size: 15px;
margin: 0px;
color: #6B6C6D;
}
.time {
font-size: 55px;
margin: 0px;
background: -webkit-linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.warning {
position: absolute;
height: 180px;
width: 180px;
border-radius: 50%;
background-color: #DBDBDB;
animation: warning_bell 1s infinite;
display: none;
}
#keyframes warning_bell {
from {
transform: scale(0);
opacity: 1;
}
to {
transform: scale(1);
opacity: 0;
}
}
<div class="timer">
<div class="right_progress_bar">
<div class="right_progress"></div>
</div>
<div class="left_progress_bar">
<div class="left_progress"></div>
</div>
<div class="main_content">
<div class="warning"></div>
<div class="timer_content">
<p class="content">You can do in</p>
<p class="time">12</p>
<p class="content">seconds</p>
</div>
</div>
</div>

Categories