xml SVG圆角
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10177985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
SVG rounded corner
提问by Danis
I have the following SVG:
我有以下 SVG:
<g>
<path id="k9ffd8001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="#a0a700"></path>
<path id="kb8000001" d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z" stroke="#808600" stroke-width="0" transform="rotate(0 0 0)" stroke-linecap="square" stroke-linejoin="round" fill-opacity="1" stroke-opacity="1" fill="url(#k9ffb0001)"></path>
</g>
I want to get a CSS-like border-top-right-radiusand border-top-bottom-radiuseffect.
我希望得到一个类似CSSborder-top-right-radius和border-top-bottom-radius效果。
How can I achieve that rounded corner effect?
我怎样才能实现圆角效果?
回答by hmak.me
Here is how you can create a rounded rectangle with SVG Path:
以下是如何使用 SVG 路径创建圆角矩形:
<path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" />
Explanation
解释
m100,100:move to point(100,100)
m100,100:移动到点(100,100)
h200:draw a 200px horizontal line from where we are
h200:从我们所在的位置画一条 200px 的水平线
a20,20 0 0 1 20,20:draw an arc with 20px X radius, 20px Y radius, clockwise, to a point with 20px difference in X and Y axis
a20,20 0 0 1 20,20:画一个 20px X 半径,20px Y 半径的圆弧,顺时针,到 X 和 Y 轴相差 20px 的点
v200:draw a 200px vertical line from where we are
v200:从我们所在的位置画一条 200 像素的垂直线
a20,20 0 0 1 -20,20:draw an arc with 20px X and Y radius, clockwise, to a point with -20px difference in X and 20px difference in Y axis
a20,20 0 0 1 -20,20:顺时针绘制一条 X 和 Y 半径为 20px 的圆弧,到 X 轴相差 -20px 和 Y 轴相差 20px 的点
h-200:draw a -200px horizontal line from where we are
h-200:从我们所在的位置画一条 -200px 的水平线
a20,20 0 0 1 -20,-20:draw an arc with 20px X and Y radius, clockwise, to a point with -20px difference in X and -20px difference in Y axis
a20,20 0 0 1 -20,-20:顺时针绘制一条 X 和 Y 半径为20像素的圆弧,到 X 轴差为 -20 像素,Y 轴差为-20像素的点
v-200:draw a -200px vertical line from where we are
v-200:从我们所在的位置画一条 -200px 的垂直线
a20,20 0 0 1 20,-20:draw an arc with 20px X and Y radius, clockwise, to a point with 20px difference in X and -20px difference in Y axis
a20,20 0 0 1 20,-20:顺时针绘制一条 X 和 Y 半径为 20px 的圆弧,到 X 轴相差 20px 和 Y 轴相差 -20px 的点
z:close the path
z:关闭路径
<svg width="440" height="440">
<path d="M100,100 h200 a20,20 0 0 1 20,20 v200 a20,20 0 0 1 -20,20 h-200 a20,20 0 0 1 -20,-20 v-200 a20,20 0 0 1 20,-20 z" fill="none" stroke="black" stroke-width="3" />
</svg>
回答by vallismortis
Not sure why nobody posted an actual SVG answer. Here is an SVG rectangle with rounded corners (radius 3) on the top:
不知道为什么没有人发布实际的 SVG 答案。这是一个顶部带有圆角(半径 3)的 SVG 矩形:
<svg:path d="M0,0 L0,27 A3,3 0 0,0 3,30 L7,30 A3,3 0 0,0 10,27 L10,0 Z" />
This is a Move To (M), Line To (L), Arc To (A), Line To (L), Arc To (A), Line To (L), Close Path (Z).
这是移动到 (M)、线到 (L)、弧到 (A)、线到 (L)、弧到 (A)、线到 (L)、闭合路径 (Z)。
The comma-delimited numbers are absolute coordinates. The arcs are defined with additional parameters specifying the radius and type of arc. This could also be accomplished with relative coordinates (use lower-case letters for L and A).
逗号分隔的数字是绝对坐标。圆弧是用指定圆弧半径和类型的附加参数定义的。这也可以通过相对坐标来完成(L 和 A 使用小写字母)。
The complete reference for those commands is on the W3C SVG Pathspage, and additional reference material on SVG paths can be found in this article.
回答by Yona Appletree
As referenced in my answer to Applying rounded corners to paths/polygons, I have written a routine in javascript for generically rounding corners of SVG paths, with examples, here: http://plnkr.co/edit/kGnGGyoOCKil02k04snu.
正如我在对路径/多边形应用圆角的回答中提到的那样,我在 javascript 中编写了一个例程,用于对 SVG 路径的一般圆角,并在此处提供示例:http: //plnkr.co/edit/kGnGGyoOCKil02k04snu。
It will work independently from any stroke effects you may have. To use, include the rounding.js file from the Plnkr and call the function like so:
它将独立于您可能具有的任何中风效果而工作。要使用,请包含 Plnkr 中的 rounding.js 文件并像这样调用函数:
roundPathCorners(pathString, radius, useFractionalRadius)
The result will be the rounded path.
结果将是圆形路径。
The results look like this:
结果如下所示:


回答by Phrogz
You have explicitly set your stroke-linejointo roundbut your stroke-widthto 0, so of courseyou're not going to see rounded corners if you have no stroke to round.
你已经明确地设置了你的stroke-linejointoround但你的stroke-widthto 0,所以如果你没有要圆的笔划,你当然不会看到圆角。
Here's a modified example with rounded corners made through strokes:
http://jsfiddle.net/8uxqK/1/
这是一个通过笔画制作圆角的修改示例:http:
//jsfiddle.net/8uxqK/1/
<path d="M64.5 45.5 82.5 45.5 82.5 64.5 64.5 64.5 z"
stroke-width="5"
stroke-linejoin="round"
stroke="#808600"
fill="#a0a700" />
Otherwise—if you need an actual rounded shape fill and not just a rounded fatty stroke—you must do what @Jlange says and make an actual rounded shape.
否则——如果你需要一个实际的圆形填充,而不仅仅是一个圆形的脂肪笔触——你必须按照@Jlange 所说的做一个实际的圆形。
回答by Joshua
I'd also consider using a plain old <rect>which provides the rxand ryattributes
我也会考虑使用一个普通的旧的<rect>,它提供了rx和ry属性
MDN SVG docs<- note the second drawn rect element
MDN SVG 文档<- 注意第二个绘制的 rect 元素
回答by Mvin
I've happened upon this problem today myself and managed to solve it by writing a small JavaScript function.
我今天自己遇到了这个问题,并通过编写一个小的 JavaScript 函数设法解决了它。
From what I can tell, there is no easy way to give a path element in an SVG rounded corners exceptif you only need the borders to be rounded, in which case the (CSS) attributes stroke, stroke-widthand most importantly stroke-linejoin="round"are perfectly sufficient.
据我所知,没有简单的方法可以在 SVG 圆角中提供路径元素,除非您只需要圆角边框,在这种情况下(CSS)属性stroke,stroke-width最重要的stroke-linejoin="round"是完全足够。
However, in my case I used a path object to create custom shapes with ncorners that are filled out with a certain color and don't have visible borders, much like this:
但是,在我的例子中,我使用了一个路径对象来创建带有n 个角的自定义形状,这些角用某种颜色填充并且没有可见的边框,就像这样:
I managed to write a quick function that takes an array of coordinates for an SVG path and returns the finished path string to put in the dattribute of the path html element. The resulting shape will then look something like this:
我设法编写了一个快速函数,该函数接受 SVG 路径的坐标数组,并返回完成的路径字符串以放入d路径 html 元素的属性中。生成的形状将如下所示:
Here is the function:
这是函数:
/**
* Creates a coordinate path for the Path SVG element with rounded corners
* @param pathCoords - An array of coordinates in the form [{x: Number, y: Number}, ...]
*/
function createRoundedPathString(pathCoords) {
const path = [];
const curveRadius = 3;
// Reset indexes, so there are no gaps
pathCoords = pathCoords.slice();
for (let i = 0; i < pathCoords.length; i++) {
// 1. Get current coord and the next two (startpoint, cornerpoint, endpoint) to calculate rounded curve
const c2Index = ((i + 1) > pathCoords.length - 1) ? (i + 1) % pathCoords.length : i + 1;
const c3Index = ((i + 2) > pathCoords.length - 1) ? (i + 2) % pathCoords.length : i + 2;
const c1 = pathCoords[i];
const c2 = pathCoords[c2Index],
const c3 = pathCoords[c3Index];
// 2. For each 3 coords, enter two new path commands: Line to start of curve, bezier curve around corner.
// Calculate curvePoint c1 -> c2
const c1c2Distance = Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
const c1c2DistanceRatio = (c1c2Distance - curveRadius) / c1c2Distance;
const c1c2CurvePoint = [
((1 - c1c2DistanceRatio) * c1.x + c1c2DistanceRatio * c2.x).toFixed(1),
((1 - c1c2DistanceRatio) * c1.y + c1c2DistanceRatio * c2.y).toFixed(1)
];
// Calculate curvePoint c2 -> c3
const c2c3Distance = Math.sqrt(Math.pow(c2.x - c3.x, 2) + Math.pow(c2.y - c3.y, 2));
const c2c3DistanceRatio = curveRadius / c2c3Distance;
const c2c3CurvePoint = [
((1 - c2c3DistanceRatio) * c2.x + c2c3DistanceRatio * c3.x).toFixed(1),
((1 - c2c3DistanceRatio) * c2.y + c2c3DistanceRatio * c3.y).toFixed(1)
];
// If at last coord of polygon, also save that as starting point
if (i === pathCoords.length - 1) {
path.unshift('M' + c2c3CurvePoint.join(','));
}
// Line to start of curve (L endcoord)
path.push('L' + c1c2CurvePoint.join(','));
// Bezier line around curve (Q controlcoord endcoord)
path.push('Q' + c2.x + ',' + c2.y + ',' + c2c3CurvePoint.join(','));
}
// Logically connect path to starting point again (shouldn't be necessary as path ends there anyway, but seems cleaner)
path.push('Z');
return path.join(' ');
}
You can determine the rounding strength by setting the curveRadiusvariable at the top. The default is 3 for a 100x100 (viewport) coordinate system, but depending on the size of your SVG, you may need to adjust this.
您可以通过设置顶部的curveRadius变量来确定舍入强度。100x100(视口)坐标系的默认值为 3,但根据 SVG 的大小,您可能需要调整此值。
回答by Lekensteyn
This question is the first result for Googling "svg rounded corners path". Phrogz suggestion to use strokehas some limitations (namely, that I cannot use stroke for other purposes, and that the dimensions have to be corrected for the stroke width).
这个问题是谷歌搜索“svg圆角路径”的第一个结果。Phrogz 建议使用stroke有一些限制(即,我不能将笔画用于其他目的,并且必须针对笔画宽度校正尺寸)。
Jlange suggestion to use a curve is better, but not very concrete. I ended up using quadratic Bézier curves for drawing rounded corners. Consider this picture of a corner marked with a blue dot and two red points on adjacent edges:
Jlange 建议使用曲线更好,但不是很具体。我最终使用二次贝塞尔曲线来绘制圆角。考虑这张用蓝点和相邻边缘上的两个红点标记的角的图片:


The two lines could be made with the Lcommand. To turn this sharp corner into a rounded corner, start drawing a curve from the left red point (use M x,yto move to that point). Now a quadratic Bézier curve has just a single control point which you must set on the blue point. Set the end of the curve at the right red point. As the tangent at the two red points are in the direction of the previous lines, you will see a fluent transition, "rounded corners".
这两行可以用L命令制作。要将这个尖角变成圆角,请从左侧红点开始绘制曲线(用于M x,y移动到该点)。现在,二次贝塞尔曲线只有一个控制点,您必须将其设置在蓝点上。将曲线的末端设置在右侧的红点处。由于两个红点处的切线在前几条线的方向上,您将看到一个流畅的过渡,即“圆角”。
Now to continue the shape after the rounded corner, a straight line in a Bézier curve can be achieved by setting the control point between on the line between the two corners.
现在继续圆角后的形状,可以通过在两个角之间的线上设置控制点来实现贝塞尔曲线中的一条直线。
To help me with determining the path, I wrote this Python script that accepts edges and a radius. Vector math makes this actually very easy. The resulting image from the output:
为了帮助我确定路径,我编写了这个接受边和半径的 Python 脚本。矢量数学使这实际上非常容易。输出的结果图像:


#!/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)
回答by Hymanie
Here are some paths for tabs:
以下是选项卡的一些路径:
https://codepen.io/mochime/pen/VxxzMW
https://codepen.io/mochime/pen/VxxzMW
<!-- left tab -->
<div>
<svg width="60" height="60">
<path d="M10,10
a10 10 0 0 1 10 -10
h 50
v 47
h -50
a10 10 0 0 1 -10 -10
z"
fill="#ff3600"></path>
</svg>
</div>
<!-- right tab -->
<div>
<svg width="60" height="60">
<path d="M10 0
h 40
a10 10 0 0 1 10 10
v 27
a10 10 0 0 1 -10 10
h -40
z"
fill="#ff3600"></path>
</svg>
</div>
<!-- tab tab :) -->
<div>
<svg width="60" height="60">
<path d="M10,40
v -30
a10 10 0 0 1 10 -10
h 30
a10 10 0 0 1 10 10
v 30
z"
fill="#ff3600"></path>
</svg>
</div>
The other answers explained the mechanics. I especially liked hossein-maktoobian's answer.
其他答案解释了机制。我特别喜欢 hossein-maktoobian 的回答。
The paths in the pen do the brunt of the work, the values can be modified to suite whatever desired dimensions.
笔中的路径首当其冲,可以修改值以适应任何所需的尺寸。
回答by Dennis Ranish
I found a solution but it is a bit hackyso it may not always work. I found that if you have an arc (A or a) with really small values it forces it to create a curve in one spot thus forming a rounded comer...
我找到了一个解决方案,但它有点笨拙,所以它可能并不总是有效。我发现如果你有一个值非常小的弧(A 或 a),它会迫使它在一个点上创建一条曲线,从而形成一个圆角......
<svg viewBox="0 0 1 0.6" stroke="black" fill="grey" style="stroke-width:0.05px;">
<path d="M0.7 0.2 L0.1 0.1 A0.0001 0.0001 0 0 0 0.099 0.101 L0.5 0.5Z"></path>
</svg>
回答by polkovnikov.ph
Just to simplify implementing answer of @hmak.me, here's a commented piece of React code to generate rounded rectangles.
只是为了简化@hmak.me 的实现答案,这里有一段注释过的 React 代码来生成圆角矩形。
const Rect = ({width, height, round, strokeWidth}) => {
// overhang over given width and height that we get due to stroke width
const s = strokeWidth / 2;
// how many pixels do we need to cut from vertical and horizontal parts
// due to rounded corners and stroke width
const over = 2 * round + strokeWidth;
// lengths of straight lines
const w = width - over;
const h = height - over;
// beware that extra spaces will not be minified
// they are added for clarity
const d = `
M${round + s},${s}
h${w}
a${round},${round} 0 0 1 ${round},${round}
v${h}
a${round},${round} 0 0 1 -${round},${round}
h-${w}
a${round},${round} 0 0 1 -${round},-${round}
v-${h}
a${round},${round} 0 0 1 ${round},-${round}
z
`;
return (
<svg width={width} height={height}>
<path d={d} fill="none" stroke="black" strokeWidth={strokeWidth} />
</svg>
);
};
ReactDOM.render(
<Rect width={64} height={32} strokeWidth={2} round={4} />,
document.querySelector('#app'),
);

