it-swarm.com.de

SVG abgerundete Ecke

Ich habe folgende 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>

Ich möchte einen CSS-ähnlichen border-top-right-radius- und border-top-bottom-radius-Effekt erhalten.

Wie kann ich diesen abgerundeten Eckeneffekt erzielen?

51
Danis

Ich weiß, dass dies zu spät ist, um dies zu beantworten, aber um SO willen, können Sie mit SVG-Pfad ein runderes Rechteck erstellen:

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

Erklärung:

m100,100: zum Punkt (100,100) bewegen

h200: zeichne eine horizontale Linie von 200px von wo wir sind

a20,20 0 0 1 20,20: Zeichne einen Bogen mit 20px X Radius, 20px Y Radius im Uhrzeigersinn bis zu einem Punkt mit 20px Unterschied in der X- und Y-Achse

v200: Zeichne eine 200px vertikale Linie von wo wir sind

a20,20 0 0 1 -20,20: Zeichne einen Bogen mit 20px X- und Y-Radius im Uhrzeigersinn bis zu einem Punkt mit -20px Unterschied in X und 20px Unterschied in Y-Achse

h-200: zeichnet eine horizontale Linie von -200px von wo wir sind

a20,20 0 0 1 -20, -20: Zeichne einen Bogen mit 20px X- und Y-Radius im Uhrzeigersinn auf einen Punkt mit -20px Unterschied in X und -20px Unterschied in Y-Achse

v-200: zeichnet eine vertikale Linie von -200px von wo wir sind

a20,20 0 0 1 20, -20: Zeichne einen Bogen mit 20px X- und Y-Radius im Uhrzeigersinn bis zu einem Punkt mit 20px Unterschied in X und -20px Unterschied in Y-Achse

z: schließe den Pfad

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

70

Nicht sicher, warum niemand eine tatsächliche SVG-Antwort gepostet hat. Hier ist ein SVG-Rechteck mit abgerundeten Ecken (Radius 3) oben:

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

Dies ist eine Verschiebung nach (M), eine Linie nach (L), einen Bogen nach (A), eine Linie nach (L), einen Bogen nach (A), eine Linie nach (L), einen Pfad schließen (Z).

Die durch Kommas getrennten Zahlen sind absolute Koordinaten. Die Bögen werden mit zusätzlichen Parametern definiert, die den Radius und den Typ des Bogens angeben. Dies kann auch mit relativen Koordinaten erreicht werden (verwenden Sie Kleinbuchstaben für L und A).

Die vollständige Referenz für diese Befehle finden Sie auf der Seite W3C SVG Paths . Weitere Referenzmaterialien zu SVG-Pfaden finden Sie in diesem Artikel .

44
vallismortis

Wie in meiner Antwort auf Anwenden abgerundeter Ecken auf Pfade/Polygone verwiesen, habe ich in Javascript eine Routine zum generischen Abrunden von Ecken von SVG-Pfaden geschrieben, mit Beispielen, hier: http://plnkr.co/edit/ kGnGGyoOCKil02k04snu .

Es funktioniert unabhängig von Schlaganfalleffekten. Um zu verwenden, schließen Sie die Datei rounding.js aus dem Plnkr ein und rufen Sie die Funktion wie folgt auf:

roundPathCorners(pathString, radius, useFractionalRadius)

Das Ergebnis ist der abgerundete Pfad.

Die Ergebnisse sehen so aus:

SVG Path Rounding Examples

34
Yona Appletree

Sie haben Ihren stroke-linejoin explizit auf round gesetzt, aber Ihren stroke-width auf 0, also natürlich werden Sie keine abgerundeten Ecken sehen, wenn Sie keinen Rundungsschlag haben.

Hier ein modifiziertes Beispiel mit abgerundeten Ecken durch Striche:
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" />

Ansonsten - wenn Sie eine tatsächliche abgerundete Formfüllung und nicht nur einen abgerundeten Fettstrich benötigen - müssen Sie tun, was @Jlange sagt, und eine tatsächliche abgerundete Form erstellen.

24
Phrogz

Ich würde auch in Betracht ziehen, einen einfachen alten <rect> zu verwenden, der die Attribute rx und ry bereitstellt

MDN SVG docs <- Beachten Sie das zweite gezeichnete Element

18
Joshua

Diese Frage ist das erste Ergebnis für Googling "svg abgerundete Ecken". Der Vorschlag von Phrogz zur Verwendung von stroke hat einige Einschränkungen (nämlich, dass ich den Strich nicht für andere Zwecke verwenden kann und die Bemaßungen für die Strichbreite korrigiert werden müssen).

Ein Vorschlag, eine Kurve zu verwenden, ist zwar besser, aber nicht sehr konkret. Am Ende habe ich quadratische Bézier-Kurven zum Zeichnen von abgerundeten Ecken verwendet. Betrachten Sie dieses Bild einer Ecke, die mit einem blauen Punkt und zwei roten Punkten an den angrenzenden Kanten markiert ist:

corner of a figure marked blue with two points on the adjacent edges

Die beiden Zeilen können mit dem Befehl L erstellt werden. Um aus dieser scharfen Ecke eine abgerundete Ecke zu machen, zeichnen Sie eine Kurve vom linken roten Punkt aus (bewegen Sie sich mit M x,y zu diesem Punkt). Nun hat eine quadratische Bézierkurve nur einen einzigen Kontrollpunkt, den Sie auf den blauen Punkt setzen müssen. Setzen Sie das Ende der Kurve auf den rechten roten Punkt. Da die Tangente an den beiden roten Punkten in der Richtung der vorherigen Linien liegt, wird ein fließender Übergang "abgerundete Ecken" angezeigt.

Um nun die Form nach der abgerundeten Ecke fortzusetzen, kann eine gerade Linie in einer Bézier-Kurve erzielt werden, indem der Kontrollpunkt auf der Linie zwischen den beiden Ecken festgelegt wird.

Um mir bei der Ermittlung des Pfads zu helfen, habe ich dieses Python-Skript geschrieben, das Kanten und einen Radius akzeptiert. Vektormathematik macht dies eigentlich sehr einfach. Das resultierende Bild aus der Ausgabe:

shape created from script output

#!/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)
4
Lekensteyn

Ich bin heute selbst auf dieses Problem gestoßen und habe es mit einer kleinen JavaScript-Funktion gelöst.

Soweit ich das beurteilen kann, gibt es keine einfache Möglichkeit, ein Pfadelement in einer svg abgerundeten Ecken anzugeben mit Ausnahme von, wenn nur die Ränder gerundet werden müssen. In diesem Fall sind die (CSS) -Attribute Strich, Strichbreite und vor allem Strichlinienjoin = "round" sind vollkommen ausreichend.

In meinem Fall habe ich jedoch ein Pfadobjekt verwendet, um benutzerdefinierte Formen mit n Ecken zu erstellen, die mit einer bestimmten Farbe ausgefüllt sind und keine sichtbaren Ränder haben, ähnlich wie hier:

 enter image description here

Es ist mir gelungen, eine schnelle Funktion zu schreiben, die ein Array von Koordinaten für einen svg-Pfad verwendet und die fertige Pfadzeichenfolge zurückgibt, um sie in das d-Attribut des path-html-Elements einzufügen. Die resultierende Form sieht dann ungefähr so ​​aus:

 enter image description here

Hier ist die Funktion:

/**
* 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}, ...]
*/
createRoundedPathString (pathCoords) {
    const path = [];
    const curveRadius = 3;

    // Reset indexes, so there are no gaps
    pathCoords = pathCoords.filter(() => true);

    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],
            c2 = pathCoords[c2Index],
            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(' ');
}

Sie können die Rundungsstärke bestimmen, indem Sie oben die Variable curveRadius einstellen. Der Standardwert ist 3 für ein 100x100 (Viewport) -Koordinatensystem. Abhängig von der Größe Ihrer SVG-Datei müssen Sie dies möglicherweise anpassen.

1
Mvin

Hier sind einige Pfade für Registerkarten:

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>

Die anderen Antworten erklärten die Mechanik. Ich mochte besonders die Antwort von Hossein-Maktoobian.

Die Pfade im Stift übernehmen die Hauptlast der Arbeit, die Werte können geändert werden, um den gewünschten Dimensionen zu entsprechen.

0
Jackie

Ich habe eine Lösung gefunden, aber es ist ein bisschen hacky, so dass es möglicherweise nicht immer funktioniert. Wenn Sie einen Bogen (A oder a) mit sehr kleinen Werten haben, wird er gezwungen, eine Kurve an einer Stelle zu erstellen, wodurch eine abgerundete Ecke entsteht.

<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>
0
Dennis Ranish