Какими способами можно нарисовать нестандартную фигуру?

Разместить в центре страницы фигуру из четырёх кругов, расположенных на равном расстоянии друг от друга; два из кругов соединяются перемычкой в форме, напоминающей песочные часы — перемычка должна быть не прямой, а вогнутой с обеих сторон. Прототип: <a href="https://nia.red/pat/" rel="nofollow">вот</a>.
  • 13 февраля 2026 г. 10:13
Ответы на вопрос 3
Ниже — обзор возможных способов нарисовать такую «нестандартную» фигуру (четыре круга по кругу, два из которых соединены «перемычкой» в виде вогнутого песочных часов), и готовые примеры для трёх наиболее удобных подходов.

Варианты подходов
- SVG — лучший вариант для векторной точной графики. Простой контроль форм (arc, path, Beziers), легко масштабируется и стилизуется CSS/SMIL/JS.
- Canvas 2D — рисуете программно (arc, bezierCurveTo). Удобно для анимаций и динамики.
- Чистый CSS — через clip-path/path(), маски (mask-image), многослойные градиенты; кроссбраузерность хуже, но можно обойтись без SVG.
- SVG + булевы операции (mask/clipPath или сторонние утилиты) — когда нужен точный union/subtract.
- Библиотеки: Paper.js, Snap.svg, D3.js, Fabric.js — упрощают создание кривых и булевых операций.
- Растер/PNG/SVG в графическом редакторе (Inkscape/Illustrator) — если не нужна программная генерация.

Рекомендую SVG — далее привожу готовый пример (центр страницы, 4 круга по окружности, левый и правый соединены вогнутой «песочницей»).

1) SVG (рекомендуется)
- код можно вставить прямо в HTML; легко менять радиусы/позиции/цвет.

Пример (вставьте в тело страницы):
```
<svg viewBox="0 0 400 400" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
  <rect width="100%" height="100%" fill="#fafafa"/>
  <g transform="translate(0,0)" fill="#4a90e2" stroke="#2f6fb0" stroke-width="2">
    <!-- параметры: центр 200,200; расстояние до центров 80; радиус кругов 30 -->
    <!-- четыре круга (право, верх, лево, низ) -->
    <circle cx="280" cy="200" r="30"/>
    <circle cx="200" cy="120" r="30"/>
    <circle cx="120" cy="200" r="30"/>
    <circle cx="200" cy="280" r="30"/>

    <!-- перемычка между левым (120,200) и правым (280,200) -->
    <!-- верхний и нижний кривые делают «вогнутость» (hourglass) -->
    <path d="
      M 120 170
      C 160 120, 240 120, 280 170
      L 280 230
      C 240 280, 160 280, 120 230
      Z
    "/>
  </g>
</svg>
```
Пояснения: путь (path) описывает верхнюю кубическую Безье-кривую от верхней точки левого круга до верхней точки правого круга с контрольными точками, смещёнными внутрь (это даёт вогнутость). Затем идёт линия вниз и нижняя кривая возвращается обратно — в итоге закрытая «лента» hourglass. Кружки и перемычка имеют одинаковый fill, поэтому визуально выглядят как единая фигура.

2) Canvas 2D
- подходит, если нужна анимация или динамическая генерация.

Пример:
```
<canvas id="c" width="400" height="400"></canvas>
<script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');

const cx = 200, cy = 200, orbit = 80, r = 30;
const left = {x: cx - orbit, y: cy};
const right = {x: cx + orbit, y: cy};

ctx.fillStyle = '#4a90e2';
ctx.strokeStyle = '#2f6fb0';
ctx.lineWidth = 2;

// четыре круга
[[right.x,right.y],[cx,cy-orbit],[left.x,left.y],[cx,cy+orbit]].forEach(p=>{
  ctx.beginPath();
  ctx.arc(p[0], p[1], r, 0, Math.PI*2);
  ctx.fill();
  ctx.stroke();
});

// перемычка (hourglass) — верхняя и нижняя кривые
ctx.beginPath();
ctx.moveTo(left.x, left.y - r);
ctx.bezierCurveTo(left.x + 40, left.y - 80, right.x - 40, right.y - 80, right.x, right.y - r);
ctx.lineTo(right.x, right.y + r);
ctx.bezierCurveTo(right.x - 40, right.y + 80, left.x + 40, left.y + 80, left.x, left.y + r);
ctx.closePath();
ctx.fill();
ctx.stroke();
</script>
```

3) CSS / clip-path (без SVG)
- можно использовать clip-path: path('...') или маску. Подходит, если хотите держать всё в DOM-элементе и управлять через CSS.
- caveat: поддержка clip-path: path() не во всех старых браузерах.

Пример (основная идея — вставить SVG-путь в clip-path):
```
<div class="shape"></div>

<style>
.shape{
  width:400px;
  height:400px;
  margin:20px auto;
  background:#4a90e2;
  /* вставляем тот же путь, что и в SVG */
  -webkit-clip-path: path("M 120 170 C 160 120, 240 120, 280 170 L 280 230 C 240 280, 160 280, 120 230 Z M 280 200 A 30 30 0 1 1 280 199.9 Z ...");
  clip-path: path("..."); /* потребуется объединить круги и перемычку в один path */
}
</style>
```
Примечание: в clip-path нужно объединить контуры (path) всех элементов (четыре круга + перемычка) — это труднее вручную, поэтому практичнее сделать SVG и использовать его как <svg> или как background-image.

Дополнительные замечания и советы
- Если вам нужна идеально плавная «стыковка» перемычки и кругов (без видимых швов), лучше использовать один объединённый SVG path (union) или настроить кривые так, чтобы контуры точно стыковались с точками окружностей.
- Если надо вырезать часть (boolean subtract), используйте SVG mask или библиотеку, поддерживающую булевы операции (например, Paper.js, или Inkscape/Illustrator для подготовки SVG).
- Для адаптивности делайте всё в координатах viewBox и масштабируйте через CSS.
- Для анимаций: в SVG можно анимировать атрибут d (path) или применять SMIL/CSS/JS-анимации; в Canvas — перерисовывать.

Если хотите, могу:
- прислать готовый SVG path, который объединяет все четыре круга и перемычку в один закрытый контур (для экспортирования);
- сделать адаптивную версию (в процентах) или анимированную (подтяжка/растяжение перемычки);
- подготовить PNG/SVG-файл по вашему цвету и размеру.

Напишите, какой из способов предпочтительнее и нужно ли точное воссоздание прототипа (я сделаю подгонку координат и дам итоговый файл).
Открыть любой графический редактор, нарисовать желаемое и разместить на вашей странице.
Примерно так: <br/> <pre><code>&lt;style&gt;
    body {
        margin: 0;
        min-height: 100vh;
        position: relative;
    }
    .krug {
        width:100px; height:100px;
        background-color:#99F;
        border-radius:50%;
        margin:10px;
    }
    .cont-in {
        display:inline-block;
    }
    .cent {
        width:150px; height:50px;
        background-color:#99F;
        transform:rotate(-45deg);
        position:absolute;
        top:90px; left:50px;
        display:inline-block;
    }
.cont-out {
        width: 260px; height: 260px;
        position: absolute;
        left: 0; top: 0;
        right: 0; bottom: 0;
        margin: auto;
}
&lt;/style&gt;
&lt;div class="cont-out"&gt;
    &lt;div class="cont-in"&gt;
        &lt;div class="krug"&gt;&lt;/div&gt;
        &lt;div class="krug"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="cont-in"&gt;
        &lt;div class="krug"&gt;&lt;/div&gt;
        &lt;div class="krug"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="cent"&gt;&lt;/div&gt;
&lt;/div&gt;</code></pre>
Похожие вопросы