CSS Only Pie Chart - Как добавить интервал / отступ между сегментами?
Я построил круговую диаграмму только для CSS, но мне нужно добавить пространство между каждым сегментом, как если бы это была граница. Я попытался добавить границу к каждому фрагменту, но на самом деле это не сработало.
Есть идеи, как сделать эту круговую диаграмму CSS более похожей на следующее изображение?
Мой код:
.palette {
height: 48px;
width: 48px;
}
.palette .colorOuter1,
.palette .colorOuter2,
.palette .colorOuter3,
.palette .colorOuter4,
.palette .colorOuter5 {
height: 200px;
width: 200px;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
clip: rect(0px, 200px, 200px, 100px);
}
.palette .colorOuter1 {
clip: auto;
background: #eee;
}
.palette .colorOuter2 {
transform: rotate(0deg);
}
.palette .colorOuter2 {
transform: rotate(72deg);
}
.palette .colorOuter3 {
transform: rotate(144deg);
}
.palette .colorOuter4 {
transform: rotate(216deg);
}
.palette .colorOuter5 {
transform: rotate(288deg);
}
.palette .colorInner1,
.palette .colorInner2,
.palette .colorInner3,
.palette .colorInner4,
.palette .colorInner5 {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
border-radius: 50%;
transform: rotate(72deg);
}
.palette .colorInner1 {
background: #5D5E63;
clip: rect(0px, 100px, 200px, 0px);
}
.palette .colorInner2 {
background-color: #AEADA9;
clip: rect(0px, 100px, 100px, 0px);
}
.palette .colorInner3 {
background-color: #D5C4A8;
clip: rect(0px, 100px, 100px, 0px);
}
.palette .colorInner4 {
background-color: #AA875F;
clip: rect(0px, 100px, 100px, 0px);
}
.palette .colorInner5 {
background-color: #B7CBC7;
clip: rect(0px, 100px, 100px, 0px);
}
.palette .centerOverlay {
position: absolute;
border-radius: 50%;
top: 60px;
left: 60px;
background: #fff;
width: 80px;
height: 80px;
display: block;
clip: auto;
}
<div class="palette">
<div class="colorOuter1">
<div class="colorInner1"></div>
</div>
<div class="colorOuter2">
<div class="colorInner2"></div>
</div>
<div class="colorOuter3">
<div class="colorInner3"></div>
</div>
<div class="colorOuter4">
<div class="colorInner4"></div>
</div>
<div class="colorOuter5">
<div class="colorInner5"></div>
</div>
<div class="centerOverlay"></div>
</div>
Свободный перевод вопроса CSS Only Pie Chart - How to add spacing/padding between slices? от участника @stwhite.
Ответы (1 шт):
Сначала я бы воссоздал это с меньшим количеством кода, с помощью clip-path, как показано ниже:
.palette {
height: 200px;
width: 200px;
position:relative;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:50px solid var(--c,red);
border-radius:50%;
clip-path:polygon(50% 50%, 50% 0%, 100% 0%,100% 33.745%);
}
.color1 {
transform:rotate(72deg);
--c:blue;
}
.color2 {
transform:rotate(144deg);
--c:orange;
}
.color3 {
transform:rotate(-72deg);
--c:green;
}
.color4 {
transform:rotate(-144deg);
--c:purple;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
Затем вы можете применить translation к своим элементам, чтобы создать пробелы:
.palette {
height: 200px;
width: 200px;
position:relative;
margin:20px;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:50px solid var(--c,red);
border-radius:50%;
clip-path:polygon(50% 50%, 50% 0%, 100% 0%,100% 33.745%);
}
.color1 {
transform:rotate(72deg) translate(5px,-5px);
--c:blue;
}
.color2 {
transform:rotate(144deg) translate(5px,-5px);
--c:orange;
}
.color3 {
transform:rotate(-72deg) translate(5px,-5px);
--c:green;
}
.color4 {
transform:rotate(-144deg) translate(5px,-5px);
--c:purple;
}
.color5 {
transform:rotate(0) translate(5px,-5px);
--c:red;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
Или, если вы хотите создать эффект отсутствующих частей, чтобы сохранить круглую форму (как показано на скриншоте), вам необходимо настроить траекторию clip-path.
.palette {
height: 200px;
width: 200px;
position:relative;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:50px solid var(--c,red);
border-radius:50%;
clip-path:polygon(
calc(50% + 5px) 50%,
calc(50% + 5px) 0%,
100% 0%,
100% calc(33.745% - 5px),
50% calc(50% - 5px));
}
.color1 {
transform:rotate(72deg);
--c:blue;
}
.color2 {
transform:rotate(144deg);
--c:orange;
}
.color3 {
transform:rotate(-72deg);
--c:green;
}
.color4 {
transform:rotate(-144deg);
--c:purple;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
А с переменными CSS мы легко справимся со всем:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:var(--s) solid var(--c,red);
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(33.745% - var(--g)/2),
50% calc(50% - var(--g)/2));
}
.color1 {
transform:rotate(72deg);
--c:blue;
}
.color2 {
transform:rotate(144deg);
--c:orange;
}
.color3 {
transform:rotate(-72deg);
--c:green;
}
.color4 {
transform:rotate(-144deg);
--c:purple;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
</div>
Используя тот же код, вы можете легко масштабировать до любого количества сегментов:
С 8 сегментами:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:var(--s) solid var(--c,red);
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(0% - var(--g)/2),
50% calc(50% - var(--g)/2));
}
.color1 {
transform:rotate(45deg); /* 360/8 */
--c:blue;
}
.color2 {
transform:rotate(90deg);
--c:orange;
}
.color3 {
transform:rotate(135deg);
--c:green;
}
.color4 {
transform:rotate(180deg);
--c:purple;
}
.color5 {
transform:rotate(-45deg); /* 360/8 */
--c:orange;
}
.color6 {
transform:rotate(-90deg);
--c:lightblue;
}
.color7 {
transform:rotate(-135deg);
--c:pink;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
Три сегмента:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:var(--s) solid var(--c,red);
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(78.665% - var(--g)/2),
50% calc(50% - var(--g)/2));
}
.color1 {
transform:rotate(120deg);
--c:blue;
}
.color2 {
transform:rotate(-120deg);
--c:orange;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
</div>
Вот формула магического числа, используемого в clip-path:
- 5 сегментов:
33.75% = 50% - tan(90deg - 72deg)*50% - 8 сегментов:
0% = 50% - tan(90deg - 45deg)*50% - 3 сегмента:
78.665% = 50% - tan(90deg - 120deg)*50%
Таким образом, общая формула для N сегментов составляет 50% * (1 - tan (90deg - 360deg / N)) с N в [3 8].
Если N <3, у нас есть тривиальные случаи, когда нам не нужен сложный код.
Для N > 8 нам нужен другой путь отсечения и другая формула: 50% * (1 + tan (360deg / N))
Пример с 10 сегментами:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:var(--s) solid var(--c,red);
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
calc(86.327% - var(--g)/2) 0%,
50% calc(50% - var(--g)/2));
}
.color1 {
transform:rotate(36deg);
--c:blue;
}
.color2 {
transform:rotate(72deg);
--c:orange;
}
.color3 {
transform:rotate(108deg);
--c:green;
}
.color4 {
transform:rotate(144deg);
--c:purple;
}
.color5 {
transform:rotate(180deg);
--c:lightblue;
}
.color6 {
transform:rotate(-36deg);
--c:silver;
}
.color7 {
transform:rotate(-72deg);
--c:black;
}
.color8 {
transform:rotate(-108deg);
--c:darkgreen;
}
.color9 {
transform:rotate(-144deg);
--c:pink;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
Идея на случай, если вы хотите добиться градиентной окраски. При этом используется конический градиент, поэтому пока не будет работать в Firefox:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
border:var(--s) solid transparent;
background:
linear-gradient(#fff,#fff) padding-box,
conic-gradient(from calc(-1*var(--d,0deg)), red,blue,green) border-box;
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
calc(86.327% - var(--g)/2) 0%,
50% calc(50% - var(--g)/2));
transform:rotate(var(--d,0deg));
}
.color1 {
--d:36deg;
}
.color2 {
--d:72deg;
}
.color3 {
--d:108deg;
}
.color4 {
--d:144deg;
}
.color5 {
--d:180deg;
}
.color6 {
--d:-36deg;
}
.color7 {
--d:-72deg;
}
.color8 {
--d:-108deg;
}
.color9 {
--d:-144deg;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
Вы можете смоделировать другую окраску градиента с помощью linear-gradient, и у вас будет лучшая поддержка:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
padding:var(--s);
background:
linear-gradient(#fff,#fff) content-box,
linear-gradient(red,blue,green) padding-box;
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(0% - var(--g)/2),
50% calc(50% - var(--g)/2));
transform:rotate(var(--d,0deg));
}
.palette > *:before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
padding:inherit;
background:inherit;
transform:rotate(calc(-1*var(--d,0deg)));
border-radius:50%;
}
.color1 {
--d:45deg;
}
.color2 {
--d:90deg;
}
.color3 {
--d:135deg;
}
.color4 {
--d:180deg;
}
.color5 {
--d:-45deg;
}
.color6 {
--d:-90deg;
}
.color7 {
--d:-135deg;
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
Мы можем добавить маску для полной прозрачности:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:linear-gradient(red,blue,green) padding-box;
-webkit-mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s)));
mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s)));
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
100% 0%,
100% calc(0% - var(--g)/2),
50% calc(50% - var(--g)/2));
transform:rotate(var(--d,0deg));
}
.palette > *:before {
content:"";
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background:inherit;
transform:rotate(calc(-1*var(--d,0deg)));
border-radius:50%;
}
.color1 {
--d:45deg;
}
.color2 {
--d:90deg;
}
.color3 {
--d:135deg;
}
.color4 {
--d:180deg;
}
.color5 {
--d:-45deg;
}
.color6 {
--d:-90deg;
}
.color7 {
--d:-135deg;
}
body {
background:linear-gradient(to left,grey,#fff);
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
</div>
То же самое и с коническим градиентом:
.palette {
--g:10px; /* The gap between shapes*/
--s:50px; /* the size*/
height: 200px;
width: 200px;
position:relative;
display:inline-block;
overflow:hidden;
}
.palette > * {
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
background: conic-gradient(from calc(-1*var(--d,0deg)), red,blue,green);
-webkit-mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s)));
mask:radial-gradient(farthest-side,transparent calc(99% - var(--s)),#fff calc(100% - var(--s)));
border-radius:50%;
clip-path:polygon(
calc(50% + var(--g)/2) 50%,
calc(50% + var(--g)/2) 0%,
calc(86.327% - var(--g)/2) 0%,
50% calc(50% - var(--g)/2));
transform:rotate(var(--d,0deg));
}
.color1 {
--d:36deg;
}
.color2 {
--d:72deg;
}
.color3 {
--d:108deg;
}
.color4 {
--d:144deg;
}
.color5 {
--d:180deg;
}
.color6 {
--d:-36deg;
}
.color7 {
--d:-72deg;
}
.color8 {
--d:-108deg;
}
.color9 {
--d:-144deg;
}
body {
background:linear-gradient(to left,grey,white);
}
<div class="palette">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:40px;--g:20px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
<div class="palette" style="--s:60px;--g:0px">
<div class="color1"></div>
<div class="color2"></div>
<div class="color3"></div>
<div class="color4"></div>
<div class="color5"></div>
<div class="color6"></div>
<div class="color7"></div>
<div class="color8"></div>
<div class="color9"></div>
<div class="color10"></div>
</div>
Свободный перевод ответа от участника @Temani Afif.






