Це питання є першим результатом для Googling "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.