首頁  >  問答  >  主體

如何在 SVG 中製作插入陰影

我需要製作一個帶有內嵌陰影的盒子,就像 CSS3 具有內嵌盒子陰影一樣。到目前為止我發現的是一個帶有 feGaussianBlur 的濾鏡,但問題是它還在框架外添加了陰影,這是我不想要的。這是我到目前為止得到的程式碼:

<svg>
    <defs>
        <filter id="drop-shadow">
            <feGaussianBlur in="SourceAlpha" result="blur" stdDeviation="5" />
            <feGaussianBlur in="SourceAlpha" result="blur2" stdDeviation="10" />
            <feGaussianBlur in="SourceAlpha" result="blur3" stdDeviation="15" />
            <feMerge>
                <feMergeNode in="blur" mode="normal"/>
                <feMergeNode in="blur2" mode="normal"/>
                <feMergeNode in="blur3" mode="normal"/>
                <feMergeNode in="SourceGraphic" mode="normal"/>
            </feMerge>
        </filter>
    </defs>
    <rect x="10" y="10" width="100" height="100"
    stroke="black" stroke-width="4" fill="transparent" filter="url(#drop-shadow)"/>
</svg>

我製作了一個演示,並將此程式碼與所需的 CSS 製作結果進行比較。此濾鏡不僅適用於矩形,也適用於梯形和更複雜的多邊形。

我已經嘗試過使用 RadialGradient,但由於這會使漸變變成圓形,所以這也不好。

P粉311089279P粉311089279334 天前628

全部回覆(2)我來回復

  • P粉287345251

    P粉2873452512023-10-22 11:16:24

    主要基於我發現的實驗,這就是我的想法:

    <defs><filter id="inset-shadow">
        <feOffset dx="10" dy="10"/>                                                         <!-- Shadow Offset -->
        <feGaussianBlur stdDeviation="10"  result="offset-blur"/>                           <!-- Shadow Blur -->
        <feComposite operator="out" in="SourceGraphic" in2="offset-blur" result="inverse"/> <!-- Invert the drop shadow to create an inner shadow -->
        <feFlood flood-color="black" flood-opacity="1" result="color"/>                     <!-- Color & Opacity -->
        <feComposite operator="in" in="color" in2="inverse" result="shadow"/>               <!-- Clip color inside shadow -->
        <feComponentTransfer in="shadow" result="shadow">                                   <!-- Shadow Opacity -->
            <feFuncA type="linear" slope=".75"/>
        </feComponentTransfer>
        <!--<feComposite operator="over" in="shadow" in2="SourceGraphic"/>-->                       <!-- Put shadow over original object -->
    </filter></defs>
    
    <rect width="100" height="100" fill="yellow" filter="url(#inset-shadow)"/>

    如果您希望看到填充,請取消註解最後一個 。不幸的是,fill="transparent" 不會為濾鏡提供可使用的 Alpha,也不會產生陰影。

    回覆
    0
  • P粉216203545

    P粉2162035452023-10-22 11:00:31

    如果你有實心填充,你可以加上

    <feComposite operator="in" in2="SourceGraphic"/>

    到過濾器的末端,它會將模糊剪裁為 SourceGraphic 的形狀。由於您的形狀是透明的,因此您需要做更多的工作。我建議在原始圖形上使用半透明填充,以便獲得正確的合成選擇,並使用 feFuncA 將最終操作的填充歸零。事實證明這非常複雜。但這裡有一個適用於任何實線形狀的解決方案

    <filter id="inset-shadow" >
                <!-- dial up the opacity on the shape fill to "1" to select the full shape-->
                <feComponentTransfer in="SourceAlpha" result="inset-selection">
                    <feFuncA type="discrete" tableValues="0 1 1 1 1 1"/>
                </feComponentTransfer>
    
                <!-- dial down the opacity on the shape fill to "0" to get rid of it -->
                <feComponentTransfer in="SourceGraphic" result="original-no-fill">
                    <feFuncA type="discrete" tableValues="0 0 1"/>
                </feComponentTransfer>
    
                <!-- since you can't use the built in SourceAlpha generate your own -->
                <feColorMatrix type="matrix" in="original-no-fill" result="new-source-alpha" values="0 0 0 0 0
                          0 0 0 0 0
                          0 0 0 0 0
                          0 0 0 1 0"
    />            
    
                <feGaussianBlur in="new-source-alpha" result="blur" stdDeviation="5" />
                <feGaussianBlur in="new-source-alpha" result="blur2" stdDeviation="10" />
                <feGaussianBlur in="new-source-alpha" result="blur3" stdDeviation="15" />
                <feMerge result="blur">
                    <feMergeNode in="blur" mode="normal"/>
                    <feMergeNode in="blur2" mode="normal"/>
                    <feMergeNode in="blur3" mode="normal"/>
                </feMerge>
                <!-- select the portion of the blur that overlaps with your shape -->
                <feComposite operator="in" in="inset-selection" in2="blur" result="inset-blur"/>
                 <!-- composite the blur on top of the original with the fill removed -->
                <feComposite operator="over" in="original-no-fill" in2="inset-blur"/>            
            </filter>

    這是我的小提琴分支:http://jsfiddle.net/kkPM4/

    #

    回覆
    0
  • 取消回覆