Создать SVG прогресс круг - PullRequest
       12

Создать SVG прогресс круг

3 голосов
/ 08 марта 2011

Кто-нибудь знает, как создать круг "прогрессбар" в SVG? Мне нужно указать процент от круга, так что цвет растет в форме торта.

Рост может быть статичным, если у меня есть атрибут для изменения его текущего состояния.

Ответы [ 7 ]

10 голосов
/ 01 мая 2015

Ниже приводится идея, которую я использовал. С небольшими изменениями в тегах css и animation мы можем добиться большего эффекта для интуитивного взаимодействия с пользователем.

--- КОД ОБРАЗЦА ----

.over{
  -webkit-animation: rotator 1.5s ease-in-out infinite;
  stroke-dasharray: 107,38;
}
.bag{
  position: absolute;
}
@-webkit-keyframes rotator {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
<div class="container">
  <svg class="bag" height="100" width="100">
    <circle  cx="50" cy="50" r="40" stroke="#F8BBD0" stroke-width="3" fill="none">
    </circle>
  </svg>
  <svg class="over" height="100" width="100">
    <circle  cx="50" cy="50" r="40" stroke="#E91E63" stroke-width="3" fill="none" >
      <animate attributeType="CSS" attributeName="stroke-dasharray" from="1,254" to="247,56" dur="5s" repeatCount="indefinite" />
    </circle>
  </svg>
</div>

Надеюсь, вы искали что-то вроде этого. :)

8 голосов
/ 09 марта 2011

Спасибо, Болдевин.

Чтобы ответить на свой вопрос, я нашел следующее решение:

В шаблоне можно использовать следующий путь:

<path id="progress" fill="none" stroke="#ffffff" d="" stroke-width="10"/>

И используйте эту функцию из Raphael js-framework для обновления x и y. Если итоговое значение равно 100, значение представляет собой процент выполнения:

function updateState (value, total, R) {
    var center;
    var alpha = 360 / total * value,
        a = (90 - alpha) * Math.PI / 180,
        x = 300 + R * Math.cos(a),
        y = 300 - R * Math.sin(a),
        path;
    if (total == value) {
        path = "M"+ 300 +","+ (300 - R) +" A"+ R+","+ R+","+ 0+","+ 1+","+ 1+","+ 299.99+","+ 300 - R;
    } else {
        if(alpha > 180) {
            center = 1;
        } else {
            center = 0;
        }
        path = "M"+ 300+","+ (300 - R) +" A"+ R+","+ R+","+ 0+"," + center +","+ 1+","+ x+","+ y;
    }
    return path;
}

Возвращаемая переменная пути - это значение атрибута d в ​​элементе пути.

Это прекрасно работает, если ваш браузер поддерживает SVG Full с командой Elliptical Arc для элемента path. В моем случае у меня только SVG крошечный, так что это не будет работать для меня :(

4 голосов
/ 19 мая 2013

Используйте этот самостоятельно реализованный метод в JavaScript, например, здесь процент = 85

HTML-код:

<p style="position:absolute;margin-left:95px;margin-top:50px;" id="percentage">0 %</p>  
<svg style="position:absolute" id="svg_test" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" cx="110" cy="60" r="50" fill="none" stroke="#e4e4e4" stroke-width="2"></circle>
<path id="svgpath" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" fill="none" stroke="#16a6b6" d="M60,60 A50,50 0 0,1 160,60" stroke-width="2"></path>
</svg>

<circle style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" cx="110" cy="60" r="50" fill="none" stroke="#e4e4e4" stroke-width="2"></circle>
<path id="svgpath" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);" fill="none" stroke="#16a6b6" d="M60,60 A50,50 0 0,1 160,60" stroke-width="2"></path>
</svg>

jQuery-код:

    percentage=85
    if(percentage>=50)
    {
        flag=1;
    }
    var per=0;
    $(svg).animate({ 'to': 1 }, {
    duration: 2000,
    step: function(pos, fx) {

        //var offset = (pos);
        if(pos<0.5)
        {
            if(percentage>=50)
            {
                per=180;
                $('#percentage').html(Math.round(pos*100)+" %");
            }
            else
            {
                per=(percentage*180/50);
                $('#percentage').html(Math.round(percentage*pos*2)+" %");
            }

            endx=110-50*Math.cos(0+(Math.PI/180)*per*(pos*2));
            endy=60-50*Math.sin(0+(Math.PI/180)*per*(pos*2));
            svg.setAttribute('d',current_dx+endx+","+endy);
        }   
        else if(pos>=0.5 && pos!=1 && flag==1)
        {
            per=((percentage-50)*180/50);
            $('#percentage').html(Math.round(50+(percentage-50)*(pos-0.5)*2)+" %");
            endx=110+50*Math.cos(0+(Math.PI/180)*per*(pos-0.5)*2);
            endy=60+50*Math.sin(0+(Math.PI/180)*per*(pos-0.5)*2);
            svg.setAttribute('d',current_d+endx+","+endy);

        }


    }
});

Демонстрация: Нажмите здесь

4 голосов
/ 08 марта 2011

Бесстыдное копирование и вставка из спецификации :

<path d="M275,175 v-150 a150,150 0 0,0 -150,150 z"
    fill="yellow" stroke="blue" stroke-width="5" />

Путь использует команду "эллиптическая дуга", чтобы нарисовать частичный круг.Вы можете нарисовать несколько из них, каждый из которых описывает отдельный круговой разрез, или дать одному из них идентификатор и указать его с помощью <use xlink:href="#ID" />.Затем вы можете повернуть <use/>.Нарисуйте столько, сколько вам нужно для гранулярности (например, 100 секторов позволяют вам шаги от 0% до 100%).

Чтобы раскрасить их, просто установите атрибут fill="" каждого отдельного сектора в соответствиизначение.

2 голосов
/ 17 ноября 2014

Некоторое время назад мне был нужен один, поэтому я много учился, чтобы сделать это. Все, что вам нужно, это простая разметка SVG с правильными координатами, немного CSS для нее и немного JS (чтобы можно было изменить% индикатора выполнения). Но в то же время вы можете сгенерировать SVG на бэкэнде с правильными координатами на основе желаемого%, и если ваш прогресс не может быть доступен только для чтения, это также сработает.

Это реализация: http://codepen.io/leandroico/pen/zwIHl

А это образец разметки SVG:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
  <g class="arcs">
    <circle cx="50" cy="50" r="49" class="outer-circle" />
    <path d="M50 1 A 49 49, 0, 1, 1, 7.06 73.61, L 50 50 z" class="outer-arc" id="arc1" />
    <circle cx="50" cy="50" r="35" class="inner-circle"  />
    <path d="M50 15 A 35 35, 0, 1, 1, 19.33 66.86" class="inner-arc" id="arc2" />
  </g>
  <g class="circles">
    <circle cx="50" cy="50" r="49" class="outer-circle" />
    <circle cx="50" cy="50" r="35" class="inner-circle" />
  </g>
  <text x="50" y="58" id="percentage-label">67%</text>
</svg>
1 голос
/ 10 апреля 2014
<svg xmlns="http://www.w3.org/2000/svg" width="225" height="225">
    <g>
        <circle cx="112" cy="112" r="95"></circle>
        <path id="path" d="M 112,17 A 95,95 0 0,0 112,17"></path>
    </g>
</svg>
<script type="text/javascript">
    function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
        var angleInRadians = angleInDegrees * Math.PI / 180.0;
        var x = centerX + radius * Math.cos(angleInRadians);
        var y = centerY + radius * Math.sin(angleInRadians);
        return [x, y];
    }
    function drawCircle(elm, centerX, centerY, radius, percentage) {
        var angle = (360 * (percentage / 100)) % 360;
        var start = polarToCartesian(centerX, centerY, radius, -90);
        var end = polarToCartesian(centerX, centerY, radius, -(angle + 90));
        var large = percentage < 50 ? 0 : 1;
        var length = (2 * Math.PI * radius) * (percentage / 100);
        console.log(start, end, angle);
        elm.setAttribute('d', 'M ' + start[0] + ',' + start[1] + ' A ' + radius + ',' + radius + ' ' + 0 + ' ' + large + ',' + 0 + ' ' + end[0] + ',' + end[1]);
        elm.setAttribute('stroke-dasharray', length);
        elm.setAttribute('stroke-dashoffset', length);
    }
    drawCircle(document.getElementById('path'), 112, 112, 95, 47);
</script>
0 голосов
/ 01 июня 2019

Codepen-Link

<div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>

CSS, необходимый для этого круга svg

.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}


a {
  font-size: 26px;
}

.flex-wrapper {
  display: flex;
  flex-flow: row nowrap;
}

.single-chart {
  width: 33%;
  justify-content: space-around ;
}

.circular-chart {
  display: block;
  margin: 10px auto;
  max-width: 80%;
  max-height: 250px;
}

.circle-bg {
  fill: none;
  stroke: #eee;
  stroke-width: 3.8;
}

.circle {
  fill: none;
  stroke-width: 2.8;
  stroke-linecap: round;
  animation: progress 1s ease-out forwards;
}

@keyframes progress {
  0% {
    stroke-dasharray: 0 100;
  }
}

.circular-chart.orange .circle {
  stroke: #ff9f00;
}

.percentage {
  fill: #666;
  font-family: sans-serif;
  font-size: 0.5em;
  text-anchor: middle;
}


a {
  font-size: 26px;
}
<div class="flex-wrapper">
  <div class="single-chart">
      <svg viewBox="0 0 36 36" class="circular-chart orange">
          <path class="circle-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <path class="circle" stroke-dasharray="30, 100" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" />
          <text x="18" y="20.35" class="percentage">30%</text>
      </svg>
  </div>
</div>


<br>
<br>
<br>
<br>
<br>

<a href="https://codepen.io/sergiopedercini/">Thanks to sergiopedercini</a>
...