Этот вопрос является первым результатом поиска в Google "пути с закругленными углами svg". Предложение Phrogz для использования stroke
имеет некоторые ограничения (а именно, что я не могу использовать штрих для других целей и что размеры должны быть скорректированы с учетом ширины штриха).
Предложение Jlange использовать кривую лучше, но не очень конкретное. В итоге я использовал квадратичные кривые Безье для рисования закругленных углов. Рассмотрим это изображение угла, отмеченного синей точкой и двумя красными точками на смежных краях:
Две строчки можно создать с помощью L
команды. Чтобы превратить этот острый угол в закругленный, начните рисовать кривую от левой красной точки (используйте M x,y
для перехода к этой точке). Теперь у квадратичной кривой Безье есть только одна контрольная точка, которую вы должны установить на синей точке. Установите конец кривой в правой красной точке. Поскольку касательная к двум красным точкам направлена в направлении предыдущих линий, вы увидите плавный переход, «закругленные углы».
Теперь, чтобы продолжить форму после закругленного угла, можно получить прямую линию кривой Безье, установив контрольную точку между ними на линии между двумя углами.
Чтобы помочь мне определить путь, я написал этот скрипт Python, который принимает края и радиус. Векторная математика делает это на самом деле очень просто. Полученное изображение из вывода:
#!/usr/bin/env python
# Given some vectors and a border-radius, output a SVG path with rounded
# corners.
#
# Copyright (C) Peter Wu <peter@lekensteyn.nl>
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)
border-radius
и его варианты не работают в SVG.