Подтвердить что ты не робот

Округленный угол SVG

У меня есть следующий SVG:

<g>
  <path id="k9ffd8001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="#a0a700"></path>
  <path id="kb8000001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="url(#k9ffb0001)"></path>
</g>

Я хочу получить CSS-подобный эффект border-top-right-radius и border-top-bottom-radius.

Как мне добиться этого эффекта закругления угла?

4b9b3361

Ответ 1

Вот как вы можете создать прямоугольник с закругленными углами с помощью SVG Path:

<path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" />

объяснение

m100,100: перейти к точке (100,100)

h200: нарисуйте горизонтальную линию 200px от того места, где мы находимся

a20,20 0 0 1 20,20: нарисуйте дугу с радиусом X 20px, радиусом Y 20px по часовой стрелке до точки с разницей в 20px по оси X и Y.

v200: нарисуйте вертикальную линию 200px от того места, где мы находимся

a20,20 0 0 1 -20, 20: нарисуйте дугу с радиусом X и Y 20 пикселей по часовой стрелке до точки с разницей в -20 px по оси X и 20 пикселей по оси Y

h -20 0: нарисуйте горизонтальную линию -20 0px от того места, где мы находимся

a20,20 0 0 1 -20, -20: нарисуйте дугу с радиусом X и Y 20 пикселей по часовой стрелке до точки с разницей в -20 px в разнице X и -20 px в оси Y

v -20 0: нарисуйте вертикальную линию -20 0px от того места, где мы находимся

a20,20 0 0 1 20, -20: нарисуйте дугу с радиусом X и Y 20 пикселей по часовой стрелке до точки с разницей X в 20 пикселей и разностью -20 px по оси Y

z: закрыть путь

<svg width="440" height="440">
  <path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" fill="none" stroke="black" stroke-width="3" />
</svg>

Ответ 2

Не уверен, почему никто не опубликовал фактический ответ SVG. Вот прямоугольник SVG с закругленными углами (радиус 3) сверху:

<svg:path d="M0,0 L0,27 A3,3 0 0,0 3,30 L7,30 A3,3 0 0,0 10,27 L10,0 Z" />

Это перемещение к (M), линия к (L), дуга к (A), линия к (L), дуга к (A), линия к (L), близкий путь (Z).

Числа, разделенные запятыми, являются абсолютными координатами. Дуги определяются с помощью дополнительных параметров, определяющих радиус и тип дуги. Это также может быть достигнуто с помощью относительных координат (используйте строчные буквы для L и A).

Полный справочник по этим командам находится на странице Пути SVG W3C, а дополнительные справочные материалы по путям SVG можно найти в этой статье.

Ответ 3

Как упоминалось в моем ответе на Применение закругленных углов к путям/полигонам, я написал рутину в javascript для общих закруглений углов путей SVG, с примерами здесь: http://plnkr.co/edit/kGnGGyoOCKil02k04snu.

Он будет работать независимо от любых эффектов удара, которые могут возникнуть у вас. Чтобы использовать, включите файл rounding.js из Plnkr и вызовите функцию следующим образом:

roundPathCorners(pathString, radius, useFractionalRadius)

Результатом будет округленный путь.

Результаты выглядят так:

SVG Path Rounding Examples

Ответ 4

Вы явно установили stroke-linejoin в round, но ваш stroke-width в 0, поэтому, конечно, вы не увидите закругленные углы, если у вас нет обводки.

Здесь представлен модифицированный пример с закругленными углами, выполненными с помощью штрихов:
http://jsfiddle.net/8uxqK/1/

<path d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z"
      stroke-width="5"
      stroke-linejoin="round"
      stroke="#808600"
      fill="#a0a700" />

В противном случае - если вам нужна фактическая закругленная заполненность формы, а не только округлый жирный штрих - вы должны сделать то, что говорит @Jlange, и сделать фактическую округлую форму.

Ответ 5

Я также хотел бы рассмотреть возможность использования простого старого <rect> который предоставляет атрибуты rx и ry

MDN SVG docs <- обратите внимание на второй нарисованный прямоугольный элемент

Ответ 6

Этот вопрос является первым результатом для Gogling "svg rounded cornerners". Предложение Phrogz использовать stroke имеет некоторые ограничения (а именно, что я не могу использовать штрих для других целей и что размеры должны быть исправлены для ширины штриха).

Предложение Jlange использовать кривую лучше, но не очень конкретно. В итоге я использовал квадратичные кривые Безье для рисования округлых углов. Рассмотрим эту картину угла, отмеченного синей точкой, и двумя красными точками на смежных ребрах:

corner of a figure marked blue with two points on the adjacent edges

Две строки могут быть сделаны с помощью команды L. Чтобы превратить этот острый угол в закругленный угол, начните рисовать кривую из левой красной точки (используйте M x,y, чтобы перейти к этой точке). Теперь квадратичная кривая Безье имеет только одну контрольную точку, которую вы должны установить в синей точке. Установите конец кривой в правой красной точке. Поскольку касательная в двух красных точках находится в направлении предыдущих линий, вы увидите плавный переход, "закругленные углы".

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

Чтобы помочь мне определить путь, я написал этот Python script, который принимает ребра и радиус. Векторная математика делает это очень легко. Полученное изображение с выхода:

shape created from script output

#!/usr/bin/env python
# Given some vectors and a border-radius, output a SVG path with rounded
# corners.
#
# Copyright (C) Peter Wu <[email protected]>

from math import sqrt

class Vector(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def sub(self, vec):
        return Vector(self.x - vec.x, self.y - vec.y)

    def add(self, vec):
        return Vector(self.x + vec.x, self.y + vec.y)

    def scale(self, n):
        return Vector(self.x * n, self.y * n)

    def length(self):
        return sqrt(self.x**2 + self.y**2)

    def normal(self):
        length = self.length()
        return Vector(self.x / length, self.y / length)

    def __str__(self):
        x = round(self.x, 2)
        y = round(self.y, 2)
        return '{},{}'.format(x, y)

# A line from vec_from to vec_to
def line(vec_from, vec_to):
    half_vec = vec_from.add(vec_to.sub(vec_from).scale(.5))
    return '{} {}'.format(half_vec, vec_to)

# Adds 'n' units to vec_from pointing in direction vec_to
def vecDir(vec_from, vec_to, n):
    return vec_from.add(vec_to.sub(vec_from).normal().scale(n))

# Draws a line, but skips 'r' units from the begin and end
def lineR(vec_from, vec_to, r):
    vec = vec_to.sub(vec_from).normal().scale(r)
    return line(vec_from.add(vec), vec_to.sub(vec))

# An edge in vec_from, to vec_to with radius r
def edge(vec_from, vec_to, r):
    v = vecDir(vec_from, vec_to, r)
    return '{} {}'.format(vec_from, v)


# Hard-coded border-radius and vectors
r = 5
a = Vector(  0,  60)
b = Vector(100,   0)
c = Vector(100, 200)
d = Vector(  0, 200 - 60)

path = []
# Start below top-left edge
path.append('M {} Q'.format(a.add(Vector(0, r))))

# top-left edge...
path.append(edge(a, b, r))
path.append(lineR(a, b, r))
path.append(edge(b, c, r))
path.append(lineR(b, c, r))
path.append(edge(c, d, r))
path.append(lineR(c, d, r))
path.append(edge(d, a, r))
path.append(lineR(d, a, r))

# Show results that can be pushed into a <path d="..." />
for part in path:
    print(part)

Ответ 7

Я сам столкнулся с этой проблемой сегодня и сумел решить ее, написав небольшую функцию JavaScript.

Из того, что я могу сказать, нет простого способа задать элемент пути в svg с закругленными углами, кроме случаев, когда вам нужно только скруглить границы, и в этом случае (CSS) атрибуты stroke, stroke-width и, что наиболее важно, stroke- linejoin = "round" вполне достаточно.

Однако в моем случае я использовал объект контура для создания пользовательских фигур с n углами, которые заполнены определенным цветом и не имеют видимых границ, так:

enter image description here

Мне удалось написать быструю функцию, которая принимает массив координат для пути svg и возвращает готовую строку пути для вставки в атрибут d элемента html пути. Получившаяся форма будет выглядеть примерно так:

enter image description here

Вот функция:

/**
* Creates a coordinate path for the Path SVG element with rounded corners
* @param pathCoords - An array of coordinates in the form [{x: Number, y: Number}, ...]
*/
createRoundedPathString (pathCoords) {
    const path = [];
    const curveRadius = 3;

    // Reset indexes, so there are no gaps
    pathCoords = pathCoords.filter(() => true);

    for (let i = 0; i < pathCoords.length; i++) {

      // 1. Get current coord and the next two (startpoint, cornerpoint, endpoint) to calculate rounded curve
      const c2Index = ((i + 1) > pathCoords.length - 1) ? (i + 1) % pathCoords.length : i + 1;
      const c3Index = ((i + 2) > pathCoords.length - 1) ? (i + 2) % pathCoords.length : i + 2;

      const c1 = pathCoords[i],
            c2 = pathCoords[c2Index],
            c3 = pathCoords[c3Index];

      // 2. For each 3 coords, enter two new path commands: Line to start of curve, bezier curve around corner.

      // Calculate curvePoint c1 -> c2
      const c1c2Distance = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
      const c1c2DistanceRatio = (c1c2Distance - curveRadius) / c1c2Distance;
      const c1c2CurvePoint = [
        ((1 - c1c2DistanceRatio) * c1.x + c1c2DistanceRatio * c2.x).toFixed(1),
        ((1 - c1c2DistanceRatio) * c1.y + c1c2DistanceRatio * c2.y).toFixed(1)
      ];

      // Calculate curvePoint c2 -> c3
      const c2c3Distance = Math.sqrt(Math.pow(c2.x - c3.x, 2) + Math.pow(c2.y - c3.y, 2));
      const c2c3DistanceRatio = curveRadius / c2c3Distance;
      const c2c3CurvePoint = [
        ((1 - c2c3DistanceRatio) * c2.x + c2c3DistanceRatio * c3.x).toFixed(1),
        ((1 - c2c3DistanceRatio) * c2.y + c2c3DistanceRatio * c3.y).toFixed(1)
      ];

      // If at last coord of polygon, also save that as starting point
      if (i === pathCoords.length - 1) {
        path.unshift('M' + c2c3CurvePoint.join(','));
      }

      // Line to start of curve (L endcoord)
      path.push('L' + c1c2CurvePoint.join(','));
      // Bezier line around curve (Q controlcoord endcoord)
      path.push('Q' + c2.x + ',' + c2.y + ',' + c2c3CurvePoint.join(','));
    }
    // Logically connect path to starting point again (shouldn't be necessary as path ends there anyway, but seems cleaner)
    path.push('Z');

    return path.join(' ');
}

Вы можете определить силу округления, установив переменную curveRadius вверху. По умолчанию 3 для системы координат 100x100 (область просмотра), но в зависимости от размера вашего svg, вам может потребоваться изменить это.

Ответ 8

Вот несколько путей для вкладок:

https://codepen.io/mochime/pen/VxxzMW

<!-- left tab -->
<div>
  <svg width="60" height="60">
    <path d="M10,10 
             a10 10 0 0 1 10 -10
             h 50   
             v 47
             h -50
             a10 10 0 0 1 -10 -10
             z"
      fill="#ff3600"></path>
  </svg>
</div>

<!-- right tab -->
<div>
  <svg width="60" height="60">
    <path d="M10 0   
             h 40
             a10 10 0 0 1 10 10
             v 27
             a10 10 0 0 1 -10 10
             h -40
             z"
      fill="#ff3600"></path>
  </svg>
</div>

<!-- tab tab :) -->
<div>
  <svg width="60" height="60">
    <path d="M10,40 
             v -30
             a10 10 0 0 1 10 -10
             h 30
             a10 10 0 0 1 10 10
             v 30
             z"
      fill="#ff3600"></path>
  </svg>
</div>

Ответ 9

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

<svg viewBox="0 0 1 0.6" stroke="black" fill="grey" style="stroke-width:0.05px;">
  <path d="M0.7 0.2 L0.1 0.1 A0.0001 0.0001 0 0 0 0.099 0.101 L0.5 0.5Z"></path>
</svg>

Ответ 10

<?php
$radius = 20;
$thichness = 4;
$size = 200;

if($s == 'circle'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<circle cx="' . ($size/2) . '" cy="' . ($size/2) . '" r="' . (($size/2)-$thichness) . '" stroke="black" stroke-width="' . $thichness . '" fill="none" />';
  echo '</svg>';
}elseif($s == 'square'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<path d="M' . ($radius+$thichness) . ',' . ($thichness) . ' h' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',' . $radius . ' v' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',' . $radius . ' h-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',-' . $radius . ' v-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',-' . $radius . ' z" fill="none" stroke="black" stroke-width="' . $thichness . '" />';
  echo '</svg>';
}
?>

Ответ 11

Вы используете элемент path, почему бы вам просто не дать путь кривой? См. Здесь, как создавать кривые с использованием элементов пути: http://www.w3.org/TR/SVG/paths.html#PathDataCurveCommands