Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
640 views
in Technique[技术] by (71.8m points)

css - How to make an inset drop shadow in SVG

I need to make a box with an inset drop shadow, in the same way that CSS3 has inset box-shadows. What I've found so far is a filter with feGaussianBlur, but the problem with that is that it also adds a drop shadow outside the box, which I don't want. Here's the code I've got so far:

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

I've made a demo that also compares this code with the desired CSS-made result. The filter should not just work on rectangles, but also on trapezoids and more complicated polygons.

I've already tried using radialGradient, but since that makes the gradient circular, that's not good either.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you had a solid fill, you could just add

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

to the end of your filter and it would clip the blur to the shape of the SourceGraphic. Since your shape is transparent, you'll have to do a little more work. What I'd suggest is using a semi-transparent fill on the original graphic in order to get the right selection for compositing and using an feFuncA to zero out the fill for the final operation. This turns out to be surprisingly complicated. But here is a solution that will work for any solid-stroke shape

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

here is my fork of your fiddle: http://jsfiddle.net/kkPM4/


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...