Câu hỏi này là kết quả đầu tiên cho "con đường góc tròn svg" của Googling. Đề xuất của Phrogz để sử dụng stroke
có một số hạn chế (cụ thể là, tôi không thể sử dụng đột quỵ cho các mục đích khác và kích thước phải được sửa cho chiều rộng nét).
Đề xuất của Jlange để sử dụng đường cong tốt hơn, nhưng không cụ thể lắm. Tôi đã kết thúc bằng cách sử dụng đường cong Bézier bậc hai để vẽ các góc tròn. Xem xét bức tranh này của một góc được đánh dấu bằng một dấu chấm màu xanh và hai điểm đỏ trên các cạnh liền kề:
Hai dòng có thể được thực hiện với lệnh L
. Để biến góc nhọn này thành một góc tròn, bắt đầu vẽ một đường cong từ điểm đỏ bên trái (sử dụng M x,y
để di chuyển đến điểm đó). Bây giờ đường cong Bézier bậc hai chỉ là một điểm điều khiển duy nhất mà bạn phải đặt trên điểm màu xanh. Đặt đầu của đường cong tại điểm màu đỏ bên phải. Khi ốp tại hai điểm màu đỏ là theo hướng của các dòng trước đó, bạn sẽ thấy một chuyển đổi trôi chảy, "góc tròn".
Bây giờ để tiếp tục hình dạng sau góc tròn, một đường thẳng trong đường cong Bézier có thể đạt được bằng cách đặt điểm điều khiển giữa trên đường giữa hai góc.
Để giúp tôi xác định đường dẫn, tôi đã viết tập lệnh Python này chấp nhận các cạnh và bán kính. Vector toán học làm cho điều này thực sự rất dễ dàng.Hình ảnh thu được từ kết quả:
#!/usr/bin/env python
# Given some vectors and a border-radius, output a SVG path with rounded
# corners.
#
# Copyright (C) Peter Wu <[email protected]>
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)
Thật tệ khi CSS ''border-radius' và các biến thể của nó không hoạt động trong SVG. –