Как добавить поле для обводки SVG Circle для простого пончика - PullRequest
2 голосов
/ 28 мая 2019

Я пытаюсь построить очень простую диаграмму пончиков.

Вот рабочий код:

const countries = [
{'percent': 2,colour: 'red'},
{'percent': 28,colour: 'blue'},
{'percent': 36,colour: 'yellow'},
{'percent': 34,colour: 'orange'}
];


const donutData = countries.map((country, index) => {
  return {
    stroke: country.colour,
    dashoffset: 25 - countries.slice(0, index).reduce((a, b) => a + b.percent, 0),
    dashArray: [country.percent, 100 - country.percent]
  }
});
const div = document.createElement('div');
div.innerHTML = '<svg id="donut" width="100%" height="100%" viewBox="3 3 36 36"></svg>';
document.body.appendChild(div);
document.querySelector('#donut').innerHTML= donutData.reduce((a, item) => {
  return a +
    `<circle 
  	cx="21"
    cy="21"
    fill="transparent"
    r="15.91549430918954"
    stroke-width="2.3"
    stroke="${item.stroke}"
    stroke-dasharray="${item.dashArray[0]} ${item.dashArray[1]}"
    stroke-dashoffset="${item.dashoffset}"></circle>
`;
}, '')

https://jsfiddle.net/miladhi/1dxnkjht/1/

Выше работает нормально, но попробуйте добавить stroke-linecap="round" к <circle>, и он будет иметь форму, штрихи расположены друг над другом.

Как вы можете видеть здесь https://jsfiddle.net/miladhi/x8w4kgdv/.

Я могу понять проблему, но не знаю, как добавить немного поля между штрихами, чтобы избежать уродливой укладки.

Я ценю любое предложение.

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Это то, что вы хотели?

Просто вычтите радиус круглых концевых колпачков (по одному на каждый конец) из длины тире.

Пока радиус круга не очень малкруглые колпачки должны аккуратно касаться друг друга.

const countries = [
{'percent': 10,colour: 'red'},
{'percent': 20,colour: 'blue'},
{'percent': 36,colour: 'yellow'},
{'percent': 34,colour: 'orange'}
];

const STROKE_WIDTH = 2.3;

const donutData = countries.map((country, index) => {
  // Subtract the radius of the round cap, twice.
  const dashLength = country.percent - STROKE_WIDTH;
  return {
    stroke: country.colour,
    dashoffset: 25 - countries.slice(0, index).reduce((a, b) => a + b.percent, 0),
    dashArray: [dashLength, 100 - dashLength]
  }
});
const div = document.createElement('div');
div.innerHTML = '<svg id="donut" width="100%" height="100%" viewBox="3 3 36 36"></svg>';
document.body.appendChild(div);
document.querySelector('#donut').innerHTML= donutData.reduce((a, item) => {
  return a +
    `<circle 
  	cx="21"
    cy="21"
    fill="transparent"
    r="15.91549430918954"
    stroke-width="${STROKE_WIDTH}"
    stroke-linecap="round"
    stroke="${item.stroke}"
    stroke-dasharray="${item.dashArray[0]} ${item.dashArray[1]}"
    stroke-dashoffset="${item.dashoffset}"></circle>
`;
}, '')

Обновление

Версия, которая несколько изящно обрабатывает короткие строки.

const countries = [
{'percent': 10, colour: 'red'},
{'percent': 20, colour: 'blue'},
{'percent': 36, colour: 'yellow'},
{'percent': 33, colour: 'orange'},
{'percent': 1,  colour: 'green'},
];

const STROKE_WIDTH = 2.3;

const donutData = countries.map((country, index) => {
  let dashLength, offsetAdjust, caps;
  if (country.percent >= STROKE_WIDTH) {
    // Subtract the radius of the round cap, twice.
    dashLength = country.percent - STROKE_WIDTH;
    offsetAdjust = STROKE_WIDTH / 2;
    caps = "round";
  } else {
    dashLength = country.percent;
    offsetAdjust = 0;
    caps = "butt";
  }
  return {
    stroke: country.colour,
    dashoffset: 25 - countries.slice(0, index).reduce((a, b) => a + b.percent, 0) - offsetAdjust,
    dashArray: [dashLength, 100 - dashLength],
    caps: caps
  }
});
const div = document.createElement('div');
div.innerHTML = '<svg id="donut" width="100%" height="100%" viewBox="3 3 36 36"></svg>';
document.body.appendChild(div);
document.querySelector('#donut').innerHTML= donutData.reduce((a, item) => {
  return a +
    `<circle 
  	cx="21"
    cy="21"
    fill="transparent"
    r="15.91549430918954"
    stroke-width="${STROKE_WIDTH}"
    stroke-linecap="${item.caps}"
    stroke="${item.stroke}"
    stroke-dasharray="${item.dashArray[0]} ${item.dashArray[1]}"
    stroke-dashoffset="${item.dashoffset}"></circle>
`;
}, '')
0 голосов
/ 31 мая 2019

Вот как вы можете сделать это с путями и маркерами. Хитрость заключается в том, чтобы использовать комбинацию маркера начала / конца маркера. Кажущееся перекрытие предыдущей строки фактически прикреплено к текущей строке как начало маркера.

<svg width="600px" height="400px">
  <defs>
    <marker id="round-cap-blue" viewBox="0 0 1 1" 
        markerWidth="1" markerHeight="1"
        orient="auto" refX="0.5" refY="0.5">
      <circle cx="0.5" cy="0.5" r="0.5" fill="blue"/>
    </marker>
    
        <marker id="round-cap-red" viewBox="0 0 1 1" 
        markerWidth="1" markerHeight="1"
        orient="auto" refX="0.5" refY="0.5">
      <circle cx="0.5" cy="0.5" r="0.5" fill="red"/>
    </marker>
    
            <marker id="round-cap-green" viewBox="0 0 1 1" 
        markerWidth="1" markerHeight="1"
        orient="auto" refX="0.5" refY="0.5">
      <circle cx="0.5" cy="0.5" r="0.5" fill="green"/>
    </marker>
    
    
    </defs>
  
  <g transform="translate(100,0)">
    
  <path fill="none" stroke="blue" stroke-width="30" d="M 150 150
           A 100 100 0 0 0 50 50" marker-end="url(#round-cap-blue)"/>
  
   <path fill="none" stroke="red" stroke-width="30" d="M 50 250
           A 100 100 0 0 0 150 150" marker-end="url(#round-cap-red)"/>
    
   <path fill="none" stroke="green" stroke-width="30" d="M 50 50
           A 100 100 0 0 0 50 250" marker-start="url(#round-cap-blue)" marker-end="url(#round-cap-green)"/>
    
    
  </g>
  
</svg>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...