Как сделать изогнутые прямоугольники (bent rectangle) в SVG

134
01 июня 2019, 08:50

У меня есть проект, над которым я работаю. Необходимо сделать круговую навигацию с кнопками, которые выглядят как сегменты вокруг 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%);
}  
Answer 1

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

6 сегментов

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

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

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);
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 = 2*Math.PI*R 
let dash = .2*perimeter/6; 
let gap = .8*perimeter/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 = 2*Math.PI*R 
let dash = .2*perimeter/12; 
let gap = .8*perimeter/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 = 2*Math.PI*R 
let dash = .9*perimeter/10; 
let gap = .1*perimeter/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 = 2*Math.PI*R 
let dash = .5*perimeter/20; 
let gap = .5*perimeter/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 = 2*Math.PI*R 
let dash = .7*perimeter/35; 
let gap = .3*perimeter/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>

Answer 2
  • Сначала я создаю один сегмент (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 : R*Math.cos(a - Math.PI/2), 
  y : R*Math.sin(a - Math.PI/2) 
} 
let p3 = { 
  x : r*Math.cos(a - Math.PI/2), 
  y : r*Math.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 = 2*Math.PI*R 
let dash = .7*perimeter/7; 
let gap = .3*perimeter/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 = 2*Math.PI*R 
let dash = .8*perimeter/5; 
let gap = .2*perimeter/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> 

READ ALSO
Ошибка в скрипте шаблона ember.js

Ошибка в скрипте шаблона ember.js

Необходимо было написать тестовую функцию в шаблоне Ember(hbs) через тег script

131
Создание необычных форм из div и input [закрыт]

Создание необычных форм из div и input [закрыт]

Нужно получить что-то этого вида(форма авторизации на сайте) возможно ли такое сделать? подскажите пожалуйста как

161
Ползунок с возможностью ввода значений

Ползунок с возможностью ввода значений

Есть обычный ползунок на jQuery Uislide()

138
Как перехватить отправку формы

Как перехватить отправку формы

Есть страница, и на этой странице данные загружаются из другого файла с помощью ajaxТак вот как из загружаемых данных перехватить отправку...

168