2013-07-26 28 views
35

SVG, z którym pracuję, ma cień przez filtr feGaussianBlur.Cień SVG odcięty

Sam cień jest wyświetlany prawidłowo, ale zostaje odcięty na górnej i dolnej krawędzi.

tak:

image of cutoff shadow

SVG w pytaniu:

<?xml version="1.0" standalone="no" ?> 
<!DOCTYPE svg 
    PUBLIC '-//W3C//DTD SVG 1.1//EN' 
    'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> 
<svg height="600" version="1.1" width="700" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
    <defs/> 
    <filter id="SVGID_0"> 
    <feGaussianBlur in="SourceGraphic" stdDeviation="6.6"/> 
    <feOffset dx="0" dy="0"/> 
    <feMerge> 
     <feMergeNode/> 
     <feMergeNode in="SourceGraphic"/> 
    </feMerge> 
    </filter> 
    <path d="M 0 83 Q 0 83 0 83 Q 0 83 6 79.5 Q 12 76 17 71 Q 22 66 30.5 57.5 Q 39 49 54 36 Q 69 23 82.5 16.5 Q 96 10 120 4.5 Q 144 -1 170.5 0 Q 197 1 218 16.5 Q 239 32 253.5 51 Q 268 70 278 83.5 Q 288 97 299 110 Q 310 123 320 129.5 Q 330 136 338 136.5 Q 346 137 355 129.5 L 364 122" stroke-linecap="round" style="stroke: #005e7a; stroke-width: 30; fill: none; filter: url(#SVGID_0);" transform="translate(50 50)" /> 
</svg> 

przycinanie zdarza się konsekwentnie w Chrome (30), Firefox (25) i Opera (12).

Widzę, że nie jest to ograniczenie dla przeglądarki, ponieważ jest ustawione na 600 x 700.

Mogę również zobaczyć w DevTools inspektora obwiednię < path> elementu, a to prawie tak, jakby to, co odcina cień:

path bounding box

Jeśli to przypadek:

  1. Dlaczego cień jest obcięty tylko w pionie, a nie w poziomie?
  2. Jak obejść ten problem, aby nie był tak obcięty?

Jeśli to nie ramka ograniczająca, co powoduje to i jak tego uniknąć?

Odpowiedz

60

Należy zwiększyć rozmiar obszaru filtra.

<filter id="SVGID_0" y="-40%" height="180%"> 

działa dobrze. Domyślne wartości dla obszaru filtra to: x = "- 10%" y = "- 10%" szerokość = "120%" wysokość = "120%" - duże zacięcia są zwykle przycinane. (Twój cień nie jest przycinany w poziomie, ponieważ twoja szerokość jest około 2,5 x twoja wysokość - tak, że 10% skutkuje szerszym poziomym obszarem filtrującym). Ponadto, region filtru y wydaje się być obliczany tak, jakby ścieżka miała skok o wartości 0 pikseli, więc ignoruje szerokość obrysu. (Różne przeglądarki mają różne zachowanie wrt czy uważają skok być częścią obwiedni dla celów obliczania regionie filtr).

(aktualizacja: przesuwając się obserwacje z komentarzem) Należy pamiętać, że jeśli szczególności kształt albo zero szerokości, albo zero wysokości (np. linia pozioma lub pionowa), następnie musi określić filterUnits="userSpaceOnUse" jako część deklaracji filtra i jawnie określić region filtra (x, y, szerokość wysokość) w userSpaceUnits (zazwyczaj pikselach), które tworzy wystarczająco dużo miejsca, aby wyświetlić cień.

+2

Ah, bardzo interesujące. Nie miałem pojęcia o regionie filtra, ale widzę go teraz w specyfikacji. – kangax

+1

Jak ustawić atrybut y i atrybut wysokości filtru, jeśli nie wiesz, jak duży będzie twój cień wcześniej? Czy po prostu musisz ustawić to w locie, czy można powiedzieć "Chciałbym, aby mój cień nigdy nie został odcięty, bez względu na to, jak duży jest?" –

+1

Można utworzyć bardzo duży domyślny obszar cienia, ale to także zajmie pamięć. Bardzo duże cienie również wymagają dużej wydajności, więc lepiej ich unikać. –

0

Jeśli używasz go wewnątrz HTML, możesz po prostu użyć właściwości CSS, aby rozwiązać ten problem.

svg { 
    overflow: visible !important; 
} 

Nie sprawdzałem innych przeglądarek, ale chrom ma overflow: hidden domyślnie na znaczniki SVG.

Trochę za późno, ale mam nadzieję, że jest to pomocne.

+0

Ktoś pokonał; Czy istnieje dobry ogólny powód, aby nie stosować tej nieruchomości? – user66081

+0

Używam go w projekcie i działa świetnie. Nie wiem, czy istnieje konkretny przypadek, w którym nie należy go stosować. W moim projekcie nie mogłem znaleźć kombinacji "y" i "wysokości", która działała z rozwiązaniem Michaela Mullany, więc musiałem wdrożyć to, które opisałem powyżej. –

+0

Thx, myślę, że to jest przydatne. – user66081

4

Jak napisano w komentarzu powyżej, poprawka dla mnie polegała na dodaniu atrybutu do svg tagu filter shadow.

filterUnits="userSpaceOnUse" 

Wyjście końcowe:

<filter id="dropshadow" height="130%" width="130%" filterUnits="userSpaceOnUse"> 

co sprawia, że ​​cień absolutnie umieszczone i widoczna poza opakowanie.

+2

Dodanie tego bez dodania wyraźnych wymiarów powoduje nieokreślone zachowanie i może spowodować problemy z wydajnością, ponieważ rozmycie (na przykład) można obliczyć na całej powierzchni rysunku SVG. Jeśli to zrobisz, musisz dodać wyraźne wymiary. –

+0

Czy wymagane są tylko atrybuty x/y? –

+1

tylko szerokość i wysokość –