SVGの丸い角


83

私は次の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>
</svg>

私は、CSSのような取得したいborder-top-right-radiusborder-top-bottom-radius効果を。

どうすればその丸みを帯びたコーナー効果を実現できますか?


CSSborder-radiusとそのバリアントがSVGで機能しないのは残念です。
Steven Vachon 2015年

7
ところで。長方形がある場合は、角を追加rx=3またはry=3丸めることができます。developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx
Lukas Liesis 2018年

回答:


125

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" />

説明

m100,100: ポイントに移動(100,100)

h200: 現在の場所から200pxの水平線を描画します

a20,20 0 0 1 20,20: X軸とY軸の差が20pxの点に、X半径20px、Y半径20pxの円弧を時計回りに描画します。

v200: 現在の場所から200pxの垂直線を描画します

a20,20 0 0 1 -20,20: XとYの半径が20pxの円弧を時計回りに、Xの差が-20px、Yの軸の差が20pxの点に描画します。

h-200: 現在の場所から-200pxの水平線を描画します

a20,20 0 0 1 -20、-20: XとYの半径が20pxの円弧を時計回りに、Xの差が-20px、Yの軸の差が-20pxの点に描画します。

v-200: 現在の場所から-200pxの垂直線を描画します

a20,20 0 0 1 20、-20: XとYの半径が20pxの円弧を時計回りに、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>


3
アークの詳細に興味がある人のために、これはAPIです:A rx ry x-axis-rotation large-arc-flag sweep-flag x ydeveloper.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths
Nic Sc​​ozzaro

より複雑な形状ではなく、丸みを帯びた長方形が必要な場合(これは、グーグルでこれを見つけた方法です)、より簡単なアプローチは、 <svg viewBox="0 0 110 110" xmlns="http://www.w3.org/2000/svg"> `<rect x =" 5 "y =" 5 "width =" 100 "heightを使用することです。 = "100" rx = "15" style = "stroke:#000000; fill:#FFFFFF" /> `</svg>
John Sibly

58

なぜ誰も実際の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" />

これは、Move To(M)、Line To(L)、Arc To(A)、Line To(L)、Arc To(A)、Line To(L)、Close Path(Z)です。

カンマ区切りの数値は絶対座標です。円弧は、円弧の半径とタイプを指定する追加のパラメータで定義されます。これは、相対座標を使用して実行することもできます(LとAには小文字を使用します)。

これらのコマンドの完全なリファレンスはW3CSVGパスのページにあり、SVGパスに関する追加のリファレンス資料はこの記事にあります。


12
これは私が探していた直接の答えではありませんが、それが役に立たないのであれば良い神です。その手紙は何のためにあるのかといつも思っていました。
Alex McCabe 2016年


47

私の答えで参照されているように パス/ポリゴンへの丸みを帯びた角の適用へのいるように、SVGパスの角を一般的に丸くするためのルーチンをjavascriptで記述しました。例は、http//plnkr.co/edit/kGnGGyoOCKil02k04snuです。

それはあなたが持っているかもしれないどんなストローク効果からも独立して働きます。使用するには、Plnkrからrounding.jsファイルを含め、次のように関数を呼び出します。

roundPathCorners(pathString, radius, useFractionalRadius)

結果は丸みを帯びたパスになります。

結果は次のようになります。

SVGパス丸めの例


相対コマンドのサポートはさらに良いでしょうが、素晴らしいです。
Joachim Breitner 2015

1
私は同意します:)これは私の問題を解決するためのほんの少しの一時的なものであり、本格的な図書館での試みではありませんでした。その機能を備えたフォークを歓迎します!
ヨナアップルツリー2015年

これを含むレポはありますか?それを作ってくれてありがとう。
djave 2018

1
私はそれのためにレポを作ることを決して気にしませんでした...私はおそらくそうするべきですが。
ヨナアップルツリー2018

リポジトリに関する
@Djave

36

あなたは明示的に設定されているstroke-linejoinroundが、あなたstroke-widthには0そう、もちろん、あなたが丸めるストロークがないならあなたは丸い角を見ることはありません。

これは、ストロークによって作成された丸い角を持つ変更された例です: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" />

それ以外の場合、丸みを帯びた太いストロークだけでなく、実際の丸みを帯びた形状の塗りつぶしが必要な場合は、@ Jlangeの言うことを実行して、実際の丸みを帯びた形状を作成する必要があります。


これはjsfiddleで正しく表示されますが、ローカルのHTMLドキュメントにコピーすると、単なる長方形になります。
Mads Skjern 2015

6
stroke-linecap代わりに使用できますstroke-linejoin。わたしにはできる。
lobodart 2015年

32

と属性<rect>を提供するプレーンオールドの使用も検討しますrxry

MDN SVG docs <-2番目に描画されたrect要素に注意してください


2
しかし、OPは、一部のコーナーのみを丸めることを望んでいます。
ロバートロングソン2014

9
これは私の質問に答えます。それが私をこのページに導いた理由です。ほんとありがと!
Steven Vachon 2015年

1
長方形だけでなく、要素のいくつかのグループに丸みを帯びた角を使用する必要がある場合は、ここに表示れているように、clipPathdeveloper.mozilla.org / pt-BR / docs / Web / SVG / Element / clipPathを使用してそれを行うことができます。jsfiddle.net/thiagomata/mp28rnj6/1
Thiago Mata

OPのデッドリンク。:(
posfan12 2016

@ posfan12あなたのためにそれを修正しました:)
Joshua

12

私は今日この問題に自分で遭遇し、小さなJavaScript関数を書くことでそれを解決することができました。

私の知る限り、SVGの丸みを帯びた角にパス要素を指定する簡単な方法はありません。ただし、境界線を丸くする必要がある場合を除きます。この場合、(CSS)属性strokestroke-widthそして最も重要なのはstroke-linejoin="round"完全に十分です。

ただし、私の場合は、パスオブジェクトを使用して、次のように、特定の色で塗りつぶされ、境界線が表示されないn個のコーナーを持つカスタムシェイプを作成しました。

ここに画像の説明を入力してください

SVGパスの座標の配列を受け取り、完成したパス文字列を返してdpathhtml要素の属性に入れるクイック関数を作成することができました。結果の形状は次のようになります。

ここに画像の説明を入力してください

関数は次のとおりです。

/**
 * 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(' ');
}

上部のcurveRadius変数を設定することにより、丸めの強さを決定できます。100x100(ビューポート)座標系のデフォルトは3ですが、SVGのサイズによっては、これを調整する必要がある場合があります。


1
この数学は素晴らしいです。私はそれを理解し、ポリゴンに丸い角を持たせるためにAndroidに実装しました。
Adil Soomro

1
これが私がStackOverflowを愛する理由です。
バンコク

5

この質問は、グーグルの「svg丸めコーナーパス」の最初の結果です。使用するPhrogzの提案にstrokeは、いくつかの制限があります(つまり、ストロークを他の目的に使用できないこと、およびストロークの幅に合わせて寸法を修正する必要があること)。

曲線を使用するというJlangeの提案の方が優れていますが、あまり具体的ではありません。丸い角を描くために二次ベジェ曲線を使用することになりました。青い点と隣接するエッジ上の2つの赤い点でマークされたコーナーのこの写真を考えてみましょう。

隣接するエッジに2つのポイントがある青でマークされた図のコーナー

このLコマンドで2行を作成できます。この鋭い角を丸い角に変えるには、左の赤い点から曲線を描き始めます(M x,yその点に移動するために使用します)。これで、2次ベジエ曲線には、青い点に設定する必要のある制御点が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)

3

タブのパスは次のとおりです。

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>

他の答えは力学を説明しました。私は特にhossein-maktoobianの答えが好きでした。

ペンのパスは作業の矢面に立たされ、値は必要な寸法に合わせて変更できます。


1

私は解決策を見つけましたが、それは少しハッキーなので、常にうまくいくとは限りません。値が非常に小さい円弧(Aまたはa)があると、1つのスポットに曲線が作成され、丸みを帯びた角が形成されることがわかりました。

<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>


1

@ 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'),
);

Jsfiddleリンク。


-2
<?php
$radius = 20;
$thichness = 4;
$size = 200;

if($s == 'circle'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<circle cx="' . ($size/2) . '" cy="' . ($size/2) . '" r="' . (($size/2)-$thichness) . '" stroke="black" stroke-width="' . $thichness . '" fill="none" />';
  echo '</svg>';
}elseif($s == 'square'){
  echo '<svg width="' . $size . '" height="' . $size . '">';
  echo '<path d="M' . ($radius+$thichness) . ',' . ($thichness) . ' h' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',' . $radius . ' v' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',' . $radius . ' h-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 -' . $radius . ',-' . $radius . ' v-' . ($size-($radius*2)-($thichness*2)) . ' a' . $radius . ',' . $radius . ' 0 0 1 ' . $radius . ',-' . $radius . ' z" fill="none" stroke="black" stroke-width="' . $thichness . '" />';
  echo '</svg>';
}
?>

-5

パス要素を使用しているのですが、パスにカーブを付けてみませんか?パス要素を使用して曲線を作成する方法については、http//www.w3.org/TR/SVG/paths.html#PathDataCurveCommandsを参照してください。


あなたの答えをありがとう。それらは本当に役に立ちますが、問題はKendoUIチャートを使用していて、パスが動的に作成されていることです。Phrogzを提供する方法でそれらを変更しようとしましたが、border-radius = 10pxの効果が得られますが、border-top-が必要です。 left-radius = 10pxおよびborder-bottom-left-radius = 10pxのみ。私はSVGが本当に新しいので、2番目の方法は私には向いていません。それで、私のためにパスコーディネーターを書いてくれませんか。よろしく
お願いします

私はあなたのためにこれをしたいのですが、私は単に数学/座標の場所を通過する時間がありません。リンクで楕円弧コマンドを使用する場合は、それほど難しくはありません。
RestingRobot 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.