Mam następujący plik 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>
Chcę uzyskać CSS-jak border-top-right-radius
i border-top-bottom-radius
efektu.
Jak mogę uzyskać efekt zaokrąglonego narożnika?
xml
image
svg
vector-graphics
Danis
źródło
źródło
border-radius
i jego warianty nie działają w SVG.rx=3
lubry=3
zaokrąglić rogi. developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rxOdpowiedzi:
Oto jak możesz utworzyć zaokrąglony prostokąt ze ścieżką 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" />
Wyjaśnienie
m100,100: przejdź do punktu (100,100)
h200: narysuj 200px poziomą linię z miejsca, w którym się znajdujemy
a20,20 0 0 1 20,20: narysuj łuk o promieniu 20px X, promieniu 20px Y, zgodnie z ruchem wskazówek zegara, do punktu o 20px różnicy w osiach X i Y
v200: narysuj 200px pionową linię z miejsca, w którym się znajdujemy
a20,20 0 0 1 -20,20: narysuj łuk o promieniu 20px X i Y, zgodnie z ruchem wskazówek zegara, do punktu o -20px różnicy w X i 20px różnicy w osi Y
h-200: narysuj poziomą linię -200px z miejsca, w którym się znajdujemy
a20,20 0 0 1 -20, -20: narysuj łuk o promieniu 20px X i Y, zgodnie z ruchem wskazówek zegara, do punktu z -20px różnicą w X i -20px różnicy w osi Y
v-200: narysuj pionową linię -200px z miejsca, w którym się znajdujemy
a20,20 0 0 1 20, -20: narysuj łuk o promieniu 20px X i Y, zgodnie z ruchem wskazówek zegara, do punktu z różnicą 20px w X i -20px w osi Y
z: zamknij ścieżkę
<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>
źródło
A rx ry x-axis-rotation large-arc-flag sweep-flag x y
( developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths )<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 = "obrys: # 000000; fill: #FFFFFF" /> `</svg>
Nie jestem pewien, dlaczego nikt nie opublikował rzeczywistej odpowiedzi SVG. Oto prostokąt SVG z zaokrąglonymi narożnikami (promień 3) u góry:
<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" />
To jest Ruch do (M), Linia do (L), Łuk do (A), Linia do (L), Łuk do (A), Linia do (L), Zamknij ścieżkę (Z).
Liczby oddzielone przecinkami są współrzędnymi bezwzględnymi. Łuki są definiowane za pomocą dodatkowych parametrów określających promień i typ łuku. Można to również osiągnąć za pomocą współrzędnych względnych (użyj małych liter dla L i A).
Pełne odniesienie do tych poleceń znajduje się na stronie Ścieżki SVG W3C , a dodatkowe materiały referencyjne na temat ścieżek SVG można znaleźć w tym artykule .
źródło
Jak wspomniano w mojej odpowiedzi na temat Stosowanie zaokrąglonych rogów do ścieżek / wielokątów , napisałem procedurę w javascript do ogólnego zaokrąglania rogów ścieżek SVG, z przykładami, tutaj: http://plnkr.co/edit/kGnGGyoOCKil02k04snu .
Będzie działać niezależnie od wszelkich efektów udaru, które możesz mieć. Aby użyć, dołącz plik rounding.js z Plnkr i wywołaj funkcję w ten sposób:
Rezultatem będzie zaokrąglona ścieżka.
Wyniki wyglądają następująco:
źródło
Zostały jawnie ustawić
stroke-linejoin
abyround
ale swojąstroke-width
TO0
, więc oczywiście nie zobaczysz zaokrąglonych rogów, jeśli nie masz skoku do zaokrąglenia.Oto zmodyfikowany przykład z zaokrąglonymi rogami wykonanymi za pomocą pociągnięć:
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" />
W przeciwnym razie - jeśli potrzebujesz rzeczywistego wypełnienia o zaokrąglonym kształcie, a nie tylko zaokrąglonego tłustego obrysu - musisz zrobić to, co mówi @Jlange i zrobić rzeczywisty zaokrąglony kształt.
źródło
stroke-linecap
zamiaststroke-linejoin
. Mi to pasuje.Rozważyłbym również użycie zwykłego starego,
<rect>
który zawiera atrybutyrx
iry
Dokumentacja MDN SVG <- zwróć uwagę na drugi narysowany element prostokątny
źródło
Sam napotkałem ten problem dzisiaj i udało mi się go rozwiązać, pisząc małą funkcję JavaScript.
Z tego, co wiem, nie ma łatwego sposobu na podanie elementu ścieżki w zaokrąglonych rogach SVG, z wyjątkiem sytuacji, gdy potrzebujesz tylko zaokrąglenia granic, w którym to przypadku atrybuty (CSS)
stroke
,stroke-width
a co najważniejszestroke-linejoin="round"
są całkowicie wystarczające.Jednak w moim przypadku użyłem obiektu ścieżki do stworzenia niestandardowych kształtów z n rogami, które są wypełnione określonym kolorem i nie mają widocznych granic, podobnie jak to:
Udało mi się napisać szybką funkcję, która pobiera tablicę współrzędnych dla ścieżki SVG i zwraca gotowy ciąg ścieżki do umieszczenia w
d
atrybucie elementu html ścieżki. Wynikowy kształt będzie wtedy wyglądał mniej więcej tak:Oto funkcja:
/** * 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(' '); }
Możesz określić siłę zaokrąglenia, ustawiając zmienną curveRadius u góry. Domyślną wartością jest 3 dla układu współrzędnych 100x100 (rzutnia), ale w zależności od rozmiaru pliku SVG może być konieczne dostosowanie tego.
źródło
To pytanie jest pierwszym wynikiem wyszukiwania w Google „ścieżki zaokrąglonych rogów svg”. Sugestia Phrogz do użycia
stroke
ma pewne ograniczenia (mianowicie, że nie mogę używać obrysu do innych celów i że wymiary muszą być skorygowane o szerokość obrysu).Sugestia Jlange, aby użyć krzywej, jest lepsza, ale niezbyt konkretna. Skończyło się na użyciu kwadratowych krzywych Béziera do rysowania zaokrąglonych rogów. Rozważ to zdjęcie narożnika oznaczonego niebieską kropką i dwoma czerwonymi punktami na sąsiednich krawędziach:
Dwie linie można utworzyć za pomocą
L
polecenia. Aby zmienić ten ostry narożnik w zaokrąglony, zacznij rysować krzywą od lewego czerwonego punktu (użyj,M x,y
aby przejść do tego punktu). Teraz kwadratowa krzywa Béziera ma tylko jeden punkt kontrolny, który należy ustawić na niebieskim punkcie. Ustaw koniec krzywej w prawym czerwonym punkcie. Ponieważ styczna w dwóch czerwonych punktach jest skierowana w kierunku poprzednich linii, zobaczysz płynne przejście, „zaokrąglone rogi”.Teraz, aby kontynuować kształt za zaokrąglonym rogiem, można uzyskać prostą linię na krzywej Béziera, ustawiając punkt kontrolny między na linii między dwoma rogami.
Aby pomóc mi w określeniu ścieżki, napisałem ten skrypt w Pythonie, który akceptuje krawędzie i promień. Matematyka wektorowa sprawia, że jest to naprawdę bardzo łatwe. Wynikowy obraz z wyjścia:
#!/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)
źródło
Oto kilka ścieżek do kart:
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>
Inne odpowiedzi wyjaśniały mechanikę. Szczególnie podobała mi się odpowiedź hossein-maktoobian.
Najważniejsze są ścieżki w piórze, wartości można modyfikować w celu dostosowania do dowolnych pożądanych wymiarów.
źródło
Znalazłem rozwiązanie, ale jest trochę hakerskie, więc może nie zawsze działać. Odkryłem, że jeśli masz łuk (A lub a) o naprawdę małych wartościach, zmusza to do utworzenia krzywej w jednym miejscu, tworząc w ten sposób zaokrąglony róg ...
<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>
źródło
Aby uprościć implementację odpowiedzi @ hmak.me, oto skomentowany fragment kodu Reacta do generowania zaokrąglonych prostokątów.
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 link.
źródło
Zasadniczo robi to to samo, co odpowiedź Mvinsa , ale jest bardziej skompresowaną i uproszczoną wersją. Działa poprzez cofnięcie odległości promienia linii sąsiadujących z rogiem i połączenie obu końców krzywą Beziera, której punkt kontrolny znajduje się w oryginalnym punkcie narożnym.
function createRoundedPath(coords, radius, close) { let path = "" const length = coords.length + (close ? 1 : -1) for (let i = 0; i < length; i++) { const a = coords[i % coords.length] const b = coords[(i + 1) % coords.length] const t = Math.min(radius / Math.hypot(b.x - a.x, b.y - a.y), 0.5) if (i > 0) path += `Q${a.x},${a.y} ${a.x * (1 - t) + b.x * t},${a.y * (1 - t) + b.y * t}` if (!close && i == 0) path += `M${a.x},${a.y}` else if (i == 0) path += `M${a.x * (1 - t) + b.x * t},${a.y * (1 - t) + b.y * t}` if (!close && i == length - 1) path += `L${b.x},${b.y}` else if (i < length - 1) path += `L${a.x * t + b.x * (1 - t)},${a.y * t + b.y * (1 - t)}` } if (close) path += "Z" return path }
źródło
<?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>'; } ?>
źródło
Używasz elementu ścieżki, dlaczego po prostu nie nadasz ścieżce krzywej? Zobacz tutaj, jak tworzyć krzywe przy użyciu elementów ścieżki: http://www.w3.org/TR/SVG/paths.html#PathDataCurveCommands
źródło