9

I'm trying to create a dynamic blur effect, that can be modified with javascript on the fly.

To start with, I'm using this really simple svg filter:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter id="blur">
<feGaussianBlur stdDeviation="0" />
</filter>
</svg>

The stdDeviation starts at 0, and I want to be able to change that with the javascript. I've tried a few different things, but I haven't quite been able to nail it down.

Firstly, (and I should note that I am using jQuery) I tried to simply select the feGaussianBlur element and modify it's attribute:

$('feGaussianBlur').attr('stdDeviation',5);

This didn't replace the already existing attribute like I expected, but rather, added another, leaving me with <feGaussianBlur stdDeviation="0" stdDeviation="5" /> Removing the original stdDeviation from the HTML made it so that there was only one attribute after the change, but it had no effect.

Next, I attempted to simply replace the contents of the filter with the new one:

$('filter#blur').html('<feGaussianBlur stdDeviation="5" />');

This time, not only did it not succeed in changing, but it caused the element that this filter is applied to, to disappear completely (I assume the filter was corrupted, or somesuch).

I even tried re-applying the css declaration for the filter afterwards, for both of the previous cases.

The one thing that I tried that DID work, was to build out 10 different filters, with 10 different values, and then rather than changing the SVG with the javascript, I simply reassigned the css to a different filter ID. To be honest, this approach seems a little more.. proper? The big downside though is that it isn't very versatile, and takes a lot of work to change things. Also, I'd prefer to use values with a decimal place, which would require 100 filter declarations to accomplish.

So, my question is... Is there a good way to dynamically modify an SVG filter (in my case, the blur filter specifically) using javascript? If there is, is it a respectable approach, in terms of semantics and standards? If nothing else, I'm more than willing to fall back to my solution of using a few (I can live without decimals) filters and swapping them out, but I want to explore my options first.

Or, if you don't have a solution, but could at least explain to me why my first couple attempts did not work, please let me know! I'm curious what the reasons are.

2 Answers 2

11

It would be simpler to do this using ordinary DOM rather than jquery. Move the id to the feGaussianBlur element

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter>
<feGaussianBlur id="blur" stdDeviation="0" />
</filter>
</svg>

And then

document.getElementById("blur").setAttribute("stdDeviation", "5");

or alternatively

document.getElementById("blur").setStdDeviation(5, 5);
3
  • 1
    That works perfectly! I am curious though why jQuery can not seem to do the exact same thing? Doesn't it essentially boil down to this anyways?
    – Blake Mann
    Commented Oct 3, 2013 at 0:26
  • Wild guess - I'm going to guess it's because you've put your filter element in the svg namespace. If you leave off the namespace declaration, I'm going to guess it will work Commented Feb 11, 2014 at 23:46
  • 1
    This won't work in IE 10+. You need to use stdDeviationX and stdDeviationY in IE 10 or later. msdn.microsoft.com/en-us/library/hh773246(v=vs.85).aspx Commented Jun 16, 2015 at 4:26
5

This question is old, but it's worth answering.

There are two reasons why setting/getting attributes with jQuery on SVG elements might not work:

1. Letter case

jQuery has this code in its attr() implementation:

if ( .... || !jQuery.isXMLDoc( elem ) ) {
   name = name.toLowerCase();

In other words, it reads/sets the attribute stddeviation, not stdDeviation.

2. Attributes vs properties

In old jQuery versions, the propetry, instead of the attribute, is used. This casuses things to fail if the property is not a simple string value (E.g., "For an SVG element, className is not a string, but an instance of SVGAnimatedString". E.g., There isn't really a stdDeviation property at all, but X and Y ones). See the documentation of prop() and attr() for more information.

So, what to do?

Here's an implementation of xattr(), which works where attr() fails, because it doesn't try to be smart. Use it instead of attr().

jQuery.fn.xattr = function(name, val) {
  if (val !== undefined) {
    this.each(function() {
      this.setAttribute(name, val);
    });
    return this;
  }
  else {
    if (this.length)
      return this[0].getAttribute(name);
  }
};
1
  • 1
    Thanks, it's good to finally get an answer for the "why" instead of just the workaround.
    – Blake Mann
    Commented Jan 28, 2019 at 16:21

Not the answer you're looking for? Browse other questions tagged or ask your own question.