Obecnie budujemy aplikację SVG opartą na przeglądarce. W tej aplikacji użytkownik może stylizować i ustawiać różne kształty, w tym prostokąty.
Kiedy zastosuję a stroke-width
do rect
powiedzmy elementu SVG 1px
, obrys jest stosowany rect
w różny sposób do przesunięcia i wstawki przez różne przeglądarki. Jest to kłopotliwe, zwłaszcza gdy próbuję obliczyć zewnętrzną szerokość i wizualną pozycję prostokąta i ustawić go obok innych elementów.
Na przykład:
- Firefox dodaje wstawkę 1px (dolny i lewy) oraz przesunięcie 1px (górny i prawy)
- Chrome dodaje wstawkę 1px (u góry i po lewej) i przesunięcie 1px (u dołu i po prawej)
Moim jedynym rozwiązaniem do tej pory było narysowanie rzeczywistych granic (prawdopodobnie za pomocą path
narzędzia) i umieszczenie granic za obrysowanym elementem. Ale to rozwiązanie jest nieprzyjemnym obejściem i wolałbym nie iść tą drogą, jeśli to możliwe.
Moje pytanie brzmi: czy możesz kontrolować sposób stroke-width
rysowania pliku SVG na elementach?
paint-order
parametr, w którym można określić, że wypełnienie powinno być renderowane na szczycie obrysu, aby uzyskać „wyrównanie zewnętrzne”, patrz jsfiddle.net/hne0kyLg/1Odpowiedzi:
Nie, nie można określić, czy obrys ma być rysowany wewnątrz czy na zewnątrz elementu. Złożyłem propozycję grupie roboczej SVG dotyczącą tej funkcji w 2003 r., Ale nie otrzymała ona żadnego wsparcia (ani dyskusji).
Jak zauważyłem we wniosku,
Edycja : Ta odpowiedź może być błędna w przyszłości. Osiągnięcie tych wyników powinno być możliwe przy użyciu SVG Effects Vector , poprzez połączenie
veStrokePath
zveIntersect
(dla „wewnątrz”) lub zveExclude
(dla „na zewnątrz). Jednak Vector Effects są nadal działającym modułem roboczym, bez żadnych implementacji, które mogę jeszcze znaleźć.Edycja 2 : Specyfikacja szkicu SVG 2 zawiera
stroke-alignment
właściwość (ze środkiem | wewnątrz | poza możliwymi wartościami). Ta właściwość może ostatecznie przekształcić się w UA.Edycja 3 : Amusingly i dissapointingly grupa robocza SVG usunęła
stroke-alignment
z SVG 2. Można zobaczyć niektóre z problemów opisanych po prozę tutaj .źródło
UPDATE:
stroke-alignment
atrybut był w dniu 1 kwietnia 2015 roku przeniósł się do zupełnie nowej specyfikacji zwanej Strokes SVG .Od wersji redakcyjnej SVG 2.0 z 26 lutego 2015 r. (I być może od 13 lutego ),
z wartościamistroke-alignment
nieruchomość jest obecnyinner
,center
(domyślnie) iouter
.Wygląda na to, że działa w taki sam sposób, jak
stroke-location
właściwość zaproponowana przez @Phrogz i późniejsząstroke-position
sugestię . Ta nieruchomość została zaplanowana co najmniej od 2011 r., Ale oprócz wspomnianej adnotacji, nigdy nie został szczegółowo opisany, ponieważ został odroczony - wydaje się, że do tej pory.
Żadna przeglądarka nie obsługuje tej właściwości ani, o ile mi wiadomo, żadnej z nowych funkcji SVG 2, ale mam nadzieję, że wkrótce będą dostępne. To była własność, o którą osobiście namawiałem i bardzo się cieszę, że w końcu jest w specyfikacji.
Wydaje się, że istnieją pewne problemy dotyczące zachowania właściwości na otwartych ścieżkach i pętlach. Problemy te najprawdopodobniej przedłużą wdrożenia w różnych przeglądarkach. Jednak zaktualizuję tę odpowiedź o nowe informacje, gdy przeglądarki zaczną obsługiwać tę właściwość.
źródło
stroke-alignment
jest określony w SVG Strokes, roboczym szkicu W3C. Tymczasem wersja robocza edytora W3C SVG 2 mówi, że właściwość pozycjonowania obrysu powinna znajdować się w specyfikacji SVG na svgwg.org/svg2-draft/painting.html#SpecifyingStrokePaint , ale ta specyfikacja już osiągnęła status Rekomendacji kandydata W3C i żadna taka właściwość nie jest w specyfikacji oprócz linku dostroke-position
wniosku, co wydaje się, że tak nie będzie.Znalazłem prosty sposób, który ma kilka ograniczeń, ale działał dla mnie:
Oto działający przykład:
źródło
<use>
? Dlaczego nie wstawić bezpośrednio ścieżki i ścieżki przycinania? Działa to dobrze:<svg width="240" height="240" viewBox="0 0 1024 1024"> <path id="ld" d="M256,0 L0,512 L384,512 L128,1024 L1024,384 L640,384 L896,0 L256,0 Z" clip-path="url(#clip)" stroke="#0081C6" stroke-width="160" fill="#00d2b8"/> <clipPath id="clip"> <use xlink:href="#ld"/> </clipPath> </svg>
. (Tak, jest to całkowicie uzasadnione i poprawne SVG i będzie renderowane poprawnie wszędzie. Nie obawiaj się rekurencji.)Możesz użyć CSS do stylizacji kolejności obrysu i wypełnień. Oznacza to, że najpierw pociągnij, a następnie wypełnij drugi i uzyskaj pożądany efekt.
MDN na
paint-order
: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/paint-orderKod CSS:
źródło
Oto funkcja, która obliczy, ile pikseli należy dodać - przy użyciu danego obrysu - do góry, z prawej, u dołu i z lewej strony, wszystkie na podstawie przeglądarki:
źródło
Jak zauważyli ludzie powyżej, albo będziesz musiał ponownie obliczyć przesunięcie współrzędnych ścieżki obrysu lub podwoić jego szerokość, a następnie zamaskować jedną lub drugą stronę, ponieważ SVG nie tylko natywnie nie obsługuje wyrównania obrysu programu Illustrator, ale PostScript również nie .
Specyfikacja uderzeń w PostScript ręcznych stanach Wydanie 2nd Adobe: " 4.5.1 Głaskanie: udar operator rysuje linię pewnej grubości wzdłuż toru prądowego Dla każdego segmentu prostym lub zakrzywionym w ścieżce. Udar rysuje linię, który jest skoncentrowany na segment z bokami równoległymi do segmentu. ” (podkreślenie ich)
Pozostała część specyfikacji nie ma atrybutów do przesunięcia pozycji linii. Kiedy program Illustrator pozwala wyrównać do wewnątrz lub na zewnątrz, ponownie oblicza przesunięcie rzeczywistej ścieżki (ponieważ jest to nadal tańsze obliczeniowo niż nadruk, a następnie maskowanie). Współrzędne ścieżki w dokumencie .ai są odniesieniem, a nie tym, co zostaje rastrowane lub eksportowane do ostatecznego formatu.
Ponieważ rodzimym formatem Inkscape jest specyfikacja SVG, nie może oferować funkcji, której brakuje w specyfikacji.
źródło
Oto obejście dla wewnętrznych granic
rect
za pomocąsymbol
iuse
.Przykład : https://jsbin.com/yopemiwame/edit?html,output
SVG :
Uwaga: pamiętaj, aby zastąpić
?
inuse
rzeczywistymi wartościami.Tło : Powodem dlaczego to działa, bo jest symbolem ustanawia nową rzutnię zastępując
symbol
zesvg
i tworzenia elementu w DOM cienia. Tensvg
cień DOM jest następnie łączony z bieżącymSVG
elementem. Zauważ, żesvg
s może być zagnieżdżone i każdasvg
tworzy nową rzutnię, która przycina wszystko, co nakłada się, w tym nakładającą się ramkę. Aby uzyskać bardziej szczegółowy przegląd tego, co się dzieje, przeczytaj fantastyczny artykuł Sary Soueidan.źródło
Nie wiem, jak to będzie pomocne, ale w moim przypadku właśnie utworzyłem inny okrąg z samą ramką i umieściłem go „wewnątrz” drugiego kształtu.
źródło
(Brudnym) możliwym rozwiązaniem jest użycie wzorów,
oto przykład z obrysowanym trójkątem:
https://jsfiddle.net/qr3p7php/5/
źródło
Rozwiązanie Xaviera Ho, polegające na podwojeniu szerokości obrysu i zmianie kolejności farb, jest genialne, chociaż działa tylko wtedy, gdy wypełnienie ma jednolity kolor, bez przezroczystości.
Opracowałem inne podejście, bardziej skomplikowane, ale działa na każde wypełnienie. Działa również w elipsach lub ścieżkach (z późniejszymi są niektóre przypadki narożne o dziwnym zachowaniu, na przykład otwarte ścieżki, które przecinają się, ale niewiele).
Sztuką jest wyświetlanie kształtu na dwóch warstwach. Jeden bez obrysu (tylko wypełnienie), a drugi tylko z obrysem o podwójnej szerokości (przezroczyste wypełnienie) i przeszedł przez maskę, która pokazuje cały kształt, ale ukrywa oryginalny kształt bez obrysu.
źródło