I am trying to create a material design, such as a shadow on an SVG circle. I want this shadow to develop with a good transition when you click on the circle, but at the moment I'm struggling to figure out whether it is possible to revive this transition, so I hope someone can help.
I added a small example of what I still have, a circle with a dropshadow that changes when you hover over it. I spent quite a bit of time trying to make a dropshadow in CSS, but came to the conclusion that I don't think this is possible right now.
Now that I have the shadows, I cannot find a way to animate them. I found an example using animation tags for single properties (like circle colors) and found examples using key frames for CSS transitions, but here I want to change the actual filter itself. Is this possible, and someone can illustrate how you can achieve this - ideally, I'm trying to achieve compatibility with IE10 / FF / Chrome, so I would be interested to know if there are any complications with the solution?
circle { fill: #8BC34A; stroke: white; stroke-width: 2px; filter: url(#f1); transition: 2s ease; } circle:hover { filter: url(#f2); transition: 2s ease; }
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="500" height="500" viewPort="0 0 200 200"> <defs> <filter id="f1" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="0" /> <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f2" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="0" /> <feGaussianBlur result="blurOut" in="offOut" stdDeviation="30" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> </defs> <circle r="100" cx="150" cy="150" /> </svg>
UPDATE
After trying a few things, I gave a few examples, although none of them do what I want. I need to be able to switch transitions to one / several elements (and not every circle in SVG), for which I can have several hundred. I also ultimately want to change both the size of the circle (the rise according to the material design) and the increase in the side of the shadow below it.
(function() { var svg = d3.select("#svg_javaScriptAnimation"); setInterval(function() {
circle { fill: #8BC34A; stroke: white; stroke-width: 2px; } text { fill: white; } #svg_keyframes{ animation:filters 2s infinite; } @-webkit-keyframes filters { 0%{ -webkit-filter:drop-shadow(0px 16px 10px #333); } 100% { -webkit-filter:drop-shadow(0px 16px 30px #333); } } .kf_Shadow1 { -webkit-animation-name: shadow-expand; / Chrome, Safari, Opera / -webkit-animation-duration: 2s; / Chrome, Safari, Opera / -webkit-animation-iteration-count: infinite; animation-name: shadow-expand; animation-duration: 2s; animation-iteration-count: infinite; } .kf_Fill1 { -webkit-animation-name: circle-fill; / Chrome, Safari, Opera / -webkit-animation-duration: 2s; / Chrome, Safari, Opera / -webkit-animation-iteration-count: infinite; animation-name: circle-fill; animation-duration: 2s; animation-iteration-count: infinite; } .kf_DropShadow1 { -webkit-animation-name: drop-shadow-expand; / Chrome, Safari, Opera / -webkit-animation-duration: 2s; / Chrome, Safari, Opera / -webkit-animation-iteration-count: infinite; animation-name: drop-shadow-expand; animation-duration: 2s; animation-iteration-count: infinite; } @keyframes circle-fill { 0% { fill: #FF0000; } 25% { fill: #BB0033; } 50% { fill: #990066; } 75% { fill: #4400aa; } 100% { fill: #0000ff; } } @keyframes shadow-expand { 0% { filter: url(#f1); -webkit-filter: url(#f1);} 25% { filter: url(#f2); -webkit-filter: url(#f1);} 50% { filter: url(#f3); -webkit-filter: url(#f1);} 75% { filter: url(#f4); -webkit-filter: url(#f1);} 100% { filter: url(#f5); -webkit-filter: url(#f1);} } @keyframes drop-shadow-expand { 0% { -webkit-filter:drop-shadow(0px 16px 10px #333); } 25% { -webkit-filter:drop-shadow(0px 16px 15px #333); } 50% { -webkit-filter:drop-shadow(0px 16px 20px #333); } 75% { -webkit-filter:drop-shadow(0px 16px 25px #333); } 100% { -webkit-filter:drop-shadow(0px 16px 30px #333); } } .fA_shadow { filter: url(#f1); } .jA_shadow { filter: url(#f1); stroke: none !important; } .jA_shadow_expanding { filter: url(#f1); stroke: none !important; fill: #CCC !important; } .jA_shadow_large { filter: url(#f2); stroke: none !important; fill: #CCC !important; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <h1>CSS Keyframes</h1> <p>The downside here is that the animation seems to require attaching to the svg element, which causes all of the circles to animate their drop shadows</p> <svg id="svg_keyframes" width="1000" height="280"> <g transform="translate(120, 140)"> <circle r="110"/> <text dx="-1.5em">Circle 1</text> </g> <g transform="translate(420, 140)"> <circle r="110"/> <text dx="-1.5em">Circle 2</text> </g> </svg> <h1>CSS Keyframes referencing SVG Filters</h1> <p>Unfortunately it seems that this approach simply doesn't work. The idea was that the class would change triggering a keyframe which would progressively change the filter being applied by specifying gradually expanding filters</p> <svg id="svg_filterKeyFrames" width="1000" height="280"> <defs> <filter id="f1" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="10" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f2" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="7" /> <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="15" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f3" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="10" /> <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="20" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f4" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="13" /> <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="25" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f5" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="16" /> <feGaussianBlur result="blurOut" in="matrixOut" stdDeviation="30" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> </defs> <g transform="translate(120, 140)"> <circle class="kf_Shadow1" r="110"/> <text dx="-4.5em">Shadow should change</text> </g> <g transform="translate(420, 140)"> <circle class="kf_Fill1" r="110"/> <text dx="-4.5em">Colour should change</text> </g> <g transform="translate(720, 140)"> <circle class="kf_DropShadow1" r="110"/> <text dx="-5.5em">Drop Shadow should change</text> </g> </svg> <h1>SVG Filters Animations</h1> <p>SVG filter animations are another way to tackle this problem, but it seems that they behave very similar to a CSS filter in that because they are shared all of the elements update</p> <svg id="svg_filterAnimation" width="1000" height="280"> <defs> <filter id="f1" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> <feGaussianBlur id="blur1" result="blurOut" in="matrixOut" stdDeviation="10" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> </defs> <g transform="translate(120, 140)"> <circle class="fA_shadow" r="110"/> <text dx="-1.5em">Circle 1</text> </g> <g transform="translate(420, 140)"> <circle class="fA_shadow" r="110"/> <text dx="-1.5em">Circle 2</text> </g> <animate xlink:href="#blur1" attributeName="stdDeviation" from="10" to="30" dur="2s" begin="0s" repeatCount="indefinite"/> </svg> <h1>JavaScript Animations</h1> <p>Animation via JavaScript is another approach, this uses D3 but the issue here is changing the size of gaussian blur that operates on the shadow is incredibly difficult as demonstrated in Circle 2</p> <svg id="svg_javaScriptAnimation" width="1000" height="280"> <defs> <filter id="f1" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> <feGaussianBlur id="blur1" result="blurOut" in="matrixOut" stdDeviation="10" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> <filter id="f2" x="-40%" y="-40%" height="200%" width="200%"> <feOffset result="offOut" in="SourceAlpha" dx="0" dy="4" /> <feGaussianBlur id="blur1" result="blurOut" in="matrixOut" stdDeviation="30" /> <feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> </filter> </defs> <g transform="translate(120, 140)"> <circle class="jA_shadow" r="110"/> <circle class="circle" r="110"/> <text dx="-1.5em">Circle 1</text> </g> <g transform="translate(420, 140)"> <circle class="jA_shadow_expanding" r="110"/> <circle class="circle" r="110"/> <text dx="-1.5em">Circle 2</text> </g> <g transform="translate(720, 140)"> <circle class="jA_shadow_large" r="80"/> <circle class="circle" r="110"/> <text dx="-1.5em">Circle 3</text> </g> <animate xlink:href="#blur1" attributeName="stdDeviation" from="10" to="30" dur="2s" begin="0s" repeatCount="indefinite"/> </svg>
source share