Jump to content
Search Community

Animated handwriting not working as expected

blastergod test
Moderator Tag

Recommended Posts

 Hello,

I am considering buying GASP but I am trying it first.

I want to simulate a hand drawing effect on a more complex path.

I modified the hand drawing example, but unfortunately the results are not what I expect, and I don't know if I am doing something wrong.

You can check my codepen at:

 

Any help is appreciated.

First, I don't know exactly what mistake I made that the hand is not transparent background.

The problem is that as you can see, the svg shape is drawing faster than the hand is moving, with multiple points starting at the same time.

 

Can this be solved? So the shape is drawn by the hand 100% ?

 

Thank you!

Vlad

See the Pen MWzRYWM by Cristian-M (@Cristian-M) on CodePen

Link to comment
Share on other sites

 

Welcome to the GSAP forum @blastergod

 

3 hours ago, blastergod said:

First, I don't know exactly what mistake I made that the hand is not transparent background.

 

That is the case because by default it has a black fill applied; it's an svg-thing. The easy fix is setting the fill to none, e.g. in your CSS.
 

#hand {
  fill: none
}

 

The other part of your question will be a bit more complex to solve than that, I'm afraid.

 

I think the reason why it doesn't work as you expect is because you are targetting a compound path and DrawSVG will start drawing each line contained within that compound path right away, while the motionpathPlugin will consider each line one after the other - and I think that is how they are supposed to be working (I might be wrong of course).

 

So my suggestion would be to clean that compound path out and make every path you want to be animated its own path element. When animating anything, the most important thing is preparation of a proper setup / your assets before doing anything animation wise; so you will make it easier for yourself to see through what it is you are attempting to do.

Since your SVG is rather complex and I don't have the time to dig into it right now, instead I prepared an example of my own to show you one way for how you can tween the drawing of your paths and an element following that line to be drawn in unison.

 

This example uses a timeline, that first has a tween drawing each of the letters, staggering by a bit more than its duration, so in between each letter there is a bit of a pause. Then forEach of the letters I added a motionPath-tween to the timeline, with the same duration and ease as the drawing-tween has.

To specify on when to start each of those motinpath-tweens, I make use of the position parameter, set to the index of each letter mutiplied by the 3.3 used as the stagger in the drawing-tween to make sure the motionpath-tweens start at the same time as their respective letter starts being drawn.

 

const letters = gsap.utils.toArray('path:not(#pen)')

const tl = gsap.timeline()

tl.fromTo(letters, {  
  drawSVG: "0% 0%"  
}, {  
  duration: 3,
  stagger: 3.3,  
  drawSVG: "0% 100%" ,
  ease: 'none'
})

letters.forEach(function(path, index) {
      
    tl.to('#pen', {

      motionPath: {
        path: letters[index],
        align: letters[index],
        alignOrigin: [0, 1.0],
        autoRotate: false,
        start: 0.0,
        end: 1.0,
      },

      duration: 3,
      ease: 'none'

    }, index * 3.3) // <--- position parameter
  
})

 

I hope this can help get you in the right direction. Happy tweening.

 

See the Pen NWEmPVK by akapowl (@akapowl) on CodePen


 

  • Like 3
Link to comment
Share on other sites

Thank you for the explanation.

I understand your point, and it makes sense.

 

What I am trying to do is see if I can "simulate" hand drawing animation over any SVG path (without preparing it).

Even if it does not follow the outline perfect, but simply reveals part of the svg in an animation. Speeding up the animation will make it look like the shape is drawn by hand.

I want to know if that is possible, because I am using a tool to convert BMP to SVG paths. The BMPs are white and black shapes like the ones you see in my example.

The tool then converts the images to svg paths and they look perfect.

I just need a solution to draw them part by part, to simulate a hand drawing.

 

Thank you

Vlad

Link to comment
Share on other sites

Hi,

 

As Paul already mentioned the way the paths are presented in SVG is important. Compound paths, clipped paths and other things can complicate the way your animation with either DrawSVG and/or MorphSVG plugins will behave. SVG is not something I have a ton of knowledge but when I work with SVG I always use this tool in order to remove all the things that are not really necessary:

https://jakearchibald.github.io/svgomg/

 

Also you could benefit from this tutorials by @PointC:

https://www.motiontricks.com/better-svg-exports-make-animations-easier/

https://www.motiontricks.com/animated-handwriting-effect-part-1/

https://www.motiontricks.com/animated-handwriting-effect-part-2/

https://www.motiontricks.com/svg-calligraphy-handwriting-animation/

 

Hopefully this helps.

Happy Tweening!

  • Like 3
Link to comment
Share on other sites

  • 1 month later...

Hello,

I managed to get it working by using the SVG masked, and revealing it using the stroke animation.

 

The only problem I am facing, is that the "pen" that should follow the lines is not showing. Probably because the stroke animation is used as the mask.

How can I fix this? Any ideas?

See the Pen poqRQRz by Cristian-M (@Cristian-M) on CodePen

 

Thanks!

Vlad

Link to comment
Share on other sites

Hey, 

 

Imagine a multi-layered painting.

First you paint the background, then comes the apple and after that you add shading and contours (3 layers).

In svg it's basically the same, but the first element you paint is the one in the background and the last one is on top of the others.
So basically the hand is the background, and the other paths are the shading and contours.

 

If you want your hand to be on top, add it to the end of the svg structure.

 

Quote

Elements in an SVG document fragment have an implicit drawing order, with the first elements in the SVG document fragment getting "painted" first. Subsequent elements are painted on top of previously painted elements. source: w3c

 

Hope this helps and good luck with your project

By the way, the animation looks amazing, great job!

 

EDIT:

Sorry, I was using Chrome where the pen was showing and assumed you meant the pen was behind the drawing (at least a other problem was fixed :)). 

 

EDIT 2:

This got me thinking:

Quote

The <defs> element is used to store graphical objects that will be used at a later time. Objects created inside a <defs> element are not rendered directly. To display them you have to reference them (with a <use> element for example). source

and since the pen did not move at all in Firefox, but was movable by transforms I though that the referencing of the paths in the Js was not correct (at least for the hand).

 

So I tried this and it worked (not sure if the pen is always in the right position/path).

var maskPaths = document.getElementById("maskReveal").getElementsByTagName("path");
for (let i = 1; i < paths.length; i++) {
      tl.add("path"+i);
      tl.to(paths[i], {duration: 0.75, drawSVG:true}, "path"+i);
      tl.to("#hand", {duration: 0.75, motionPath:{path:maskPaths[i], align:maskPaths[i]} }, "path"+i);
}

I'm not sure if this is the right approach/direction, but at least it "works" (even if the timing/order of the animation/paths is off) and might provide some information for the next person who wants to help.

  • Like 1
Link to comment
Share on other sites

Hello

This did not work for me. I was using the exact code you wrote, or am I mistaken?

I used

var elem=document.getElementById("theMask");
var paths = elem.getElementsByTagName("path");

And then:

for (let i = 1; i < paths.length; i++) {
      tl.add("path"+i);
      tl.to(paths[i], {duration: 0.75, drawSVG:true}, "path"+i);
      tl.to("#hand", {duration: 0.75, motionPath:{path:paths[i], align:paths[i]} }, "path"+i);
}

And it does not work. I tried adding the pen <g> at the end, made no difference.

Link to comment
Share on other sites

Okay, remember SVGs are not really my area, so you'll have to tell me if it works as intended or not (although my help reaches its limits). Since I don't know if the order inside <defs><mask> is important. 

 

Just replace your loop (line 26) with my code above and you'll find that the pen moves again, but the animation order is wrong because the paths don't match.

To fix this, I copied the paths inside maskReveal into a code editor and used the Find and Replace function.
Here is my search regex: style="fill.*; stroke:none" in case you want to try it yourself.
After this step, you will get the paths that you can copy and paste into the <mask></mask> (without the styling) element.

 

See the Pen YzdZzRv by alig01 (@alig01) on CodePen

 

But like I said I dont know if the order inside <mask></mask> (since I never had to use them :unsure:) is important, but I couldn't see at least a difference. 

 

Hope this somehow helps and is a step in the right direction 

  • Like 1
Link to comment
Share on other sites

Thank you! It seems it works. I understand now what you did, you took the motion path from maskreveal not from the mask.

I will try to work on the mask a bit. I am doing this programatically.

The problem was that drawing the image (without mask) was outlined, so the end result was not good.

I tried to remove some paths and see if I get a better result, but it seems I didn't.

I will do more digging.

 

  • Like 1
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.
×
×
  • Create New...