この質問は、グーグル「svg rounded corners path」の最初の結果です。使用する Phrogz の提案にstroke
はいくつかの制限があります (つまり、ストロークを他の目的に使用することはできず、ストロークの幅に合わせて寸法を修正する必要があります)。
曲線を使用するという Jlange の提案は優れていますが、あまり具体的ではありません。丸みを帯びた角を描くために二次ベジエ曲線を使用することになりました。隣接するエッジに青い点と 2 つの赤い点でマークされたコーナーのこの図を検討してください。
この 2 行は、コマンドで作成できますL
。この鋭い角を丸い角に変えるには、左の赤い点から曲線を描き始めます ( を使用M x,y
してその点に移動します)。二次ベジエ曲線には、青い点に設定する必要がある制御点が 1 つだけあります。曲線の終点を右の赤い点に設定します。2 つの赤い点での接線は前の線の方向にあるため、滑らかな遷移、「丸みを帯びた角」が表示されます。
丸みを帯びた角の後の形状を継続するには、2 つの角の間の線上に制御点を設定することで、ベジエ曲線の直線を実現できます。
パスの決定を支援するために、エッジと半径を受け入れるこの 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)