Jump to content
Search Community

Animate on Bezier path from mouse positions

cemycc test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Hello,

 

I have a div that have dimensions 1024x768 and position absolute on it. On that div I have one element with position absolute.

When I move the element inside the div I save his position at every move of mouse then with this positions I want to animate the element on the path recorded by mouse positions.

Also, when I move the mouse with the element I draw a path on canvas with ctx.quadraticCurveTo function using the points that I save from mouse move.

 

The problem is when i use the bezier plugin with TweenMax the element change the initial position from the canvas path because for animation is used -webkit-transform: matrix(1,0,0,1,560,230).

Also, I am using the Bezier plugin with the type cubic because this was the only type that can make almost correct animations.

 

If someone have other sugestions how can I do this ? Because for some paths I save allot of points and maybe there is another method ? I was looking at bezierThrough() function for drawing the path on canvas but I don't know what function I will need to use.

 

Thanks in advance for your help.

Link to comment
Share on other sites

Hi,

 

As for a better method I can't think of one.

 

Regarding the initial point that could be because the initial position is set with top and left CSS properties which consider the top-left corner as the origin point; meanwhile transforms, by default, use the transform origin 50% 50%, so for the first point your element has to translate half it's width and height to get into the right  position. What you could try is use a set instance to translate your element to x:0 and y:0 or translate it to half it's width and half it's height:

var element = $("#elementID"),
    elementWidth = element.outerWidth(),
    elementHeight = element.outerHeight();

//Initial position set to x:0 and y:0
TweenMax.set(element, {x:0, y:0});

//initial position set to half height and width
TweenMax,set(element, {x:elementWidth/2, y:elementHeight/2});

And finally another choice could be set half the element height and width as the initial point of the bezier path, like that the path animation will start at the point where the element is right now:

var element = $("#elementID"),
    elementWidth = element.outerWidth(),
    elementHeight = element.outerHeight(),
    bezierStart = {x:elementWidth/2, y:elementHeight/2};//start point of the bezier path

Hope this helps,

Cheers,

Rodrigo.

  • Like 1
Link to comment
Share on other sites

If you want to feed a bunch of points to a method and have it plot a nice smooth bezier curve through it and spit back cubic bezier data, that's exactly what the BezierPlugin.bezierThrough() method is for. http://api.greensock.com/js/com/greensock/plugins/BezierPlugin.html#bezierThrough()

 

Then you can use that data to draw stuff on your canvas because you'll have the raw cubic bezier data (you can also get quadratic bezier data if you prefer). The docs have the details. 

 

If you're still having trouble, please create a super simple codepen example (or jsfiddle) so we can see what's happening (again, the simpler the better please). 

Link to comment
Share on other sites

Thank you for your reply.

@rhernando I still have the same problem, I will write a codepan as soon as I am back home from work.

 

Also, I was thinking and reading some articles on internet, will be better if I have drag the elements with translate css property rather with top left ?

Also on the div I will need to rotate it and change is size. Rotation and size will be also animated on the bezier path. :)

Link to comment
Share on other sites

Thank you again for the fast reply.

I got some free time and I wrote a codepan. 

See the Pen tgjlH by anon (@anon) on CodePen

For the box element you will see that is position at 185,164 but when the animation start he goes down even if the positions on points array are similar

 

The position on points array got generated from mouse moves on my site ( I can't write the entire code because I am using coffescript ) I have wrote only the part with the problem.

Link to comment
Share on other sites

Hi,

 

Well I'm not sure if I understand this totally but here's what I think could be happening.

 

You set your element's initial position in your CSS with a top and left value. Then when the page renders for the first time the element is at that position, but at that point, before the animation starts the element's x and y coordinates (for the transform matrix) are both zero. The bezier path doesn't begins at {x:0, y:0}, so in the first run your element has to translate to that point and then it goes through the rest of the bezier path.

 

So a question: Is that initial translation, from the CSS set position to the initial bezier point, the problem/behaviour you're trying to avoid?.

 

If it is you can add this to the code before the bezier start:

TweenMax.set($box, {x:195,y:169});

$box.click(function(){
  points=[{x:195,y:169},{x:204,y:174},{x:227,y:183},{x:266,y:189},{x:324,y:189},{x:387,y:189},{x:447,y:183},{x:461,y:179}]
  TweenMax.to($box, 6, {bezier: {
                        type:'soft',
                        curviness:0,
                        values:points,
                        autoRotate:false,
                        correlate:"x,y"},
                       ease:Linear.easeNone}
  )  
});

Of course since you're capturing the points on mouse move you can set the initial element's opacity to zero, capture the initial point, use the set instance to position the element according and after that set the opacity to 1 and finally initiate the bezier path animation.

 

I've forked your codepen:

See the Pen gjcIm by rhernando (@rhernando) on CodePen

 

Hope this helps,

Cheers,

Rodrigo.

Link to comment
Share on other sites

Yep, I got the same impression as Rodrigo - it seems like maybe you were under the impression that "x" and "y" were coordinates in relation to the page or parent or something, but in css translation occurs from the element's original position in the document flow. So think of "x" and "y" as offset values form the element's original spot. Does that clear things up? 

Link to comment
Share on other sites

@rhernando I am trying to build a stage on what you can drag different elements and then you move them on that stage and after you hit play. Then they will start playing from the position where they had been dropped on the stage to the position where the user have finish moving the element.

 

I understand now, from what I have learn today I will use translate to position my elements (they are draggable and before I was using jquery UI library for the drag,drop events but now i will write from scratch with mouse move/down/up). Just need to find a way to corelate the mouse positions and the ones from the dragged div.

 

You where right, I was thinking that x and y are in relation to the first relative parent and the funny thing was that I haven't read about that on internet because was obvious for me to be like that.

 

Also, for some elements I will need to make bigger paths, for example they will have like 150+,200 points. I was thinking to verify the distance between every group of 2 points and if the distance is lower than 2 or 3 to remove the point. It will be better for animation performance ? Also, I forgot to mention that I record the points with a delay of 15 miliseconds. 

And for canvas performance I bet that will be better to use the points that I get from bezierThrough() function rather than using quadraticCurveTo() function on every group of 2 points like i am doing right now.

 

Thank you again for the help, I am learning new things everyday.

Link to comment
Share on other sites

Hi,

 

As for animation performance basically it'll depend on how many elements you're animating and the type. If you include a lot of images that could be an issue. In the matter of the amount of points perhaps the concern could be processing time and stress of JS not the graphical part itself. Maybe you could use console.time() and console.timeEnd in order to check how long it takes to process the data.

 

But as far as I know the staff runs stress tests so there's a chance that they've already done some bezier path with an insane amount of points in it.

 

Best,

Rodrigo.

Link to comment
Share on other sites

Yep, the bezier performance is very optimized (we've heard from customers who were quite surprised at how good it is) but as with anything, you can always push things too far. If you try using 1,000,000 points and animate a bunch of 20MP images on a first-generation iPhone, you're gonna have some problems :) 

 

I recommend running some tests for your particular usage. 

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...