12

У меня есть проект, над которым я работаю. Необходимо сделать круговую навигацию с кнопками, которые выглядят как сегменты вокруг Iron Man, изображенной ниже.

Я могу рисовать простые фигуры, но я затрудняюсь нарисовать эти полосы с изогнутой формой, как на рисунке ниже.

Я включил пример clip path, и я думаю, что SVG - это то, что мне нужно.

HTML

<div class="button"></div>

CSS

.button {
    background: radial-gradient(circle at 50% 160%,transparent 45%,red 44.5%,red 85%,transparent 85%);
        -webkit-clip-path: polygon(5% 0, 100% 0, 65% 90%, 35% 90%);
        clip-path: polygon(20% 0, 80% 0, 65% 90%, 35% 90%);
}  
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384

2 Answers2

11

Дополнительные примеры сегментов

6 сегментов

Подставляем в скрипт, количество сегментов и

черта- dash=0.8 пробел - gap = 0.2

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .8perimeter/6; let gap = .2perimeter/6;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:purple;fill:none;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg>

6 сегментов

черта- dash=0.2 пробел - gap = 0.8

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .2perimeter/6; let gap = .8perimeter/6;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:yellowgreen;fill:none;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg>

12 сегментов

черта- dash=0.2 пробел - gap = 0.8

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .2perimeter/12; let gap = .8perimeter/12;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:purple;fill:none;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg>

10 сегментов + background

черта- dash=0.9 пробел - gap = 0.1

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .9perimeter/10; let gap = .1perimeter/10;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:greenyellow;fill:gold;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg>

Шестеренка

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 30;

let perimeter = 2Math.PIR let dash = .5perimeter/20; let gap = .5perimeter/20;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:14px; stroke:gray;fill:gray;}
<svg id="svg" viewBox= "-100 -55 200 110"> </svg>

Update

Благодарю за идею @UModeL

Подсолнух

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 30;

let perimeter = 2Math.PIR let dash = .7perimeter/35; let gap = .3perimeter/35;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:22px; stroke:#FFEB3B; fill:#4d4d4d;}
<svg id="svg" viewBox= "-100 -55 200 110"> </svg>
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
  • если цвета для "10-и сегментов" поменять на такие: stroke: #FFEB3B; fill: #4d4d4d;, то можно назвать пример "подсолнух")) – UModeL Dec 06 '18 at 19:30
  • @UModeL cсейчас добавлю :) Я хотел показать тебе, как штудировал эту тему, отвечал на вопрос, а вопрошающий даже спасибо не сказал.. Потом понял свою ошибку,- ему просто нужно было дать быстро готовый ответ, а я всю теорию на примерах дал )))) ха-ха-ха https://ru.stackoverflow.com/q/760290/28748 – Alexandr_TT Dec 06 '18 at 19:34
  • 1
    да, ребята хотят всё и сразу, а потом по десять раз переспрашивают. Самый главный плюс в том, что развёрнутый ответ с примерами, может и не помог данному человеку (в силу срочности), но поможет тысячам с таким же вопросом. – UModeL Dec 06 '18 at 19:39
  • по вашей ссылке, реально огромная работа! Не знаю, хватило бы у меня терпения, для стольких примеров и разбора. Я пониже летаю - https://ru.stackoverflow.com/a/916526/265406 )) – UModeL Dec 06 '18 at 19:45
5
  • Сначала я создаю один сегмент (path). Затем я снова использую его, с помощью вращения.

const SVG_NS = 'http://www.w3.org/2000/svg';
const SVG_XLINK = "http://www.w3.org/1999/xlink";
const deg = 180 / Math.PI;
let R = 50;//внешний радиус
let r = 35;// внутренний радиус
let A = 2*Math.PI/7;// угол для сегмента + пробел
let a = 2*A/3; //  угол для сегмента

let path = document.createElementNS(SVG_NS, 'path'); let p1 = {x:0,y:-R} let p2 = { x : RMath.cos(a - Math.PI/2), y : RMath.sin(a - Math.PI/2) } let p3 = { x : rMath.cos(a - Math.PI/2), y : rMath.sin(a - Math.PI/2) } let p4 = { x : 0, y : -r } let d = M${p1.x},${p1.y} A${R},${R} 0 0,1,${p2.x},${p2.y} L${p3.x},${p3.y} A${r},${r} 0 0,0,${p4.x},${p4.y} L${p1.x},${p1.y}Z; path.setAttributeNS(null, "d", d); path.setAttributeNS(null, "id", "arc"); defs.appendChild(path);

for(let i = 0; i < 7; i++){ let use = document.createElementNS(SVG_NS, 'use'); use.setAttributeNS(SVG_XLINK, "xlink:href", "#arc") use.setAttributeNS(null, "fill", "gold"); use.setAttributeNS(null, "transform", rotate(${i*A*deg})); svg.appendChild(use);

}

<svg id="svg" viewBox= "-100 -55 200 110">

  <defs id="defs"></defs>

  <circle r="25" fill="gold" />


</svg>
  • Или даже проще: на этот раз я использую stroke-dasharray, и я вычисляю размер для штриха и пробелов

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .7perimeter/7; let gap = .3perimeter/7;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:black;fill:none;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg>

Примечания:

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

Пример с 5 сегментами:

const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2Math.PIR let dash = .8perimeter/5; let gap = .2perimeter/5;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray);

circle{stroke-width:20px; stroke:dodgerblue;fill:none;}
<svg id="svg" viewBox= "-100 -55 200 110"></svg> 

Ещё примеры

<style>
circle{stroke-width:20px; stroke:purple;fill:none;}
</style>
<svg id="svg" width="50%" height="50%" viewBox= "-100 -60 200 110">
<circle id="two" cx="0" cy="0" r="28" fill="none"  stroke-width="5" />

</svg> <script> const SVG_NS = 'http://www.w3.org/2000/svg'; let R = 40;

let perimeter = 2Math.PIR let dash = .8perimeter/6; let gap = .2perimeter/6;

let dasharray = document.createElementNS(SVG_NS, 'circle'); dasharray.setAttributeNS(null, "r", R); dasharray.setAttributeNS(null, "stroke-dasharray", ${dash}, ${gap});

svg.appendChild(dasharray); </script>

Вращение сегментов при наведении

circle {
stroke-width:20px;
 stroke:purple;
 fill:transparent;

} circle:hover { stroke:dodgerblue; -webkit-animation: rotate 6s linear infinite; animation: rotate 6s linear infinite; }

@-webkit-keyframes rotate { 100% {-webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg);} } @keyframes rotate { 100% {-webkit-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg);} }

<svg id="svg" width="50%" height="50%" viewBox= "-100 -60 200 110">
<circle id="two" cx="0" cy="0" r="28" fill="none"  stroke-width="5" />

</svg>
<script>
const SVG_NS = 'http://www.w3.org/2000/svg';
let R = 40;

let perimeter = 2*Math.PI*R
let dash = .8*perimeter/6;
let gap = .2*perimeter/6;


let dasharray = document.createElementNS(SVG_NS, 'circle');
dasharray.setAttributeNS(null, "r", R);
dasharray.setAttributeNS(null, "stroke-dasharray", `${dash}, ${gap}`);

svg.appendChild(dasharray);
</script>
Alexandr_TT
  • 110,146
  • 23
  • 114
  • 384
  • 4
    Считаю самым правильным первый вариант, ибо делается меню, где сегменты являются кнопками (читай отдельными элементами). А, в случае со stroke-dasharray, будет затруднительно отлавливать события для каждого штриха. Но, решения полезны в любом случае. – UModeL Dec 06 '18 at 19:19