Search code examples
javascripthtmlcsssvgsvg-filters

Is blurring or fading out an SVG path possible?


Is it possible to blur or fade out an SVG path? I have a bunch of lines that I would ideally like to fade out at the beginning or end (i.e. just on one side), or at the very least blur them so it looks like one half is more in focus than the other.

If it's not possible, how could I go about changing the SVG to make it possible?

var bodyElement = document.querySelector("body");
bodyElement.addEventListener("mousemove", getMouseDirection, false);

var xDirection = "";
var yDirection = "";

var oldX = 0;
var oldY = 0;

function getMouseDirection(e) {
  if (oldX < e.pageX) {
    xDirection = "right";
  } else {
    xDirection = "left";
  }
  if (oldY < e.pageY) {
    yDirection = "down";
  } else {
    yDirection = "up";
  }
  oldX = e.pageX;
  oldY = e.pageY;
}

var tl;

$('g')
.on('mouseover', function() {
  tl = new TimelineLite();
  if (yDirection === "down") {
    tl.to($(this), 1, {
      y: 10
    });
  }
  if (yDirection === "up") {
    tl.to($(this), 1, {
      y: -10
    });
  }
})
.on('mouseout', function() {
  tl = new TimelineLite();
  tl.to($(this), 1, {
    y: 0,
    x: 0
  });
});
body {
  background: #000;
}

.f0 {
  filter: url(#f0);
  animation-delay: .5s;
}

.f1 {
  filter: url(#f1);
  animation-delay: 1s;
}

.f2 {
  filter: url(#f2);
  animation-delay: 2s;
}

.f3 {
  filter: url(#f3);
  animation-delay: 3s;
}

.line {
  opacity: 0;
  animation-name: fadeIn;
  animation-duration: 2s;
  animation-fill-mode: forwards;
}

@keyframes fadeIn {
  to {
    opacity: 1;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.2/TweenMax.min.js"></script>

<svg height="480" version="1.1" width="640" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <filter id="f0">
      <feGaussianBlur in="SourceGraphic" stdDeviation="1" />
    </filter>
    <filter id="f1">
      <feGaussianBlur in="SourceGraphic" stdDeviation="2" />
    </filter>
    <filter id="f2">
      <feGaussianBlur in="SourceGraphic" stdDeviation="7" />
    </filter>
    <filter id="f3">
      <feGaussianBlur in="SourceGraphic" stdDeviation="15" />
    </filter>
  </defs>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S538,357,192,108" stroke-width="5"></path>
    <path class="line" fill="none" stroke="#ffffff" d="M11,163S538,357,192,108" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S626,299,507,115" stroke-width="5"></path>
    <path class="line f1" fill="none" stroke="#ffffff" d="M11,163S626,299,507,115" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S620,182,612,189" stroke-width="5"></path>
    <path class="line f2" fill="none" stroke="#ffffff" d="M11,163S620,182,612,189" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S55,480,558,56" stroke-width="5"></path>
    <path class="line f2" fill="none" stroke="#ffffff" d="M11,163S55,480,558,56" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S654,86,533,328" stroke-width="5"></path>
    <path class="line f1" fill="none" stroke="#ffffff" d="M11,163S654,86,533,328" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S397,248,466,162" stroke-width="5"></path>
    <path class="line f3" fill="none" stroke="#ffffff" d="M11,163S397,248,466,162" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S651,181,569,111" stroke-width="5"></path>
    <path class="line f3" fill="none" stroke="#ffffff" d="M11,163S651,181,569,111" stroke-width="1"></path>
  </g>
  <g>
    <path class="hitbox" fill="none" stroke="transparent" d="M11,163S599,394,220,338" stroke-width="5"></path>
    <path class="line f0" fill="none" stroke="#ffffff" d="M11,163S599,394,220,338" stroke-width="1"></path>
  </g>
</svg>

http://codepen.io/anon/pen/rxKvMj


Solution

  • This is a way to hack a progressive blur along a path by abusing stroke-dash-array and opacity manipulation within an SVG filter. Basically, you carefully construct a stroke dash array of increasing spaces, then use a large blur to "fill in the gaps". Then you boost the opacity using a component transfer and then use the original graphic to mask out the overflow. Note you must first draw your path in white (or your background color) and then the stroke dashed path over it so you have the proper selection for compositing. For a general solution, you'd need to construct the stroke-dash array and the filter using JavaScript because it and the stdDeviation you want to use are going to be dependent on the path length.

    <svg width="800px" height="600px" color-interpolation-filters="sRGB" viewBox="0 0 1600 1200">
      <defs>
        <filter id="fade-out">
          
          <feGaussianBlur in="SourceGraphic" stdDeviation="16" result="blur-source"/>
        
          <feComponentTransfer result="fader">
            <feFuncA type="gamma" exponent=".5" amplitude="2"/>
          </feComponentTransfer>
              
          <feComposite operator="in" in="fader" in2="SourceGraphic"/>    
      
        </filter>
      </defs>
    
    <g filter="url(#fade-out)">
       <path d="M200,300 Q400,50 600,300 T1000,300" stroke-width="5" fill="none" stroke="white"/> 
      
      <path d="M200,300 Q400,50 600,300 T1000,300"
            fill="none" stroke="red" stroke-width="5" stroke-dasharray="10,1,8,3,8,5,7,7,7,9,6,11,6,13,5,15,5,17,5,19,5,21,5,23,5,25,5,27,5,29,5"/> 
      </g>
    </svg>