Jump to content
GreenSock

swampthang

Multi-colored lines in SVG

Recommended Posts

I'm wondering if anyone has managed to animate multiple SVG stroke colors - on the same stroke, at the same time. What I'm supposed to try and emulate is something like this After Effects plugin...

 

https://videohive.net/item/animated-stroke-font/11905683?s_rank=3

 

After reading this:

https://jakearchibald.com/2013/animated-line-drawing-svg/

 

And looking at the first example here http://greensock.com/docs/#/HTML5/GSAP/Plugins/DrawSVGPlugin/

 

It seems like there should be a way of applying an array of colors to a stroke in opposite stroke-dasharray/stroke-dashoffset settings - like "80% 20%" in one and "20% 80%" in another. If it's not possible to apply more than 1 color to different offsets of a single stroke, I guess it would require making as many duplicates of the strokes as there are colors in the array and then applying those opposing stroke color draws.

 

Anyone ever manage to do this kind of thing?

See the Pen mEqrjE by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

Hi swampthang, I think you have a few options to create this.

 

Check out this video by Chris Gannon where he explains how to animate a gradient:

 

Create a Looping Gradient Using SVG Filters & Patterns

 

Maybe that technique might help.

 

Or you can setup multiple element and animate them separately like I did on this

See the Pen PPwqMN by ihatetomatoes (@ihatetomatoes) on CodePen

.

 

Let us know which technique you have used for the effect.

 

Thanks

Petr

  • Like 2
Link to comment
Share on other sites

Hey, Petr! Thanks so much for the links. Just watched the Chris Gannon video.

Btw, I'm one of your customers. I purchased one of your animation packages. Good job on those! 

 

So, I've got to figure out how to dynamically create the pattern filter or multiple copies in order to do this because I need to be able to do it when a new SVG line drawing is dropped in. In other words, I won't have the convenience of being able to prepare all the elements, etc. 

 

This gives me a couple of things to think about though. Thanks again.

Link to comment
Share on other sites

Here you go. Each color has to be a separate element, but not every segment, so you can create a loop.

See the Pen 107e1cacbe5a2ace8a24e9796c30355c?editors=0010 by osublake (@osublake) on CodePen

 

A gradient won't conform to the shape of path, but you can fabricate one using that same technique! 

See the Pen 5a3c63e172d177f9c1b257ceba37378b?editors=0010 by osublake (@osublake) on CodePen

  • Like 10
Link to comment
Share on other sites

Wow, Blake. That's pretty crazy.

  • Like 1
Link to comment
Share on other sites

Wow, Blake, you've done it again! These are awesome!!  :D

Link to comment
Share on other sites

Started playing with Blake's awesome code invention (it truly is genius) and here's what I've got so far. Blake's was being applied to a single path as a demo and I needed to have this apply to any number of paths as well as lines, polygons, etc. So, needed to loop through each and add some other methods for getting the length since path is the only thing that has a getTotalLength() method. So far, all I've added are lines, rect's and polygon's but here's an example... 

 

See the Pen wWPRzW by swampthang (@swampthang) on CodePen

 

I think my one main fear is this beginning to tax the DOM.

 

Oh, and I randomized the colors array to keep it from looking the same on every line.

Link to comment
Share on other sites

Started playing with Blake's awesome code invention (it truly is genius) and here's what I've got so far. Blake's was being applied to a single path as a demo and I needed to have this apply to any number of paths as well as lines, polygons, etc. So, needed to loop through each and add some other methods for getting the length since path is the only thing that has a getTotalLength() method. So far, all I've added are lines, rect's and polygon's but here's an example... 

 

See the Pen wWPRzW by swampthang (@swampthang) on CodePen

 

I think my one main fear is this beginning to tax the DOM.

 

Oh, and I randomized the colors array to keep it from looking the same on every line.

 

That's cool!  It doesn't seem to work in Safari though, at least not on my Mac or iPhone.  The hands just stay gray.

Link to comment
Share on other sites

Hmmm, yea, it looks like it's a javascript version support issue in Safari. Here's the error:

Unexpected token '>'

It's on this line where the ```=>``` occurs. Safari doesn't yet support the arrow function. Compatibility table.

var rgb = lerpColors(colors, amt).map(color => Math.round(color));

Btw, the reason I'm not as concerned about Safari is I'm doing this for a desktop app in Electron and Electron is packaged with the latest version of Chromium. So that's the only 'browser' I have to deal with. Found this, though. It might help...

 

https://github.com/paulmillr/es6-shim

Link to comment
Share on other sites

Ok, so I've added path, line, polyline, polygon, ellipse, circle, rect to the array of selectors. Had to go back and look up how to get the circumference of an ellipse. Turns out it's not that perfect but it's good enough! Here's, I guess you could call, an almost beta version...

 

See the Pen bZYkKG by swampthang (@swampthang) on CodePen

  • Like 1
Link to comment
Share on other sites

@swampthang, great to see that you've made your almost beta.

 

And thanks heaps for signing up to my workshop! You are awesome!

  • Like 3
Link to comment
Share on other sites

Thanks you, Petr. Yea, working with these libraries is a blast!

Link to comment
Share on other sites

That's cool!  It doesn't seem to work in Safari though, at least not on my Mac or iPhone.  The hands just stay gray.

 

Yeah, like swampthing pointed out, it's because of the arrow function. There's nothing really special about it. It's just a shorthand way to write a function. The only difference is using 'this' inside an arrow function is not the same as regular function.

// ES6...
var rgb = lerpColors(colors, amt).map(color => Math.round(color));

// Without...
var rgb = lerpColors(colors, amt).map(function(color) { return Math.round(color); });

On CodePen, if somebody is using a compiler like Babel, TypeScript, CoffeeScript, etc, you can get a clean version of the code by adding .js to the end of the url. If there's a question mark in the url, just remove that and anything else that follows.

// If the url looks like this...

// Change it to this...
Link to comment
Share on other sites

Here's some tips about creating gradients...

 

For getting the totalLength, GSAP can help you out! Just do this...

MorphSVGPlugin.convertToPath("circle, rect, ellipse, line, polygon, polyline");

For paths that are closed using the "z" command, you might end up with something that looks like the star on the left.

 

a0FalkZ.png

 

To fix this, you need to replace the "z" command with a line that goes to the starting coordinates in the move command. If you need help getting the coordinates, the MorphSVGPlugin can help you out again! Here's a post where I show how you can get the values from a path string, and how to rebuild it. The starting coordinates would be the first 2 numbers.

http://greensock.com/forums/topic/14129-morphsvg-change-start-and-end-point/?p=59864

 

The path that is being cloned should be inside defs tags, or hidden/removed after creating the gradient so it won't be visible as you might see parts of it showing up behind the gradient. 

 

The "total" variable refers to the number of stripes in the gradient. Lowering this number can make the stripes more noticeable on larger shapes, but it will improve the performance.

 

The "space" variable is kind of like an overlap value between the different stripes. If it's set to 0, you might see a tiny gap between some of the stripes. A value of 1 or 2 can usually eliminate any gaps.

 

To make the gradient blend between the end and the start, the last color should be the same as the first. After you randomize the colors, you can do this to copy the first color...

colors.push(colors[0].slice(0));

Here's a fork of your second demo using some of these tips. I didn't do the closed path fix, but you can see that it performs much better, while eliminating half of your code.

See the Pen NAXPqN?editors=0010 by osublake (@osublake) on CodePen

  • Like 1
Link to comment
Share on other sites

Blake, that's so helpful, man. Thanks! It was fun scouring the Internet for the formula for the circumference of an Ellipse though. ;-)

Link to comment
Share on other sites

Wow, Blake. Thanks again!

Link to comment
Share on other sites

Blake, that's so helpful, man. Thanks! It was fun scouring the Internet for the formula for the circumference of an Ellipse though. ;-)

 

I never thought about that before, but it doesn't make any sense how you can get the length of the most complicated shape, a path, but not something simple like an ellipse.

 

Here's a demo I made earlier that repeats a gradient 2 times. 

See the Pen jAYbaE?editors=0010 by osublake (@osublake) on CodePen

 

The star in that image is made by repeating the gradient 6 times, and requires a lot of stripes to make it smooth. Definitely not something that would be good for animation.

  • Like 1
Link to comment
Share on other sites

Wow, that's pretty crazy. You notice how the lines overlap as they cycle through? Like the z value is changing.

 

I wonder what it would take to add the ability to draw these in as they animate the colors and stop once it's all drawn in? I didn't even know where to start on this...

 

See the Pen wWPRzW?editors=1010 by swampthang (@swampthang) on CodePen

Link to comment
Share on other sites

This really isn't setup to work like the DrawSVG plugin. I think you'll always have one segment visible, like this...

See the Pen 76e18e4af910e7a2d46174bb52dce161?editors=0010 by osublake (@osublake) on CodePen

 

This thread has some stuff in it that might be of use. Carl has a really good dash demo in there, and I made a little utility function to calculate a dash array. You might be able to use that to get your values, but I can't say for sure. Again, you'll probably end up with some part of a segment showing.

http://greensock.com/forums/topic/12201-draw-svg-plugin-to-animate-a-dashed-line/

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×