SVG圆角

Dan*_*nis 57 xml svg image vector-graphics

我有以下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>
Run Code Online (Sandbox Code Playgroud)

我希望得到一个类似CSS border-top-right-radiusborder-top-bottom-radius效果.

如何实现圆角效果呢?

hma*_*.me 93

我知道回答这个问题的时间已经很晚了,但是为了这个,你可以用SVG Path创建一个更圆的矩形:

<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" />
Run Code Online (Sandbox Code Playgroud)

说明:

m100,100: 移动到点(100,100)

h200: 从我们所在的地方画一条200px的水平线

a20,20 0 0 1 20,20: 绘制一个半径为20px,半径为20px,顺时针方向的弧,到X轴和Y轴相差20px的点

v200: 从我们所在的地方画一条200px的垂直线

a20,20 0 0 1 -20,20: 以20px X和Y半径顺时针绘制一个圆弧,在X轴上有20px的差异,在Y轴上有20px的差异

h-200: 从我们所在的地方画一条-200px的水平线

a20,20 0 0 1 -20,-20: 顺时针绘制一个20px X和Y半径的圆弧,到X轴差为-20px,Y轴差为-20px的点

v-200: 从我们所在的地方画一条-200px的垂直线

a20,20 0 0 1 20,-20: 顺时针绘制一个20px X和Y半径的圆弧,到X轴差为20px,Y轴偏差为-20px的点

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>
Run Code Online (Sandbox Code Playgroud)

  • 如果您只想要一个圆角矩形而不是更复杂的形状(这就是我在谷歌搜索时发现的),更简单的方法可能是使用 `&lt;svg viewBox="0 0 110 110" xmlns="http://www .w3.org/2000/svg"&gt;` ` &lt;rect x="5" y="5" width="100" height="100" rx="15" style="lines:#000000; fill: # FFFFFF"/&gt;` `&lt;/svg&gt;` (8认同)
  • 对于任何对弧的更多细节感兴趣的人,这是 API:`A rx ry x-axis-rotation large-arc-flag swing-flag xy` (https://developer.mozilla.org/en-US/文档/Web/SVG/教程/路径) (6认同)

val*_*tis 48

不知道为什么没有人发布实际的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" />
Run Code Online (Sandbox Code Playgroud)

这是移动到(M),线到(L),弧到(A),线到(L),弧到(A),线到(L),关闭路径(Z).

逗号分隔的数字是绝对坐标.弧是使用指定弧的半径和类型的附加参数定义的.这也可以用相对坐标来完成(使用L和A的小写字母).

这些命令的完整参考位于W3C SVG路径页面上,本文中可以找到有关SVG路径的其他参考资料.

  • 这不是我正在寻找的答案,但如果它没用,那就是好神.总是想知道这些字母的用途. (10认同)
  • 请注意,使用相对坐标会更好,并使用专用的“h”和“l”指令来表示水平/垂直直线:“m0,0 v27 a3,3 0 00 3,3 h4 a3,3 0 00 3, -3 v-27 z`。 (4认同)

Yon*_*ree 42

正如我在将圆角应用于路径/多边形的回答中所提到的,我已经在javascript中编写了一个例程,用于一般舍入SVG路径的角落,例如:http://plnkr.co/edit/kGnGGyoOCKil02k04snu.

它可以独立于您可能具有的任何笔触效果.要使用,请包含Plnkr中的rounding.js文件并像这样调用函数:

roundPathCorners(pathString, radius, useFractionalRadius)
Run Code Online (Sandbox Code Playgroud)

结果将是圆形路径.

结果如下所示:

SVG路径舍入示例


Phr*_*ogz 28

你明确地设置了你的stroke-linejoin,round但是你stroke-width0,所以当然你不会看到圆角,如果你没有中风.

这是一个修改过的例子,通过笔划制作圆角: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" />
Run Code Online (Sandbox Code Playgroud)

否则 - 如果你需要一个实际的圆形填充而不仅仅是圆润的脂肪笔划 - 你必须做@Jlange所说的并做一个实际的圆形.

  • 你可以使用`stroke-linecap`而不是`stroke-linejoin`.这个对我有用. (5认同)
  • 我在 jsfiddle 上正确地看到了这一点,但是当复制到本地 HTML 文档时,它只是一个普通的矩形。 (2认同)

Jos*_*hua 24

我还考虑使用<rect>提供rxry属性的普通旧

MDN SVG docs < - 注意第二个绘制的rect元素

  • 这回答了我的问题,这就是我带到这个页面的原因.那谢谢啦! (5认同)
  • 但OP只希望将一些角落四舍五入. (2认同)

Mvi*_*vin 16

我今天自己遇到了这个问题,并通过编写一个小的 JavaScript 函数设法解决了它。

据我所知,没有简单的方法可以在 SVG 圆角中提供路径元素,除非您只需要将边框圆角,在这种情况下(CSS)属性strokestroke-width最重要的stroke-linejoin="round"是完全足够。

然而,在我的例子中,我使用了一个路径对象来创建带有n 个角的自定义形状,这些角用某种颜色填充并且没有可见的边框,就像这样:

在此处输入图片说明

我设法编写了一个快速函数,该函数接受 SVG 路径的坐标数组,并返回完成的路径字符串以放入d路径 html 元素的属性中。生成的形状将如下所示:

在此处输入图片说明

这是函数:

/**
 * 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(' ');
}
Run Code Online (Sandbox Code Playgroud)

您可以通过设置顶部的curveRadius变量来确定舍入强度。100x100(视口)坐标系的默认值为 3,但根据 SVG 的大小,您可能需要调整此值。


Ame*_*icA 13

对于我的情况,我需要半径开始和结束path

在此输入图像描述

我将stroke-linecap: round;其更改为我想要的:

在此输入图像描述


Lek*_*eyn 5

这个问题是谷歌搜索“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)
Run Code Online (Sandbox Code Playgroud)


Jla*_*nge -4

您正在使用路径元素,为什么不直接给路径一条曲线呢?请参阅此处,了解如何使用路径元素制作曲线:http://www.w3.org/TR/SVG/paths.html#PathDataCurveCommands