这个问题是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中不起作用是非常糟糕的。