Как сделать сектора в пончике со скругленными углами?

257
09 мая 2018, 03:25

Как это сделать?
Мне нужен мульти-сектор в пончике с закругленными концами и добавить тень самому пончику.

Хочу использовать chart.js, но можно и другие варианты без jquery.

Answer 1

Есть вариант сделать с помощью SVG. На последней секции(#part4) в качестве примера заливка градиентом.

UPD: Добавил еще вариант без CSS

.circle { 
  height: 200px; 
  width: 200px; 
  fill: none; 
  stroke-width: 5; 
  stroke-linecap: round; 
  position: absolute; 
  left:0; 
  top:0; 
 } 
#part1 { 
  stroke: #172bc3; 
  z-index: 3; 
  transform: rotate(20deg); 
} 
#part2 { 
  stroke: #f21d92; 
  z-index: 2; 
  transform: rotate(-70deg); 
} 
#part3 { 
  stroke: #9631eb; 
  z-index: 5; 
  transform: rotate(-160deg); 
} 
#part4 { 
  stroke: url(#gradient); 
  z-index: 4; 
  transform: rotate(-250deg); 
} 
#shadow { 
  stroke: white; 
  z-index:1; 
  stroke-width: 2; 
}
<svg id="part1" class="circle" viewBox="256 346 100 100"> 
  <defs> 
    <path id="line" d="M268.5,395.9c0-20.7,16.8-37.4,37.4-37.4"/> 
  </defs> 
 <use xlink:href="#line"/> 
</svg> 
<svg id="part2" class="circle" viewBox="256 346 100 100" xmlns:xlink="http://www.w3.org/1999/xlink"> 
 <use xlink:href="#line"/> 
</svg> 
<svg id="part3" class="circle" viewBox="256 346 100 100" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <use xlink:href="#line"/> 
</svg> 
<svg id="part4" class="circle" viewBox="256 346 100 100" xmlns:xlink="http://www.w3.org/1999/xlink"> 
  <defs> 
    <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%"> 
      <stop offset="0%" stop-color="#00bc9b" /> 
      <stop offset="100%" stop-color="#5eaefd" /> 
    </linearGradient> 
  </defs> 
 <use xlink:href="#line"/> 
</svg> 
<svg id="shadow" class="circle" viewBox="256 346 100 100"> 
 <defs> 
    <filter id="blurMe" width="200%" height="200%"> 
      <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> 
      <feGaussianBlur result="blurOut" in="offOut" stdDeviation="3" /> 
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> 
    </filter> 
  </defs> 
<circle cx="306" cy="396" r="38" filter="url(#blurMe)"/> 
</svg>

Answer 2

Решается вопрос с помощью SVG. Применил circles, вместо paths( почему бы и нет?:D ):

<svg viewBox="0 0 600 600"> 
  <defs> 
    <filter id="blurMe" width="200%" height="200%"> 
      <feOffset result="offOut" in="SourceAlpha" dx="0" dy="5" /> 
      <feGaussianBlur result="blurOut" in="offOut" stdDeviation="3" /> 
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> 
    </filter> 
  </defs> 
  <circle cx="115" cy="115" r="100" filter="url(#blurMe)" fill="none" stroke="white" stroke-width="2"/> 
  <circle cx="110" cy="110" r="100" stroke="#f21d92" stroke-width="20" fill="none" stroke-dasharray="550" stroke-dashoffset="350"/> 
  <circle cx="110" cy="110" r="100" stroke="#9631eb" stroke-width="20" fill="none" stroke-dasharray="550" stroke-dashoffset="-150"/> 
  <circle cx="110" cy="110" r="100" stroke="#172bc3" stroke-width="20" fill="none" stroke-dasharray="550" stroke-dashoffset="-330"/> 
  <circle cx="110" cy="110" r="100" stroke="#5eaefd" stroke-width="20" fill="none" stroke-dasharray="550" stroke-dashoffset="-470"/> 
  <circle cx="110" cy="10" r="10" fill="#5eaefd"/> 
  <circle cx="120" cy="209.5" r="10" fill="#f21d92"/> 
  <circle cx="210" cy="110" r="10" fill="#f21d92"/> 
  <circle cx="11" cy="95" r="10" fill="#172bc3"/> 
</svg>

Answer 3

Вариант SVG без CSS

<svg viewBox="0 0 100 100" height="200px" width="200px"> 
  <defs> 
    <symbol id="line" viewBox="256 346 100 100"> 
      <path stroke-width="5" fill="none" stroke-linecap="round" d="M268.5,395.9c0-20.7,16.8-37.4,37.4-37.4"/> 
    </symbol> 
    <filter id="blurMe" width="200%" height="200%"> 
      <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> 
      <feGaussianBlur result="blurOut" in="offOut" stdDeviation="3" /> 
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> 
    </filter> 
    <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%"> 
      <stop offset="0%" stop-color="#00bc9b" /> 
      <stop offset="100%" stop-color="#5eaefd" /> 
    </linearGradient> 
  </defs> 
  <circle fill="transparent" stroke="white" stoke-width="2" cx="50" cy="43" r="37" filter="url(#blurMe)"/> 
  <use stroke="#f21d92" xlink:href="#line" transform="translate(-14, 73) rotate(-70)"/> 
  <use stroke="#172bc3" xlink:href="#line" transform="translate(20, -20) rotate(20)"/> 
  <use stroke="url(#gradient)" xlink:href="#line" transform="translate(113, 14) rotate(-250)"/> 
  <use stroke="#9631eb" xlink:href="#line" transform="translate(79, 107) rotate(-160)"/> 
</svg>

Answer 4

Решение с Chart.js начиная от 2.1.0+

Chart.pluginService.register({ 
  afterUpdate: function (chart) { 
    if (chart.config.options.elements.arc.roundedCornersFor !== undefined) { 
      items=chart.config.options.elements.arc.roundedCornersFor; 
      items.forEach(function(element) { 
        var arc = chart.getDatasetMeta(0).data[element];             
        arc.round = { 
          x: (chart.chartArea.left + chart.chartArea.right) / 2, 
          y: (chart.chartArea.top + chart.chartArea.bottom) / 2, 
          radius: (chart.outerRadius + chart.innerRadius) / 2, 
          thickness: (chart.outerRadius - chart.innerRadius) / 2 - 1, 
          backgroundColor: arc._model.backgroundColor 
        } 
      }); 
    } 
  }, 
  afterDraw: function (chart) { 
    if (chart.config.options.elements.arc.roundedCornersFor !== undefined) { 
      var ctx = chart.chart.ctx; 
      items=chart.config.options.elements.arc.roundedCornersFor; 
      items.forEach(function(element) { 
        var arc = chart.getDatasetMeta(0).data[element]; 
        var startAngle = Math.PI / 2 - arc._view.startAngle; 
        var endAngle = Math.PI / 2 - arc._view.endAngle; 
        ctx.save(); 
        ctx.translate(arc.round.x, arc.round.y); 
        ctx.fillStyle = arc.round.backgroundColor;  
        ctx.beginPath(); 
        //получаются артефакты 
        //ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);  
        ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI); 
        ctx.closePath(); 
        ctx.fill(); 
        ctx.restore(); 
      }); 
    } 
 
  }, 
}); 
 
var settings = { 
  type: 'doughnut', 
  data: { 
    labels: [], 
    datasets: [{ 
      data: [25, 25, 25,25], 
      backgroundColor: [ 
        "#363edc", 
        "#48d0f0", 
        "#9a31eb", 
        "#f11e94" 
      ], 
      hoverBackgroundColor: [ 
        "#363edc", 
        "#48d0f0", 
        "#9a31eb", 
        "#f11e94" 
      ] 
    }] 
  }, 
  options: { 
      rotation: 10, 
      cutoutPercentage: 80, 
        legend: { 
          display: false 
      }, 
      tooltips: { 
          enabled: false 
      }, 
      elements: { 
        arc: { 
          roundedCornersFor: [0,1,2,3] 
        } 
      } 
  } 
}; 
 
var ctx = document.getElementById("myTest").getContext("2d"); 
var myChart = new Chart(ctx, settings);
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script> 
<canvas id="myTest"></canvas>

READ ALSO
Как определить в каком из div

Как определить в каком из div

Как определить в каком из div с id произошли изменения в этом iteminfo0_game_name или в этом iteminfo1_game_name?

203
Запрет доступности папки по условию

Запрет доступности папки по условию

Столкнулся с такой ситуацией: на свой сайт добавляю много лендингов, то есть выглядит как то так http://sitecom/land1/ и таких лендов куча

213
js click в file_get_contents

js click в file_get_contents

Как реализовать нажатие кнопки при file_get_contentsТо есть на сайте есть кнопка, при нажатии на которую подгружается доп

231