web-dev-qa-db-fra.com

Ombre SVG coupée

Le SVG avec lequel je travaille a une ombre portée via le filtre feGaussianBlur.

L'ombre elle-même s'affiche correctement, mais est coupée sur les bords supérieur et inférieur.

Ainsi:

image of cutoff shadow

Le SVG en question est:

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

Le recadrage semble se produire de manière cohérente dans Chrome (30), Firefox (25) et Opera (12).

Je peux voir que ce n'est pas une limitation de viewbox, car il est réglé sur 600x700.

Je peux également voir dans devtools inspector la boîte englobante de l'élément <path>, et c'est presque comme si c'était ce qui coupait l'ombre:

path bounding box

Si c'est le cas:

  1. Pourquoi l'ombre est-elle seulement coupée verticalement et non horizontalement?
  2. Comment contourner cela, pour qu'il ne soit pas coupé comme ça?

Si ce n'est pas la boîte englobante, qu'est-ce qui cause cela et comment éviter cet écrêtage?

54
kangax

Vous devez augmenter la taille de la zone de filtrage.

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

fonctionne très bien. Les valeurs par défaut silencieuses pour la zone de filtrage sont les suivantes: x = "- 10%" y = "- 10%" width = "120%" height = "120%" - les grands flous sont généralement coupés. (Votre ombre ne se coupe pas horizontalement parce que votre largeur est environ 2,5 fois votre hauteur - de sorte que 10% donne une zone de filtre horizontale plus large). De plus, la région du filtre y semble être calculée comme si le chemin avait un trait de pixel nul, il ignore donc la largeur du trait. (Les différents navigateurs ont un comportement différent selon qu'ils considèrent le trait comme faisant partie de la zone de délimitation aux fins du calcul de la zone de filtrage.)

(Mise à jour: remonter les observations à partir des commentaires) Veuillez noter que si votre forme particulière est soit de largeur nulle, soit de hauteur nulle (par exemple une ligne horizontale ou verticale), alors vous doit spécifier filterUnits="userSpaceOnUse" dans le cadre de la déclaration de filtre et spécifiez explicitement une région de filtre (x, y, largeur en hauteur) dans userSpaceUnits (généralement des pixels) qui crée suffisamment d'espace pour afficher une ombre.

81
Michael Mullany

Comme indiqué dans un commentaire ci-dessus, le correctif consistait à ajouter un attribut à la balise filter shadow svg.

filterUnits="userSpaceOnUse"

Sortie finale:

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

Ce qui rend l'ombre parfaitement positionnée et visible à l'extérieur de son contenant.

8
Jack Nicholson

Si vous l'utilisez dans un code HTML, vous pouvez simplement utiliser les propriétés CSS pour résoudre ce problème.

svg {
  overflow: visible !important;
}

Je n'ai pas vérifié d'autres navigateurs, mais chrome a le overflow: hidden par défaut sur les balises svg.

Un peu tard, mais j'espère que c'est utile.

4
Daniel Reina