Esta pregunta es el primer resultado para buscar en Google "svg ruta de esquinas redondeadas". Sugerencia de Phrogz para usarstroke
tiene algunas limitaciones (es decir, que no puedo usar el trazo para otros fines y que las dimensiones deben corregirse para el ancho del trazo).
La sugerencia de Jlange de usar una curva es mejor, pero no muy concreta. Terminé usando curvas cuadráticas de Bézier para dibujar esquinas redondeadas. Considere esta imagen de una esquina marcada con un punto azul y dos puntos rojos en los bordes adyacentes:
Las dos líneas se pueden hacer con el L
comando. Para convertir esta esquina afilada en una esquina redondeada, comience a dibujar una curva desde el punto rojo izquierdo (useM x,y
para moverse a ese punto). Ahora, una curva de Bézier cuadrática tiene un solo punto de control que debe establecer en el punto azul. Establezca el final de la curva en el punto rojo de la derecha. Como la tangente en los dos puntos rojos está en la dirección de las líneas anteriores, verá una transición fluida, "esquinas redondeadas".
Ahora, para continuar la forma después de la esquina redondeada, se puede lograr una línea recta en una curva de Bézier estableciendo el punto de control entre en la línea entre las dos esquinas.
Para ayudarme a determinar la ruta, escribí este script de Python que acepta bordes y un radio. La matemática vectorial hace que esto sea realmente muy fácil. La imagen resultante de la salida:
#!/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
y sus variantes no funcionen en SVG.