Scalable css percentage ring

I am trying to convert the code below mainly into a scalable version, I tried using the values ​​of vw and vh,%, etc. etc., and I cannot get the right balance of values ​​that work. Any help is appreciated.

This codepen may also help: http://codepen.io/anon/pen/dPNgvP

.arrow { position: relative; height: 0px; width: 0px; border-top: 18px solid #dd1111; border-left: 11px solid transparent; border-right: 11px solid transparent; position: absolute; bottom: 40px; left: 57px; z-index: 1; animation: load-arrow 1.6s linear; animation-fill-mode: forwards; -webkit-animation: load-arrow 1.6s linear; -webkit-animation-fill-mode: forwards; } @keyframes load-arrow { from { transform: translate(0, 0); } to { transform: translate(0, 55px); } } @-webkit-keyframes load-arrow { from { -webkit-transform: translate(0, 0); } to { -webkit-transform: translate(0, 55px); } } .pie { width: 140px; height: 140px; position: relative; border-radius: 140px; background-color: #DD1111; float: left; margin-right: 10px; } .pie .title { position: absolute; bottom: -40px; text-align: center; width: 100%; } .mask { position: absolute; width: 100%; height: 100%; } .pie1 .inner-right { transform: rotate(160deg); animation: load-right-pie-1 1s linear; -webkit-animation: load-right-pie-1 1s linear; -webkit-transform: rotate(160deg); } @keyframes load-right-pie-1 { from { transform: rotate(0deg); } to { transform: rotate(160deg); } } @-webkit-keyframes load-right-pie-1 { from { -webkit-transform: rotate(0deg); } to { -webkit-transform: rotate(160deg); } } .outer-left { clip: rect(0px 70px 140px 0px); } .outer-right { clip: rect(0px 140px 140px 70px); } .inner-left { background-color: #710000; position: absolute; width: 100%; height: 100%; border-radius: 100%; clip: rect(0px 70px 140px 0px); transform: rotate(-180deg); -webkit-transform: rotate(-180deg); } .inner-right { background-color: #710000; position: absolute; width: 100%; height: 100%; border-radius: 100%; clip: rect(0px 70px 140px 0px); transform: rotate(180deg); -webkit-transform: rotate(180deg); } .content { width: 100px; height: 100px; border-radius: 50%; background-color: #fff; position: absolute; top: 20px; left: 20px; line-height: 100px; font-family: arial, sans-serif; font-size: 35px; text-align: center; z-index: 2; } .content span { opacity: 0; animation: load-content 3s; animation-fill-mode: forwards; animation-delay: 0.6s; -webkit-animation: load-content 3s; -webkit-animation-fill-mode: forwards; -webkit-animation-delay: 0.6s; } @keyframes load-content { from { opacity: 0; } to { opacity: 1; } } @-webkit-keyframes load-content { from { opacity: 0; } to { opacity: 1; } } 
 <div class="pie pie1"> <div class="title">Twitter</div> <div class="outer-right mask"> <div class="inner-right"></div> </div> <div class="outer-left mask"> <div class="inner-left"></div> </div> <div class="content"> <span>44%</span> </div> </div> 
+6
source share
2 answers

You can simplify your code and make it dynamic using svg and JavaScript.

What does this code do?

  • Extract the percentage value from the text tag, calculates the angle and saves it for animation.
  • Animates the dark portion from theta = 0 to the calculated angle (s).

What you can do using this approach:

  • You can dynamically set the percentage by simply changing 44% in the text tags.
    • Allowed formats ----> -% | --% | ---% , including float values.
  • You can change the animation speed by changing the variable t .
  • You can also make it responsive.

Responsive demo on CodePen ---> width and height svg depend on #container width .

 var dark = document.getElementById('dark'), t = 5, percentage = parseInt(document.getElementById('perc').innerHTML.slice(0, -1), 10), theta = 0, maxTheta = (180 * percentage) / 50, radius = document.getElementById('svg').getBBox().width / 2; dark.setAttribute('transform', 'translate(' + radius + ',' + radius + ')'); var animate = setInterval(function() { theta += 0.5; var d = 'M0,0 v' + -radius + 'A' + radius + ',' + radius + ' 1 ' + ((theta > 180) ? 1 : 0) + ',1 ' + Math.sin(theta * Math.PI / 180) * radius + ',' + Math.cos(theta * Math.PI / 180) * -radius + 'z'; dark.setAttribute('d', d); if (theta > maxTheta) { clearInterval(animate); } }, t); 
 <svg id="svg" width="140" height="140" viewBox="0 0 141 141"> <path id="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path id="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text id="perc" x="70" y="79" font-size="30px" text-anchor="middle">44%</text> </svg> 

To accommodate multiple percentage rings, you can use class es instead of id s. Again, you don’t need to make any changes to the JavaScript code, just change the percentage in the text tags.

enter image description here

CodePen Demo

 var dark = document.getElementsByClassName('dark'), radius = document.getElementsByClassName('svg')[0].getBBox().width / 2, t = 0.5, x = 0, y = 0, theta = {}, maxTheta = calcTheta(document.getElementsByClassName('perc')), intervals = []; function calcTheta(el) { var jbo = {}; for (i = 0; i < el.length; i++) { theta[i] = 0; dark[i].setAttribute('transform', 'translate(' + radius + ',' + radius + ')'); jbo[i] = (180 * parseInt(el[i].innerHTML.slice(0, -1), 10)) / 50; } return jbo; } var anim = function(j) { return function() { theta[j] += 0.5; var d = 'M0,0 v' + -radius + 'A' + radius + ',' + radius + ' 1 ' + ((theta[j] > 180) ? 1 : 0) + ',1 ' + Math.sin(theta[j] * Math.PI / 180) * radius + ',' + Math.cos(theta[j] * Math.PI / 180) * -radius + 'z'; dark[j].setAttribute('d', d); if (theta[j] > maxTheta[j]) { clearInterval(intervals[j]); } } }; for (var j = 0; j < dark.length; j++) { intervals.push(setInterval(anim(j), t)); } 
 #container { width: 100%; } .svg { display: inline-block; width: 16.5%; } 
 <div id="container"> <svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">44%</text> </svg ><svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">20%</text> </svg ><svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">90%</text> </svg ><svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">14%</text> </svg ><svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">60%</text> </svg ><svg class="svg" viewBox="0 0 141 141"> <path class="light" d="M70,70 v-70 a70,70 0 0,1 0,140 a70,70 0 1,1 0,-140" fill="#DD1111" /> <path class="dark" d="M70,70 v-70 a70,70 0 0,1 0,0" fill="#710000" /> <path d="M20,70 a50,50 0 0,1 100,0 a50,50 0 0,1 -100,0" fill="white" /> <text class="perc" x="70" y="79" font-size="30px" text-anchor="middle">50%</text> </svg> </div> 
+5
source

Here is a good pieProgress.js plugin for this. Here's a demo and tutorial on how to use it.

Hope this solves your problem.

0
source

Source: https://habr.com/ru/post/980844/


All Articles