admin管理员组

文章数量:1023738

I've set my SVG image as the background of a div. Now I want to change the stroke of a specific path with jQuery every x seconds. I've seen an example (click me) where this is basically done.

This is my jQuery so far:

$(document).ready(function(){

  var _currStroke = 'ffa500';

  var svg = '<svg xmlns="" xmlns:xlink="" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5" /> </svg>';

  var encoded = window.btoa(svg);
  $("nav").css("background", "url(data:image/svg+xml;base64,"+encoded+")");

  /* change stroke color every x seconds (atm: 3) */
  var changingTimeInMS = 3000;
  var currentColor = $("outline_path").attr('stroke');
  setInterval(function() {    

    var lastIndex = changeStrokeColor(currentColor, lastIndex);

  }, changingTimeInMS);

});

function changeStrokeColor(currentColor, lastIndex) {

    var colors = ['32cd32',  /* limegreen */
                '00ffff',  /* cyan */
                'ffa500',  /* orange */
                'ffffff']; /* white */

    $.each(colors, function(lastIndex) {
      if(colors[lastIndex] == currentColor) {
          return true;
      }
      $("#outline_path").attr('style', "stroke:'+this+'");
      $("#nav").css('border-color', this);

      lastIndex++;
      return lastIndex;
});

}

So let's go through it real quick:

  1. I defined a stroke color to start with (_currStroke = 'ffa500')
  2. I encode the svg and set it as the background of my nav
  3. Please notice the svg path: it has an id (#'outline_path') and a styling: style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
  4. Save the current stroke color in a variable (currentColor)
  5. call changeStrokeColor-function every changeTimeInMS - seconds
  6. save the return value of changeStrokeColor in a variable (lastIndex)
  7. changeStrokeColors expects two variables: the current color of the stroke and the last index (is the first call of changeStrokeColors even possible? lastIndex is not declared yet but I can't set it to 0 for example because then it would be resetted every x seconds)
  8. Iterate through the colors-array; if the currentColor is equal to the index we are at the moment, skip it (return true) and continue with:
  9. search for the path with the id outline_path and change the stroke to the element we are at right now in our iteration
  10. Also change the nav border color to that color
  11. increment lastIndex and return it

I can change the color with changing var _currStroke but the 'do-it-every-x-seconds'-thing is not working at all. Please note that I'm a beginner in JS (and SVGs). Any help is appreciated.

I made a CodePen to illustrate: CodePen

I've set my SVG image as the background of a div. Now I want to change the stroke of a specific path with jQuery every x seconds. I've seen an example (click me) where this is basically done.

This is my jQuery so far:

$(document).ready(function(){

  var _currStroke = 'ffa500';

  var svg = '<svg xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5" /> </svg>';

  var encoded = window.btoa(svg);
  $("nav").css("background", "url(data:image/svg+xml;base64,"+encoded+")");

  /* change stroke color every x seconds (atm: 3) */
  var changingTimeInMS = 3000;
  var currentColor = $("outline_path").attr('stroke');
  setInterval(function() {    

    var lastIndex = changeStrokeColor(currentColor, lastIndex);

  }, changingTimeInMS);

});

function changeStrokeColor(currentColor, lastIndex) {

    var colors = ['32cd32',  /* limegreen */
                '00ffff',  /* cyan */
                'ffa500',  /* orange */
                'ffffff']; /* white */

    $.each(colors, function(lastIndex) {
      if(colors[lastIndex] == currentColor) {
          return true;
      }
      $("#outline_path").attr('style', "stroke:'+this+'");
      $("#nav").css('border-color', this);

      lastIndex++;
      return lastIndex;
});

}

So let's go through it real quick:

  1. I defined a stroke color to start with (_currStroke = 'ffa500')
  2. I encode the svg and set it as the background of my nav
  3. Please notice the svg path: it has an id (#'outline_path') and a styling: style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
  4. Save the current stroke color in a variable (currentColor)
  5. call changeStrokeColor-function every changeTimeInMS - seconds
  6. save the return value of changeStrokeColor in a variable (lastIndex)
  7. changeStrokeColors expects two variables: the current color of the stroke and the last index (is the first call of changeStrokeColors even possible? lastIndex is not declared yet but I can't set it to 0 for example because then it would be resetted every x seconds)
  8. Iterate through the colors-array; if the currentColor is equal to the index we are at the moment, skip it (return true) and continue with:
  9. search for the path with the id outline_path and change the stroke to the element we are at right now in our iteration
  10. Also change the nav border color to that color
  11. increment lastIndex and return it

I can change the color with changing var _currStroke but the 'do-it-every-x-seconds'-thing is not working at all. Please note that I'm a beginner in JS (and SVGs). Any help is appreciated.

I made a CodePen to illustrate: CodePen

Share Improve this question edited Sep 28, 2014 at 19:43 Roko C. Buljan 207k41 gold badges328 silver badges340 bronze badges asked Sep 28, 2014 at 18:03 sqesqe 1,7164 gold badges23 silver badges38 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

Working live demo

So many issues in your code,
I'll try to cover them all:

  1. You use a HTML element <nav> but in your code you're trying to target some ID: $("#nav").css( The right selector you want is actually the one you already used in your code, and that's $("nav")

  2. You're converting your SVG element to base64 data-image.
    Once it's converted to image it's no more a living Object** you can manipulate, so basically you'll need to re-build a new image with different colors before using it. Otherwise you can explore how to use SVG <pattern>.

  3. You're setting invalid colors in your array '32cd32' is not a HEX color, while '#32cd32' is.

  4. $("outline_path") is not an ID selector see•1, but in any case it's too late to target it cause your SVG is now a base64 data image see•2.

  5. There's no need to remember the lastIndex color and iterate all over again your colors Array inside $.each, simply use an Array Counter pointer, increate that counter instead and use the Reminder Operator % against the total number of colors to loop your incremented Counter: ++counter%totColors

  6. .attr('style', "stroke:'+this+'") is incorrect string + var concatenation. Should be like: .attr('style', "stroke:'"+ this +"'") where all inside the doubles is string, and outside are + concatenated variables.

  7. You'll need to pre-create all your images, to prevent blank gaps (image being created) once the interval starts ticking.

  8. You'll not be able to set transition: stroke .4s ease; to an image. Sorry. You might want to explore some other tricks in fading a bg image (2 elements involved). example1 example2 example3

  9. Don't recreate your variables all over again inside an interval. Make them Global instead.

  10. Create a function that will return the new image.


Here's my attempt to rebuild it all following your idea and initial code:

var $nav = $("nav"), // Cache your selectors
  colors = [
  '#00ffff',  // cyan
  '#32cd32',  // limegreen
  '#ffa500',  // orange
  '#ffffff',  // white
  'red'
  ], 
  totColors = colors.length, // How many colors?
  counter = 0;               // Colors Array loop counter

function newSvg(co){
  var svg = '<svg xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+ co +'; opacity: 0.5" /> </svg>';
  return "data:image/svg+xml;base64,"+ window.btoa(svg);
}

function changeStrokeColor() {
  var co = colors[++counter%totColors]; // Increase and Loop colors
  $nav.css({
    borderColor: co,
    background : "url("+ newSvg(co) +")"
  });
}  

for(var i=0; i<totColors; i++){ // Preload all backgrounds
  var img = new Image();
  img.src = newSvg(colors[i]);
}

$(function(){ // DOM ready
  $nav.css("background", "url("+ newSvg( colors[counter] ) +")" );
  setInterval(changeStrokeColor, 1000);
});

I've set my SVG image as the background of a div. Now I want to change the stroke of a specific path with jQuery every x seconds. I've seen an example (click me) where this is basically done.

This is my jQuery so far:

$(document).ready(function(){

  var _currStroke = 'ffa500';

  var svg = '<svg xmlns="" xmlns:xlink="" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5" /> </svg>';

  var encoded = window.btoa(svg);
  $("nav").css("background", "url(data:image/svg+xml;base64,"+encoded+")");

  /* change stroke color every x seconds (atm: 3) */
  var changingTimeInMS = 3000;
  var currentColor = $("outline_path").attr('stroke');
  setInterval(function() {    

    var lastIndex = changeStrokeColor(currentColor, lastIndex);

  }, changingTimeInMS);

});

function changeStrokeColor(currentColor, lastIndex) {

    var colors = ['32cd32',  /* limegreen */
                '00ffff',  /* cyan */
                'ffa500',  /* orange */
                'ffffff']; /* white */

    $.each(colors, function(lastIndex) {
      if(colors[lastIndex] == currentColor) {
          return true;
      }
      $("#outline_path").attr('style', "stroke:'+this+'");
      $("#nav").css('border-color', this);

      lastIndex++;
      return lastIndex;
});

}

So let's go through it real quick:

  1. I defined a stroke color to start with (_currStroke = 'ffa500')
  2. I encode the svg and set it as the background of my nav
  3. Please notice the svg path: it has an id (#'outline_path') and a styling: style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
  4. Save the current stroke color in a variable (currentColor)
  5. call changeStrokeColor-function every changeTimeInMS - seconds
  6. save the return value of changeStrokeColor in a variable (lastIndex)
  7. changeStrokeColors expects two variables: the current color of the stroke and the last index (is the first call of changeStrokeColors even possible? lastIndex is not declared yet but I can't set it to 0 for example because then it would be resetted every x seconds)
  8. Iterate through the colors-array; if the currentColor is equal to the index we are at the moment, skip it (return true) and continue with:
  9. search for the path with the id outline_path and change the stroke to the element we are at right now in our iteration
  10. Also change the nav border color to that color
  11. increment lastIndex and return it

I can change the color with changing var _currStroke but the 'do-it-every-x-seconds'-thing is not working at all. Please note that I'm a beginner in JS (and SVGs). Any help is appreciated.

I made a CodePen to illustrate: CodePen

I've set my SVG image as the background of a div. Now I want to change the stroke of a specific path with jQuery every x seconds. I've seen an example (click me) where this is basically done.

This is my jQuery so far:

$(document).ready(function(){

  var _currStroke = 'ffa500';

  var svg = '<svg xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5" /> </svg>';

  var encoded = window.btoa(svg);
  $("nav").css("background", "url(data:image/svg+xml;base64,"+encoded+")");

  /* change stroke color every x seconds (atm: 3) */
  var changingTimeInMS = 3000;
  var currentColor = $("outline_path").attr('stroke');
  setInterval(function() {    

    var lastIndex = changeStrokeColor(currentColor, lastIndex);

  }, changingTimeInMS);

});

function changeStrokeColor(currentColor, lastIndex) {

    var colors = ['32cd32',  /* limegreen */
                '00ffff',  /* cyan */
                'ffa500',  /* orange */
                'ffffff']; /* white */

    $.each(colors, function(lastIndex) {
      if(colors[lastIndex] == currentColor) {
          return true;
      }
      $("#outline_path").attr('style', "stroke:'+this+'");
      $("#nav").css('border-color', this);

      lastIndex++;
      return lastIndex;
});

}

So let's go through it real quick:

  1. I defined a stroke color to start with (_currStroke = 'ffa500')
  2. I encode the svg and set it as the background of my nav
  3. Please notice the svg path: it has an id (#'outline_path') and a styling: style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
  4. Save the current stroke color in a variable (currentColor)
  5. call changeStrokeColor-function every changeTimeInMS - seconds
  6. save the return value of changeStrokeColor in a variable (lastIndex)
  7. changeStrokeColors expects two variables: the current color of the stroke and the last index (is the first call of changeStrokeColors even possible? lastIndex is not declared yet but I can't set it to 0 for example because then it would be resetted every x seconds)
  8. Iterate through the colors-array; if the currentColor is equal to the index we are at the moment, skip it (return true) and continue with:
  9. search for the path with the id outline_path and change the stroke to the element we are at right now in our iteration
  10. Also change the nav border color to that color
  11. increment lastIndex and return it

I can change the color with changing var _currStroke but the 'do-it-every-x-seconds'-thing is not working at all. Please note that I'm a beginner in JS (and SVGs). Any help is appreciated.

I made a CodePen to illustrate: CodePen

Share Improve this question edited Sep 28, 2014 at 19:43 Roko C. Buljan 207k41 gold badges328 silver badges340 bronze badges asked Sep 28, 2014 at 18:03 sqesqe 1,7164 gold badges23 silver badges38 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

Working live demo

So many issues in your code,
I'll try to cover them all:

  1. You use a HTML element <nav> but in your code you're trying to target some ID: $("#nav").css( The right selector you want is actually the one you already used in your code, and that's $("nav")

  2. You're converting your SVG element to base64 data-image.
    Once it's converted to image it's no more a living Object** you can manipulate, so basically you'll need to re-build a new image with different colors before using it. Otherwise you can explore how to use SVG <pattern>.

  3. You're setting invalid colors in your array '32cd32' is not a HEX color, while '#32cd32' is.

  4. $("outline_path") is not an ID selector see•1, but in any case it's too late to target it cause your SVG is now a base64 data image see•2.

  5. There's no need to remember the lastIndex color and iterate all over again your colors Array inside $.each, simply use an Array Counter pointer, increate that counter instead and use the Reminder Operator % against the total number of colors to loop your incremented Counter: ++counter%totColors

  6. .attr('style', "stroke:'+this+'") is incorrect string + var concatenation. Should be like: .attr('style', "stroke:'"+ this +"'") where all inside the doubles is string, and outside are + concatenated variables.

  7. You'll need to pre-create all your images, to prevent blank gaps (image being created) once the interval starts ticking.

  8. You'll not be able to set transition: stroke .4s ease; to an image. Sorry. You might want to explore some other tricks in fading a bg image (2 elements involved). example1 example2 example3

  9. Don't recreate your variables all over again inside an interval. Make them Global instead.

  10. Create a function that will return the new image.


Here's my attempt to rebuild it all following your idea and initial code:

var $nav = $("nav"), // Cache your selectors
  colors = [
  '#00ffff',  // cyan
  '#32cd32',  // limegreen
  '#ffa500',  // orange
  '#ffffff',  // white
  'red'
  ], 
  totColors = colors.length, // How many colors?
  counter = 0;               // Colors Array loop counter

function newSvg(co){
  var svg = '<svg xmlns="http://www.w3/2000/svg" xmlns:xlink="http://www.w3/1999/xlink" version="1.1"  x="0px" y="0px" width="60px" height="60px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"> <path d="M69.527,2H29.971L2,29.971v39.558L29.971,97.5h39.558L97.5,69.527V29.972L69.527,2z M95.625,68.898L68.898,95.625H31.101  L4.375,68.898V31.516v-0.414L31.102,4.375h37.796l26.728,26.727L95.625,68.898L95.625,68.898z"/> <path d="M68.07,6.375H31.93L6.375,31.93v36.142L31.93,93.626h36.142L93.625,68.07V31.93L68.07,6.375z" id="outline_path" style="stroke:'+ co +'; opacity: 0.5" /> </svg>';
  return "data:image/svg+xml;base64,"+ window.btoa(svg);
}

function changeStrokeColor() {
  var co = colors[++counter%totColors]; // Increase and Loop colors
  $nav.css({
    borderColor: co,
    background : "url("+ newSvg(co) +")"
  });
}  

for(var i=0; i<totColors; i++){ // Preload all backgrounds
  var img = new Image();
  img.src = newSvg(colors[i]);
}

$(function(){ // DOM ready
  $nav.css("background", "url("+ newSvg( colors[counter] ) +")" );
  setInterval(changeStrokeColor, 1000);
});

本文标签: javascriptChange SVG stroke on path with jQueryStack Overflow