1

I'm trying to desaturate the linked image in my SVG when a button is clicked (I need it to load in colour initially).

I've tried doing this:

     $("#greyOut").click ( function() {
       $("#image1").css("filter", "grayscale(100%)");
     });

I have also tried doing this:

      $("#greyOut").click ( function() {
       $("#image1").toggleClass("desaturate");
      });

     .desaturate{
       filter: grayscale(100%);
     }

My SVG code looks like this:

    <svg version="1.1" id="mySVG" viewBox="0 0 1036.1863 541.28723" height="152.76329mm" width="292.43481mm">
    <defs id="defs1"/>
    <g transform="matrix(1,0,0,1,5.3227865,-408.7683)" id="svgGroup" style="fill:none">
     <image xlink:href="adamPNG.png" y="416.47034" x="-5.3228474" id="image1" preserveAspectRatio="none" height="533.58521" width="1029.7035" />

     //I've a lot of paths here so I've cut them out for my question

     <path id="path1"...style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
     </path>
    </g>
   </svg>

I have also tried calling just $("image") and not the id, but that doesn't work either. Is it possible to change the CSS of a linked image, or should I just set the xlink:href attribute of the <image> to a desaturated version of my image?

Update

It will work if I do this:

     $("#greyOut").click ( function() {
       $('image').attr('xlink:href', 'adamPNGgrey.png');
     });

I would still prefer to do this with CSS rather than linking in another image, if it's possible...

truly-daunting
  • 75
  • 1
  • 13
  • 1
    I'm not sure you can toggle classes on CSS internals...perhaps attributes but not classes. - http://stackoverflow.com/questions/8638621/jquery-svg-why-cant-i-addclass – Paulie_D Jul 14 '16 at 10:32
  • 1
    Your code works fine for me: https://jsfiddle.net/blonfu/aqdj01kn/2/ –  Jul 14 '16 at 10:42
  • You JSFiddle code won't work for me though :/ Nothing happens when I click the button...What browser are you using? – truly-daunting Jul 14 '16 at 10:47
  • Your code works fine for me too. Which version of jQuery are you using? On what browser are you testing the code? – Sevban Öztürk Jul 14 '16 at 10:52
  • I use Firefox. I try in Chrome now and doesn't work, neither using `-webkit-filter` –  Jul 14 '16 at 11:00
  • @SevbanÖztürk I'm using the latest JQuery (https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js), and I'm using Google Chrome, which is up to date... I tried it in Firefox there, and it works.. Not sure why it won't work in Chrome though.. – truly-daunting Jul 14 '16 at 11:02
  • @blonfu yeah I've discovered that it will work in Firefox. However, I need it to work in Chrome...wonder why it won't work.. – truly-daunting Jul 14 '16 at 11:04
  • `filter` isn't supported by Chrome on SVG objects at present. – Paulie_D Jul 14 '16 at 11:51

2 Answers2

1

If you can edit the SVG I have a solution with SVG filters. In the code snippet doesn't work, I put a external jsfiddle.

 $("#greyOut").click(function() {);
   $("#filter").toggleClass("filtered");
 });

DEMO: https://jsfiddle.net/blonfu/aqdj01kn/13/

PS Doesn't work in IE11

UPDATE:

For IE you can do this, before you check the browser and use the first jQuery for Firefox, Chrome, etc and the second for IE:

 $("#greyOut").click(function() {
   $("#filter image").attr("filter", "url(#grayscale)");
 });
  • 1
    I edit the answer for IE, but you have to do a function for know what browser is using –  Jul 14 '16 at 12:00
1

If you implement a JavaScript-only solution like the one below, you can even have full control on how much desaturation to be applied on the image.

JavaScript

(function(d){
      // Range input element
  var gsRANGE = d.getElementById('grayscalerangeinput'),

      // Function to alter saturation dynamically
      changeSaturation = function(targetID,saturationValue){
        var gs = d.getElementById('grayscale');

        if(!!gs){
          gs.setAttribute('values',saturationValue);
        }
        else {
          /* Define namespace URI for SVG
          and filtering elements associated with it */
          var nsURI = "http://www.w3.org/2000/svg",
              filter = d.createElementNS(nsURI,'filter'),
              fe = d.createElementNS(nsURI,'feColorMatrix');

          // Set attributes for the filter element
          filter.setAttribute('id','myFilter');
          fe.setAttribute('id','grayscale');
          fe.setAttribute('type','saturate');
          fe.setAttribute('values',saturationValue);

          // Append the filter element
          filter.appendChild(fe);
          d.getElementById('mySVG').appendChild(filter);

          // Set filter on target image
          d.getElementById(targetID).setAttribute('filter','url(#myFilter)');
        }
      };


  // Add event listeners on buttons and the range input
  d.getElementById('greyOut').addEventListener('click',function(){
    gsRANGE.value = 0;
    changeSaturation('image1',0);
  });

  d.getElementById('recolor').addEventListener('click',function(){
    gsRANGE.value = 10;
    changeSaturation('image1',1);
  });

  gsRANGE.addEventListener('change',function(e){
    changeSaturation('image1',e.target.value/10);
  });

})(document);

Additional HTML

<button id="greyOut" type="button">DESATURATE IMAGE</button>
<button id="recolor" type="button">SATURATE IMAGE</button>
<div>0<input id="grayscalerangeinput" type="range" min="0" max="10" value="10">100</div>

Working example here.

Arman Ozak
  • 2,304
  • 11
  • 11