SVG Schlagschatten mit CSS3

379

Ist es möglich, Schlagschatten für ein SVG-Element mit CSS3 zu setzen?

box-shadow: -5px -5px 5px #888;
-webkit-box-shadow: -5px -5px 5px #888;

Ich habe einige Anmerkungen zum Erstellen von Schatten mithilfe von Filtereffekten gesehen. Gibt es ein Beispiel für die alleinige Verwendung von CSS? Unten finden Sie einen Arbeitscode, in dem der Cusor-Stil korrekt angewendet wird, jedoch kein Schatteneffekt. Bitte helfen Sie mir, den Schatteneffekt mit dem geringsten Code zu erzielen.

svg .shadow { 
  cursor:crosshair; 
  -moz-box-shadow: -5px -5px 5px #888;
  -webkit-box-shadow: -5px -5px 5px #888;
  box-shadow: -5px -5px 5px #888; 
}	
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" baseProfile="full"  viewBox="0 0 120 70">	
    <rect class="shadow" x="10" y="10" width="100" height="50" fill="#c66" />
</svg>

bsr
quelle

Antworten:

353

Hier ist ein Beispiel für das Anwenden von Dropshadow auf einige SVGs mithilfe der Eigenschaft 'filter'. Wenn Sie die Deckkraft des Dropshadows steuern möchten, sehen Sie sich dieses Beispiel an . Das slopeAttribut steuert, wie viel Deckkraft dem Dropshadow gegeben werden soll.

Relevante Bits aus dem Beispiel:

<filter id="dropshadow" height="130%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="3"/> <!-- stdDeviation is how much to blur -->
  <feOffset dx="2" dy="2" result="offsetblur"/> <!-- how much to offset -->
  <feComponentTransfer>
    <feFuncA type="linear" slope="0.5"/> <!-- slope is the opacity of the shadow -->
  </feComponentTransfer>
  <feMerge> 
    <feMergeNode/> <!-- this contains the offset blurred image -->
    <feMergeNode in="SourceGraphic"/> <!-- this contains the element that the filter is applied to -->
  </feMerge>
</filter>
<circle r="10" style="filter:url(#dropshadow)"/>

Box-Shadow ist für die Arbeit mit CSS-Boxen (sprich: Rechtecke) definiert, während svg etwas ausdrucksvoller ist als nur Rechtecke. Lesen Sie den SVG-Primer , um mehr darüber zu erfahren, was Sie mit SVG-Filtern tun können.

Erik Dahlström
quelle
1
Gibt es eine Möglichkeit, die Deckkraft des Schlagschattens zu steuern?
Hugh Guiney
5
@ HughGuiney: Ja natürlich. Hier ist ein Beispiel für eine Möglichkeit, xn--dahlstrm-t4a.net/svg/filters/… . slopeVariieren Sie einfach das Attribut, um die gewünschte Deckkraft zu optimieren.
Erik Dahlström
1
@LorenzoPolidori IE10 und Safari 5.2 unterstützen beide SVG-Filter.
Erik Dahlström
3
Beispiel dafür, wie dieser Ansatz in D3.js umzusetzen: bl.ocks.org/cpbotha/5200394
MB21
559

Verwenden Sie die neue CSS- filterEigenschaft.

Unterstützt von Webkit-Browsern , Firefox 34+ und Edge .

Sie können diese Polyfüllung verwenden , die FF <34, IE6 + unterstützt.

Sie würden es so verwenden:

/* Use -webkit- only if supporting: Chrome < 54, iOS < 9.3, Android < 4.4.4 */

.shadow {
  -webkit-filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));
  filter: drop-shadow( 3px 3px 2px rgba(0, 0, 0, .7));
  /* Similar syntax to box-shadow */
}
<img src="https://upload.wikimedia.org/wikipedia/commons/c/ce/Star_wars2.svg" alt="" class="shadow" width="200">

<!-- Or -->

<svg class="shadow" ...>
    <rect x="10" y="10" width="200" height="100" fill="#bada55" />
</svg>

Dieser Ansatz unterscheidet sich vom box-shadowEffekt dadurch, dass er die Deckkraft berücksichtigt und den Schlagschatteneffekt nicht auf die Box, sondern auf die Ecken des SVG-Elements selbst anwendet.

Bitte beachten Sie : Dieser Ansatz funktioniert nur, wenn die Klasse nur auf dem <svg>Element platziert wird. Sie können dies NICHT für ein Inline-SVG-Element wie z <rect>.

<!-- This will NOT work! -->
<svg><rect class="shadow" ... /></svg>

Lesen Sie mehr über CSS-Filter auf html5rocks .

hitautodestruct
quelle
47
Dies scheint für Bilder oder für das gesamte SVG zu funktionieren, jedoch für Auswahlen innerhalb des SVG. die Geige
Henryville
13
Dies funktioniert in keiner Weise, um Schlagschatten auf SVG-Elemente anzuwenden. benutze es nicht. Beispiel für einen Fehler: jsbin.com/bepurahuwa/1/edit?html,css,js,output
Andy Ray
19
@AndyRay funktioniert wie ein Zauber ... jsbin.com/peviso/edit?html,css,js,output . Sie setzen die Klasse auf das <svg> -Tag.
Hitautodestruct
3
@hitautodestruct ja, so funktioniert es. Das eigentliche Problem tritt auf, wenn Sie Filter auch auf ein Element anwenden müssen, nicht jedoch auf andere.
Joum
3
Ich denke, sowohl @AndyRay als auch hitautodestruct sind richtig, denn wie hier ausgeführt , sieht dies wie ein Chrome-Rendering-Problem aus: Firefox rendert den Filter für SVG-spezifische Elemente korrekt.
Gruber
71

Mit der CSS-Funktion drop-shadow () und den rgba-Farbwerten können Sie einem svg-Element ganz einfach einen Schlagschatteneffekt hinzufügen. Mit rgba-Farbwerten können Sie die Deckkraft Ihres Schattens ändern.

img.light-shadow{
  filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.4));
}

img.dark-shadow{
  filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 1));
}
<img class="light-shadow" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.svg" />
<img class="dark-shadow" src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.svg" />

Jonny Ekholm
quelle
4
@ Foxhoundn Dies ist definitiv die moderne Lösung und sollte als Antwort akzeptiert werden.
SeedyROM
1
Aber es funktioniert nicht für
Unterelemente
Internet Explorer 11: Fehler (kein Schlagschatten, aber das ursprüngliche SVG-Bild wird angezeigt). Firefox (Release & ESR): OK. Google Chrome: OK. Edge Legacy: OK.
Culip
dam, wenn das nur bei gruppen und formen in der SVG funktioniert!
OG Sean
25

Der einfachste Weg, den ich gefunden habe, ist mit feDropShadow. Ich werde nie wieder diese unglaublich esoterischen Filter-Tag-Namen verwenden, die ich nicht verstehe.

<filter id="shadow" x="0" y="0" width="200%" height="200%">
  <feDropShadow dx="40" dy="40" stdDeviation="35" flood-color="#ff0000" flood-opacity="1" />
</filter>
Nikk Wong
quelle
4
Ich habe etwas gelesen und jetzt, wo ich Ihre Antwort verstehe, bekommen Sie definitiv diese positive Bewertung. Diese Antwort wird nicht genug geschätzt. Ein bisschen mehr Erklärung wäre jedoch gut. Dieses Beispiel zum Beispiel: developer.mozilla.org/en-US/docs/Web/SVG/Element/…
Niklas
Du hast vollkommen recht. Vielen Dank!
Nikk Wong
1

Mir ist keine reine CSS-Lösung bekannt.

Wie Sie bereits erwähnt haben, sind Filter der kanonische Ansatz zum Erstellen von Schlagschatteneffekten in SVG. Die SVG-Spezifikation enthält ein Beispiel dafür.

jbeard4
quelle
3
-webkit-filter: drop-shadow()ist der Weg, um sicher zu gehen. Siehe die Antwort von @hitautodestruct.
Clayzermk1
4
@ Clayzermk1 wenn du willst, dass es nur im Webkit funktioniert .... dann ja. Wir suchen nach einer solideren Lösung, denke ich, und ich denke, dies wird auch nicht mehr unterstützt.
Dudewad
@ jbeard4 Link defekt, besser vielleicht den Inhalt hier einfügen lassen.
Ezeewei
1
Eingereichter Link Punkt zu Removed: Filter Effects This chapter is no longer part of the SVG specification!!
F. Hauri
1
Dies ist keine Antwort.
Yay295
1

Schwarzer Text mit weißem Schatten

Ein anderer Weg, den ich für weißen Schatten (auf Text) verwendet habe: Erstellen Sie einen Klon für Schatten:

Hinweis : Dies erfordert xmlns:xlink="http://www.w3.org/1999/xlink"bei der SVG-Deklaration.

Der reale Textwert befindet sich im <defs>Abschnitt mit Position und Stil, jedoch ohne fillDefinition.

Der Text wird zweimal geklont: erstens für Schatten und zweitens für den Text selbst.

<svg xmlns="http://www.w3.org/2000/svg" width="640" height="70"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
  <filter id="Blur"><feGaussianBlur stdDeviation="0.8" /></filter>
  <text style="font-family:sans,helvetica;font-weight:bold;font-size:12pt"
      id="Text"><tspan x="12" y="19">
        Black text with white shadow
    </tspan></text>
  </defs>
  <rect style="fill:#8AB" width="640" height="70" />
  <use style="fill:white;" filter="url(#Blur)" xlink:href="#Text"
      transform="translate(1.8,.9)"/>
  <use style="fill:black;" xlink:href="#Text"/>
</svg>

Weiter entfernter Schatten mit dem größten Wert als Unschärfeabweichung :

<svg xmlns="http://www.w3.org/2000/svg" width="640" height="70"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
  <filter id="Blur"><feGaussianBlur stdDeviation="3" /></filter>
  <text style="font-family:sans,helvetica;font-weight:bold;font-size:12pt"
      id="Text"><tspan x="12" y="19">
        Black text with white shadow
    </tspan></text>
  </defs>
  <rect style="fill:#8AB" width="640" height="70" />
  <use style="fill:white;" filter="url(#Blur)" xlink:href="#Text"
      transform="translate(7,5)"/>
  <use style="fill:black;" xlink:href="#Text"/>
</svg>

Sie können denselben Ansatz für reguläre SVG-Objekte verwenden.

Bei gleicher Anforderung: Keine Fülldefinition im <defs>Abschnitt !

<svg xmlns="http://www.w3.org/2000/svg" width="364" height="172"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="Blur"><feGaussianBlur stdDeviation="0.8" /></filter>
    <g transform="matrix(.7,0,0,.7,-117.450795,-335.320895)" id="Img">
        <g transform="matrix(12.997776,0,0,-12.997776,389.30313,662.04015)">
            <path d="m 0,0 -1.107,0 c -0.039,0 -0.067,0.044 -0.067,0.086 0,0.015 0.589,1.914 0.589,1.914 0.021,0.071 0.023,0.073 0.031,0.073 l 0.001,0 c 0.009,0 0.01,-0.002 0.031,-0.073 0,0 0.589,-1.899 0.589,-1.914 C 0.067,0.044 0.037,0 0,0 M 1.493,4.345 C 1.482,4.383 1.448,4.411 1.408,4.414 l -4.065,0 C -2.698,4.41 -2.731,4.383 -2.742,4.346 c 0,0 -2.247,-7.418 -2.247,-7.432 0,-0.037 0.029,-0.067 0.067,-0.067 l 2.687,0 c 0.021,0.008 0.037,0.028 0.042,0.051 l 0.313,1 c 0.01,0.025 0.033,0.042 0.061,0.043 l 2.479,0.002 c 0.027,-0.002 0.051,-0.021 0.061,-0.045 l 0.32,-1 c 0.005,-0.023 0.021,-0.044 0.042,-0.052 0,0 2.642,10e-4 2.644,10e-4 0.037,0 0.068,0.028 0.068,0.065 0,0.013 -2.302,7.433 -2.302,7.433" />
        </g>
        <g transform="matrix(12.997776,0,0,-12.997776,508.27177,644.93113)">
            <path d="m 0,0 -1.651,-0.001 c 0,0 -0.044,0.013 -0.044,0.063 l -10e-4,0.833 c 0,0.05 0.044,0.063 0.044,0.063 l 1.514,0 C 0.038,0.958 0.394,0.87 0.394,0.463 0.394,0.056 0,0 0,0 m 7.916,0.645 3.741,0 0,2.453 -4.81,0 C 6.397,3.098 5.764,2.866 5.401,2.597 5.038,2.328 4.513,1.715 4.513,0.87 c 0,-0.845 0.513,-1.502 0.513,-1.502 0.263,-0.326 0.925,-1.005 0.925,-1.005 0.015,-0.016 0.024,-0.037 0.024,-0.061 0,-0.051 -0.041,-0.092 -0.092,-0.092 l -3.705,0 c -0.451,0.002 -0.482,0.181 -0.482,0.207 0,0.046 0.056,0.075 0.056,0.075 0.169,0.081 0.514,0.35 0.514,0.35 0.732,0.57 0.82,1.352 0.82,1.771 0,0.42 -0.063,1.163 -0.814,1.814 C 1.521,3.078 0.57,3.096 0.57,3.096 l -5.287,0 c 0,0 0,-7.52 0,-7.522 0,-0.024 0.022,-0.043 0.046,-0.043 l 2.943,0 0,2.11 c 0,0.037 0.057,0 0.057,0 l 1.533,-1.54 c 0.545,-0.551 1.446,-0.57 1.446,-0.57 l 5.796,0.001 c 0.989,0 1.539,0.538 1.69,0.688 0.15,0.151 0.651,0.714 0.651,1.647 0,0.932 -0.426,1.409 -0.608,1.628 C 8.675,-0.309 8.029,0.375 7.894,0.517 7.878,0.53 7.868,0.55 7.868,0.572 c 0,0.033 0.019,0.064 0.048,0.073" />
        </g>
        <g transform="matrix(12.997776,0,0,-12.997776,306.99861,703.01559)">
            <path d="m 0,0 c 0.02,0 0.034,0.014 0.04,0.036 0,0 2.277,7.479 2.277,7.486 0,0.02 -0.012,0.042 -0.031,0.044 0,0 -2.805,0 -2.807,0 -0.014,0 -0.023,-0.011 -0.026,-0.026 0,-0.001 -0.581,-1.945 -0.581,-1.946 -0.004,-0.016 -0.012,-0.026 -0.026,-0.026 -0.014,0 -0.026,0.014 -0.028,0.026 L -1.79,7.541 c -0.002,0.013 -0.012,0.025 -0.026,0.025 -10e-4,0 -3.1,0.001 -3.1,0.001 -0.009,-0.002 -0.017,-0.01 -0.02,-0.018 0,0 -0.545,-1.954 -0.545,-1.954 -0.003,-0.017 -0.012,-0.027 -0.027,-0.027 -0.013,0 -0.024,0.01 -0.026,0.023 l -0.578,1.952 c -0.001,0.012 -0.011,0.022 -0.023,0.024 l -2.992,0 c -0.024,0 -0.044,-0.02 -0.044,-0.045 0,-0.004 10e-4,-0.012 10e-4,-0.012 0,0 2.31,-7.471 2.311,-7.474 C -6.853,0.014 -6.839,0 -6.819,0 c 0.003,0 2.485,-0.001 2.485,-0.001 0.015,0.002 0.03,0.019 0.034,0.037 10e-4,0 0.865,2.781 0.865,2.781 0.005,0.017 0.012,0.027 0.026,0.027 0.015,0 0.023,-0.012 0.027,-0.026 L -2.539,0.024 C -2.534,0.01 -2.521,0 -2.505,0 -2.503,0 0,0 0,0" />
        </g>
        <g transform="matrix(12.997776,0,0,-12.997776,278.90126,499.03369)">
            <path d="m 0,0 c -0.451,0 -1.083,-0.232 -1.446,-0.501 -0.363,-0.269 -0.888,-0.882 -0.888,-1.727 0,-0.845 0.513,-1.502 0.513,-1.502 0.263,-0.326 0.925,-1.01 0.925,-1.01 0.015,-0.016 0.024,-0.037 0.024,-0.06 0,-0.051 -0.041,-0.093 -0.092,-0.093 -0.008,0 -6.046,0 -6.046,0 l 0,-2.674 7.267,0 c 0.988,0 1.539,0.538 1.69,0.689 0.15,0.15 0.65,0.713 0.65,1.646 0,0.932 -0.425,1.414 -0.607,1.633 -0.162,0.196 -0.808,0.876 -0.943,1.017 -0.016,0.014 -0.026,0.034 -0.026,0.056 0,0.033 0.019,0.063 0.048,0.073 l 3.5,0 0,-5.114 2.691,0 0,5.101 3.267,0 0,2.466 L 0,0 Z" />
        </g>
        <g transform="matrix(12.997776,0,0,-12.997776,583.96822,539.30215)">
            <path d="m 0,0 -1.651,-0.001 c 0,0 -0.044,0.013 -0.044,0.063 l -10e-4,0.833 c 0,0.05 0.044,0.063 0.044,0.063 l 1.514,0 C 0.038,0.958 0.394,0.87 0.394,0.463 0.394,0.056 0,0 0,0 m 2.178,-1.79 c -0.45,0.002 -0.482,0.181 -0.482,0.207 0,0.046 0.056,0.075 0.056,0.075 0.169,0.081 0.514,0.35 0.514,0.35 0.732,0.57 0.82,1.352 0.82,1.771 0,0.42 -0.063,1.163 -0.814,1.814 C 1.521,3.078 0.57,3.098 0.57,3.098 l -5.287,0 c 0,0 0,-7.522 0,-7.524 0,-0.024 0.022,-0.043 0.046,-0.043 0.005,0 2.943,0 2.943,0 l 0,2.109 c 0,0.038 0.057,0 0.057,0 l 1.533,-1.539 c 0.545,-0.551 1.446,-0.57 1.446,-0.57 l 4.525,0 0,2.679 -3.655,0 z" />
        </g>
        <g transform="matrix(12.997776,0,0,-12.997776,466.86346,556.40203)">
            <path d="m 0,0 -1.107,0 c -0.041,0 -0.067,0.044 -0.067,0.086 0,0.016 0.589,1.914 0.589,1.914 0.021,0.071 0.027,0.073 0.031,0.073 l 0.001,0 c 0.004,0 0.01,-0.002 0.031,-0.073 0,0 0.589,-1.898 0.589,-1.914 C 0.067,0.044 0.04,0 0,0 M 1.49,4.347 C 1.479,4.385 1.446,4.412 1.405,4.414 l -4.065,0 C -2.7,4.412 -2.734,4.385 -2.745,4.348 c 0,0 -2.245,-7.42 -2.245,-7.434 0,-0.037 0.03,-0.067 0.067,-0.067 l 2.687,0 c 0.022,0.007 0.038,0.028 0.043,0.051 l 0.313,1.001 c 0.01,0.024 0.033,0.041 0.061,0.042 l 2.478,0 C 0.687,-2.061 0.71,-2.078 0.721,-2.102 l 0.32,-1 c 0.005,-0.023 0.021,-0.044 0.042,-0.052 0,0 2.642,10e-4 2.644,10e-4 0.037,0 0.067,0.028 0.067,0.066 0,0.012 -2.304,7.434 -2.304,7.434" />
        </g>
    </g>
  </defs>
  <rect style="fill:#8AB" width="364" height="172" />
  <use style="fill:white;" filter="url(#Blur)" xlink:href="#Img"
    transform="translate(1.8,.9)"/>
  <use style="fill:black;" xlink:href="#Img"/>
</svg>

F. Hauri
quelle
Wäre es nicht möglich, nur zu verwenden flood-color?
Robert Monfera
Blurwird verwendet, um den Schatten etwas unscharf erscheinen zu lassen. Siehe meine zweite Textversion More distant shadow...(gerade hinzugefügt)
F. Hauri
0

Wahrscheinlich eine Weiterentwicklung, scheint es, dass Inline-CSS-Filter in gewisser Weise gut auf Elemente funktionieren.

Das Deklarieren eines Schlagschatten-CSS-Filters in einem SVG-Element sowohl in einer Klasse als auch in einer Inline funktioniert NICHT , wie zuvor angegeben.

Aber zumindest in Firefox mit der folgenden Zauberei:

Anhängen der Filterdeklaration inline mit Javascript nach dem Laden des DOM .

// Does not works, with regular dynamic css styling:

shadow0.onchange = () => {
  rect1.style.filter = "filter:drop-shadow(0 0 " + shadow0.value + "rem black);"
}

// Okay! Inline styling, appending.

shadow1.onchange = () => {
  rect1.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
  rect2.style += " ;filter:drop-shadow(0 0 " + shadow1.value + "rem black);"
}
<h4>
Does not works! 
<input id="shadow0" type="number" min="0" max="100" step="0.1">

 | Okay!
<input id="shadow1" type="number" min="0" max="100" step="0.1">

<svg viewBox="0 0 120 70">  
    <rect id="rect1" x="10" y="10" width="100" height="50" fill="#c66" />
    
    <!-- Inline style declaration does NOT works at svg level, no shadow at loading: -->
    <rect id="rect2" x="40" y="30" width="10" height="10" fill="#aaa" style="filter:drop-shadow(0 0 20rem black)" />
    
</svg>

Geben Sie hier die Bildbeschreibung ein

NVRM
quelle