yelnn
yelnn

Reputation: 73

Circle Progress Bar that progress from center and in both direction

how can I create a circle progress bar that expands in both clockwise + non clockwise direction from the starting point?

here is my progress so far: https://jsfiddle.net/qchygknu/

HTML:

<div class="wheel circle-menu is-draggable-horizontal">
   <div class="wheel__list circle-menu__circle" style="transform: rotate(1deg);">
      
      <div class="wheel__list__item circle-menu__circle__item position--top-right" style="transform: rotate(60deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-61deg);">
         </div>
         </a>
      </div>
      
      <div class="wheel__list__item circle-menu__circle__item position--bottom" style="transform: rotate(180deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-181deg);">
         </div>
         </a>
      </div>
      
      <div class="wheel__list__item circle-menu__circle__item position--top-left" style="transform: rotate(300deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-301deg);">
         </div>
         </a>
      </div>
      <svg class="circle-menu__circle__svg" viewBox="0 0 100 100">
        <text id="myTimer" text-anchor="middle" x="100" y="110" style="font-size: 36px;" >0%</text>
         <circle id="svg-circle-1" class="circle-menu__circle__svg__circle_1" cx="50" cy="50" r="50" transform="rotate(-90 50 50)"></circle>
         <circle id="svg-circle-2" class="circle-menu__circle__svg__circle_2" cx="50" cy="50" r="50" transform="rotate(-90 50 50)"></circle>
         <circle class="circle-menu__circle__svg__line" cx="50" cy="50" r="50" transform="rotate(-90 50 50)"></circle>
      </svg>
   </div>
</div>

CSS:

.circle-menu__circle {
    list-style: none;
    padding: 0;
    margin: 0 auto;
    position: relative;
    width: 400px;
    height: 400px;
}

.circle-menu__circle__item {
    width: 0;
    height: 100%;
    position: absolute;
    margin: 0 50%;
    cursor: auto;
}

.circle-menu__circle__item__inner {
    position: absolute;
    left: 50%;
    bottom: 98%;
    margin-left: -5px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background-color: #333;
}

.circle-menu__circle__svg {
    height: 100%;
    overflow: visible;
}

.circle-menu__circle__svg__circle_1 {
    fill: transparent;
    stroke: #333;
    stroke-width: 0.5px;
}

.circle-menu__circle__svg__circle_2 {
    fill: transparent;
    stroke: #333;
    stroke-width: 4px;
}

.circle-menu__circle__svg__line {
    fill: transparent;
    stroke: black;
    stroke-width: 0.5px;
    stroke-dasharray: 315;
    stroke-dashoffset: 315;
    -webkit-transition: stroke-dashoffset 1s;
    transition: stroke-dashoffset 1s;
}

Javascript:

(function () {
    // math trick 2*pi*57 = 358, must be less than 360 degree 
    var circle = document.getElementById('svg-circle-2');
    var myTimer = document.getElementById('myTimer');
    var interval = 30;
    var angle = 0;
    var angle_increment = 6;

    window.timer = window.setInterval(function () {
        
        circle.setAttribute("stroke-dashoffset", 45 );
        circle.setAttribute("stroke-dasharray", angle + ", 20000");
        myTimer.innerHTML = angle;

        if (angle >= 90) {
            window.clearInterval(window.timer);
        }
        angle += angle_increment;
    }.bind(this), interval);
})()

I have tried using svg to draw the circle and using stroke-dasharray and stroke-dashoffset but I cannot set the starting point and it can only expand in 1 direction, I need the progress bar to expand on both direction when the dot is clicked

Example - Step 1

enter image description here

Example - Step 2

enter image description here

Example - Step 3

enter image description here

Example - Step 4

enter image description here

Upvotes: 0

Views: 1816

Answers (2)

Paul LeBeau
Paul LeBeau

Reputation: 101810

You can achieve the effect you want with pure CSS.

.circle-menu__circle {
    display: block;
    margin: 0 auto;
    width: 400px;
    height: 400px;
}

.circle-menu__circle__svg__circle_1 {
    fill: transparent;
    stroke: #999;
    stroke-width: 0.5px;
}

.circle-menu__circle__item {
    fill: transparent;
    stroke: #333;
    stroke-width: 4px;
    stroke-linecap: round;
    stroke-dasharray: 0px 314.2px;
    stroke-dashoffset: 157.5px;
    transition: all 1s;
    pointer-events: visibleStroke;
}

.position--top-right {
    transform: rotate(150deg);
}

.position--bottom {
    transform: rotate(-90deg);
}

.position--top-left {
    transform: rotate(30deg);
}

.circle-menu__circle__item:hover {
    stroke-dasharray: 100px 214.2px;
    stroke-dashoffset: 207.5px;
}
<div class="wheel circle-menu is-draggable-horizontal">
   <svg class="wheel__list circle-menu__circle" viewBox="-52 -52 104 104">
      
     <circle id="svg-circle-1" class="circle-menu__circle__svg__circle_1" cx="0" cy="0" r="50"></circle>

     <circle cx="0" cy="0" r="50" class="circle-menu__circle__item position--top-right"/>
     <circle cx="0" cy="0" r="50" class="circle-menu__circle__item position--bottom"/>
     <circle cx="0" cy="0" r="50" class="circle-menu__circle__item position--top-left"/>
   </svg>
</div>

Upvotes: 1

Sachink
Sachink

Reputation: 1530

This can be helpful

(function () {
    // math trick 2*pi*57 = 358, must be less than 360 degree 
    var circle = document.getElementById('svg-circle-2');
    var myTimer = document.getElementById('myTimer');
    var interval = 30;
    var angle = 0;
    var angle_increment = 6;
    var pointLocation = -30; // -30, 90, 210 
    var arc = 120;

    window.timer = window.setInterval(function () {
        circle.setAttribute("stroke-dasharray", (angle) + ", 20000");
        circle.setAttribute("transform", "rotate("+ (pointLocation -angle/1.8) +" 50 50)");
        myTimer.innerHTML = angle;
        if (angle >= arc) {
            window.clearInterval(window.timer);
        }
        angle += angle_increment;
    }.bind(this), interval);
})()
.circle-menu__circle {
    list-style: none;
    padding: 0;
    margin: 0 auto;
    position: relative;
    width: 400px;
    height: 400px;
}

.circle-menu__circle__item {
    width: 0;
    height: 100%;
    position: absolute;
    margin: 0 50%;
    cursor: auto;
}

.circle-menu__circle__item__inner {
    position: absolute;
    left: 50%;
    bottom: 98%;
    margin-left: -5px;
    width: 15px;
    height: 15px;
    border-radius: 50%;
    background-color: #333;
}

.circle-menu__circle__svg {
    height: 100%;
    overflow: visible;
}

.circle-menu__circle__svg__circle_1 {
    fill: transparent;
    stroke: #333;
    stroke-width: 0.5px;
}

.circle-menu__circle__svg__circle_2 {
    fill: transparent;
    stroke: #333;
    stroke-width: 4px;
}

.circle-menu__circle__svg__line {
    fill: transparent;
    stroke: black;
    stroke-width: 0.5px;
    stroke-dasharray: 315;
    stroke-dashoffset: 315;
    -webkit-transition: stroke-dashoffset 1s;
    transition: stroke-dashoffset 1s;
}
<div class="wheel circle-menu is-draggable-horizontal">
   <div class="wheel__list circle-menu__circle" style="transform: rotate(1deg);">
      
      <div class="wheel__list__item circle-menu__circle__item position--top-right" style="transform: rotate(60deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-61deg);">
         </div>
         </a>
      </div>
      
      <div class="wheel__list__item circle-menu__circle__item position--bottom" style="transform: rotate(180deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-181deg);">
         </div>
         </a>
      </div>
      
      <div class="wheel__list__item circle-menu__circle__item position--top-left" style="transform: rotate(300deg);">
      <a href="#">
         <div class="circle-menu__circle__item__inner" style="transform: rotate(-301deg);">
         </div>
         </a>
      </div>
      <svg class="circle-menu__circle__svg" viewBox="0 0 100 100">
        <text id="myTimer" text-anchor="middle" x="100" y="110" style="font-size: 36px;" >0%</text>
         <circle id="svg-circle-1" class="circle-menu__circle__svg__circle_1" cx="50" cy="50" r="50" transform="rotate(-90 50 50)"></circle>
         <circle id="svg-circle-2" class="circle-menu__circle__svg__circle_2" cx="50" cy="50" r="50" ></circle>
         <circle class="circle-menu__circle__svg__line" cx="50" cy="50" r="50" transform="rotate(-90 50 50)"></circle>
      </svg>
   </div>
</div>

Upvotes: 0

Related Questions