web-dev-qa-db-fra.com

Comment appliquer un filtre ombre portée via CSS à un élément/chemin spécifique à SVG

J'aimerais appliquer un filtre d'ombre portée à un élément/chemin spécifique dans un fichier SVG inséré en ligne via CSS. I not nécessite que tout le graphique soit ombré, mais uniquement un élément situé à l'intérieur.

.shadow {
  fill: red;
  
  -webkit-filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
          filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
}
  <svg height="150" width="150">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

Comme vous pouvez le voir ci-dessus, j'essaie d'appliquer une ombre portée à l'élément cercle rouge du fichier SVG, mais cela ne fonctionne pas.

En cherchant autour de moi, je n'ai trouvé aucune information spécifique à ce sujet, seulement quelques commentaires dans d'autres questions relatives à SVG, indiquant simplement que cela ne fonctionne pas avec un seul élément SVG, mais sans trop d'explications.

UPDATE

Comme indiqué par @ azeós dans les commentaires, le rendu est correct avec Firefox (version 43.0.2), donc il s'agit d'un problème spécifique à Chrome. Est-ce qu'il y a un moyen de faire ce crossbrowser sans jouer avec le code SVG comme suggéré dans les commentaires?

8
Gruber

Vous pouvez appliquer une ombre de manière sélective en sélectionnant la couleur de l'objet que vous souhaitez ombrer, en créant une ombre puis en le fusionnant sous le graphique d'origine. Mais vous devez le faire via le filtre SVG Trapdoor dans les filtres CSS - ce qui ne fonctionne pas dans IE. (Alors ... hacky, mais possible)

Spec est ici: w3.org/TR/SVG11/filters.html#feColorMatrixElement

Le jouet de démonstration est ici:
https://beta.observablehq.com/@gitmullany/filter-effects-using-svg-color-matrices

Cette matrice double l'opacité de toutes les valeurs rouges, zéros sur l'opacité de tout le reste, puis soustrait 1. L'effet consiste à ne laisser que les éléments à 100% d'opacité qui sont en rgb (255,0,0)

#mySVG {
   filter: url(#selective-shadow);
}

.shadow {
  fill: red;
}
<svg>
 <defs>
   <filter id="selective-shadow">
     <feColorMatrix type="matrix" values="0 0 0 0 0 
                                          0 0 0 0 0
                                          0 0 0 0 0 
                                          2 0 0 0 -1"/>
     <feGaussianBlur stdDeviation="3"/>
     <feOffset dy="2" dx="2"/>
     <feMerge>
       <feMergeNode/>
       <feMergeNode in="SourceGraphic"/>
     </feMerge>         
   </filter>
 </defs>
</svg>



<svg height="150" width="150" id="mySVG">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>
2
Michael Mullany

Mise à jour 2018-03: J'ai fait quelques expériences sur cette question car je ne pouvais pas trouver non plus d'informations à ce sujet et les résultats étaient plutôt incohérents. La version TL; DR si vous êtes allez utiliser un polyfill ou faites simplement l'ombrage dans le SVG.

Expérience Codepen: http://codepen.io/staypuftman/pen/GoNoMq } _

Chrome 65 + Canary 67:

Ni Chrome ni Edge Canary ne respectent filter ou -webkit-filter correctement dans le contexte d'un objet SVG, mais fonctionnent sur une simple div.

enter image description here

Firefox 58/Quantum + Firefox 53:

Semble très bien pour les objets SVG et HTML.

enter image description here

Safari 10.1+

Safari a résolu ce problème dans la série 10.1 (et peut-être la 10.0).

enter image description here

Safari 9.x

SVG CSS dropshadow ne s'affiche pas et la variable div dropshadow a moins d'opacité pour une raison quelconque

enter image description here

IE11

Rien.

enter image description here

14
staypuftman

Dans this CodePen, j’ai ajouté différents drop-shadows à path et text générés dynamiquement. Ici j'ai trouvé une solution multi-navigateurs que vous pouvez appliquer à une class, par exemple, au lieu de #robbie img (dans le deuxième lien):

#robbie img { filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";   filter: url(#drop-shadow);   -webkit-filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));   filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5)); }

Dans le premier, CodePen j’ai commenté une autre méthode qui n’utilise pas les classes , mais utilise #numbers_dropshadows_filter et #strokes_dropshadows_filter définis dans <defs></defs>.

À votre santé

1
Riccardo Volpe