Change SVG stroke on path using jQuery
I have set the SVG image as the background of the div. Now I want to change the progress of a specific path using jQuery every x seconds. I saw an example ( click me ) where this is mostly done.
This is my jQuery:
$(document).ready(function(){
var _currStroke = 'ffa500';
var svg = '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/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 make it go very quickly:
- I defined the stroke color to start with (_currStroke = 'ffa500')
- I am coding svg and setting it as the background of my nav
- Note the svg path: it has an id (# 'outline_path) and a style:
style="stroke:'+_currStroke+'; transition: stroke .4s ease; opacity: 0.5"
- Store the current color of the stroke in a variable (currentColor)
- call the changeStrokeColor function every
changeTimeInMS
- seconds - store return value of changeStrokeColor in variable (lastIndex)
- changeStrokeColors expects two variables: the current stroke color and the last index (maybe the first call to changeStrokeColors? lastIndex hasn't been declared yet, but I can't set it to 0, for example, because then it will be reset every x seconds)
- Iterating through a set of colors; if currentColor is equal to the index we are currently finding, pass it (
return true
) and continue: - find the path with id
outline_path
and change the stroke to the element we are currently finding in our iteration - Also change the color of the navigation frame to this color
- Increment lastIndex and return it
I can change color with var _currStroke but the "do-it-every-x-seconds" thing doesn't work at all. Please note that I am new to JS (and SVG). Any help is appreciated.
I made a CodePen to illustrate: CodePen
source to share
There are so many problems in your code,
I will try to cover them:
-
You are using an HTML element
<nav>
, but in the code you are trying to target some ID : The$("#nav").css(
correct selector you want is actually the one you have already used in your code and it is$("nav")
-
converting your SVG element to base64 image data .
After it is converted to an image, it is no longer a living object ** that you can manipulate, so basically you will need to rebuild the new image with different colors before using it. Otherwise, you can learn how to use SVG<pattern>
. -
You are setting invalid colors in your array is
'32cd32'
not a HEX color , but'#32cd32'
- -
$("outline_path")
is not an identifier selector see *; 1 but anyway it's too late to hover it over so that your SVG becomes the c & bull; base64 data image . 2 -
No need to remember the color
lastIndex
and iterate over your Array colors inside again$.each
, just use the array counter pointer, increment that counter and use the Reminder Operator% of Total Colors to increment the counter cyclically:++counter%totColors
-
.attr('style', "stroke:'+this+'")
- invalid string + var concatenation. It should be like:,.attr('style', "stroke:'"+ this +"'")
where everything inside the duplicates is a string, and everything outside is+
concatenated variables. -
You will need to pre-create all of your images to prevent empty spaces (generated image) after the spacing starts ticking.
-
You will not be able to set
transition: stroke .4s ease;
on an image. I'm sorry. You might want to learn some other tricks in bg (2 elements) fading. example1 example2 example3 -
Don't re-create variables within the interval. Make them Global instead.
-
Create a function that will return a new image.
Here's my attempt to rebuild the whole thing following your idea and source 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.org/2000/svg" xmlns:xlink="http://www.w3.org/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);
});
source to share