Diese Frage ist das erste Ergebnis für Googeln "svg abgerundete Ecken Pfad". Der Vorschlag von Phrogz zur Verwendung stroke
weist einige Einschränkungen auf (nämlich, dass ich den Strich nicht für andere Zwecke verwenden kann und dass die Abmessungen für die Strichbreite korrigiert werden müssen).
Jlange Vorschlag, eine Kurve zu verwenden, ist besser, aber nicht sehr konkret. Am Ende habe ich quadratische Bézier-Kurven zum Zeichnen abgerundeter Ecken verwendet. Betrachten Sie dieses Bild einer Ecke, die mit einem blauen Punkt und zwei roten Punkten an benachbarten Kanten markiert ist:
Die zwei Zeilen könnten mit dem L
Befehl erstellt werden. Um diese scharfe Ecke in eine abgerundete Ecke zu verwandeln, zeichnen Sie eine Kurve vom linken roten Punkt (verwenden Sie M x,y
diese Option, um zu diesem Punkt zu gelangen). Jetzt hat eine quadratische Bézier-Kurve nur einen einzigen Kontrollpunkt, den Sie auf den blauen Punkt setzen müssen. Setzen Sie das Ende der Kurve auf den rechten roten Punkt. Da die Tangente an den beiden roten Punkten in Richtung der vorherigen Linien verläuft, sehen Sie einen fließenden Übergang, "abgerundete Ecken".
Um nun die Form nach der abgerundeten Ecke fortzusetzen, kann eine gerade Linie in einer Bézier-Kurve erreicht werden, indem der Kontrollpunkt zwischen auf der Linie zwischen den beiden Ecken festgelegt wird.
Um mir bei der Ermittlung des Pfads zu helfen, habe ich dieses Python-Skript geschrieben, das Kanten und einen Radius akzeptiert. Vektormathematik macht dies eigentlich sehr einfach. Das resultierende Bild aus der Ausgabe:
#!/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
und seine Varianten in SVG nicht funktionieren.