Jump to content
GreenSock

skala

Progressing draggable to smoothly drag along the path

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

I am using a draggable knob along an svg path. The path is a quadratic bezier curve which has the y coordinates going up and then down.

How should I progress the draggable instance so that I am able to fill the path while dragging the knob on the path?

 

To simply put it, I want the path to be filled while dragging the knob and the portion of the path to be filled should be only upto the knob.

Also the mouse pointer should be in sync with the draggable knob.

Any suggestions or leads are appreciated.

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

Link to comment
Share on other sites

Check out the following thread that shows how you can drag along the path. You should able to draw your Path using total Length and knob's current position using that demo.

 

 

  • Like 2
Link to comment
Share on other sites

Thanks Sahil. I will look into it and update here if I have any doubt.

 

Link to comment
Share on other sites

Hi,

Since the approach followed here is based on the closest point on the path, the continuity of the drag(and correspondingly the fill) will not be maintained always.

 

I am looking for something which will maintain the continuity as well.

 

I am using this as a reference:

 

See the Pen aOzeNR by MAW (@MAW) on CodePen

 

 

  • Like 1
Link to comment
Share on other sites

Any help is appreciated.

Link to comment
Share on other sites

I doubt it's going to be easy.

 

What I can think of is, let's say your mouse traveled 3 pixels, then compare closest points to the knob for 3 pixels and select one that is closest to the mouse. But there might be more problems to this solution, like lets say you move closer to the knob then you will need to add some conditional logic that will decide whether to move the knob or not.

 

Blake might be able to suggest something but you will have to dive a lot deeper to pull it off.

@OSUblake

  • Like 2
Link to comment
Share on other sites

Hi there!

 

I am reading this thread but finding it very hard to picture what it is that you mean by " continuity" .

 

What in Diaco's example does not fulfil your needs?

 

Another question: When you stated that you wanted the mouse pointer should be "in sync" with the draggable knob, do you mean you want to lock the mouse pointer to the location of the draggable object? If that is what you want, you will not be able to achieve it. You cannot take over the mouse pointer. The best you can do is fake it by hiding the mouse cursor and then adding a fake cursor on top of the draggable object, locking that fake one onto the position you desire.

  • Like 2
Link to comment
Share on other sites

Hi Dipscom!

 

By 'continuity' I meant that the fill of the svg path should be continous and there should not be any gaps.

 

I have created this pen for tracing the number '1' : 

In the below example, the mouse pointer is 'in sync' with the draggable knob which is possible by using bounds and calling the '.progress' function and passing appropriate value. This was straightforward as for a particular path for example 'path3', the value of y was increasing always(The mouse pointer for tracing moved only in downward direction in y).

 

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

 

 

 

I want to implement the tracing for the number '2' in a similar way as above. I need help with the tracing of number '2' so that it works in a similar fashion as the tracing of number '1' as shown in the above example. In this case having a curved path, the mouse pointer for tracing will move in both directions in y(first the pointer will go up and then it will go down while tracing). So for this case I need help with implementing similar tracing.

 

Let me know if I was still unable to convey my requirement.

 

 

 

Link to comment
Share on other sites

I'm a still a bit fuzzy about the continuity but I think I got what you want with the dragging.

 

It's going to require a bit of logic to keep track of the progress of the drawing and make the necessary adjustments to the dragging of the knob.

 

Having said that, it sounds like an interesting problem to tackle. Right now, I cannot, but I might have a stab at it later on.

  • Like 1
Link to comment
Share on other sites

Hello!

 

I have managed to spend a bit of time on this. Diaco's original pen is quite useful and a rather neat trick he's got there.

 

The catch is making sure you are using the same type of curve for the Bezier and the SVG you are drawing. In this case, it's "Cubic".

 

It will be wise to read the following pages to get yourself familiar with the Path attribute in SVG and GSAP's BezierPlugin:

 

https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths

https://greensock.com/docs/Plugins/BezierPlugin

 

Now you can just drag the knob sideways to get it to slide along the path nicely. I also feel this fixes your continuity issue, where you were saying the knob wasn't sitting exactly where you expected it to be.

 

Here's my fork of Diaco's pen: 

See the Pen PeLQVZ?editors=1010 by dipscom (@dipscom) on CodePen

 

Now if you want the dragging not to be just a straight line, you know it will be a rather complex set of logic for you to achieve that. And I don't think I'll have enough spare time to write the logic for you.

 

 

 

  • Like 2
Link to comment
Share on other sites

On 5/21/2018 at 2:44 AM, skala said:

Any help is appreciated.

 

Look at the page @Sahil linked to. You need to find the closest point on the path. NONE of the pens you have made do that. They all do linear progression.

  • Like 4
Link to comment
Share on other sites

16 hours ago, Dipscom said:

Hello!

 

I have managed to spend a bit of time on this. Diaco's original pen is quite useful and a rather neat trick he's got there.

 

The catch is making sure you are using the same type of curve for the Bezier and the SVG you are drawing. In this case, it's "Cubic".

 

It will be wise to read the following pages to get yourself familiar with the Path attribute in SVG and GSAP's BezierPlugin:

 

https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths

https://greensock.com/docs/Plugins/BezierPlugin

 

Now you can just drag the knob sideways to get it to slide along the path nicely. I also feel this fixes your continuity issue, where you were saying the knob wasn't sitting exactly where you expected it to be.

 

Here's my fork of Diaco's pen: 

See the Pen PeLQVZ?editors=1010 by dipscom (@dipscom) on CodePen

 

Now if you want the dragging not to be just a straight line, you know it will be a rather complex set of logic for you to achieve that. And I don't think I'll have enough spare time to write the logic for you.

 

 

 

 

Hi ,

It was really helpful. The documentation of BezierPlugin was exactly what I was looking for in my other answer. Now for this one, I would read more and try to make use of 'closest point on the path' approach so that the dragging is along the curve just like actual tracing as pointed out by Blake.

 

Thanks!

 

 

Link to comment
Share on other sites

7 hours ago, OSUblake said:

 

Look at the page @Sahil linked to. You need to find the closest point on the path. NONE of the pens you have made do that. They all do linear progression.

 

Hi Blake!

I went through that demo in which you are using the 'closest point on the path' approach. Using the same approach, how to fill the svg path upto the current position of the draggable circle ?

 

I have 2 paths. One is the dash-array one and the other is the path which has to be filled upto current position of the circle. I am initially setting the stroke-opacity of path2 as zero.

 

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

 

Link to comment
Share on other sites

My demo is kind of crude, and I didn't spend a lot of time polishing it. Try returning the "bestLength" in the object that is returned by the closestPoint function. I think that value should give you what you want for the stroke.

  • Like 2
Link to comment
Share on other sites

Hi Blake,

By making use of the 'bestLength' ,  I am able to fill the SVG upto the current position of the draggable circle.

 

But there is one issue, since the best Length is evaluated as the length upto the closest point on the path, there occurs sometimes a sudden shift(sudden jump) in the filling of SVG path. Thus, the 'continuity' is not maintained.

 

Can there be a workaround for this, so that the drag is smooth and there is no sudden jump in the draggable knob and correspondingly in the stroke.

Please advise.

Link to comment
Share on other sites

Yeah, that's one problem with finding the closest point on a path. Think about a circle. There would be an infinite number of closest points if your mouse was in the center. I commented out the distance property in the object returned by that function because I wasn't using it, but you could use that to run some logic to make sure it doesn't jump around.

 

Breaking your curve down into smaller chunks might make that easier. Somewhat related demo where I create bounding boxes around smaller parts of a curve. You can see that progression could follow the order of the boxes.

 

See the Pen jbVPqw by osublake (@osublake) on CodePen

 

 

  • Like 4
Link to comment
Share on other sites

Wow, Blake. That's a crazy demo. Very cool.

  • Like 1
Link to comment
Share on other sites

3 hours ago, OSUblake said:

Yeah, that's one problem with finding the closest point on a path. Think about a circle. There would be an infinite number of closest points if your mouse was in the center. I commented out the distance property in the object returned by that function because I wasn't using it, but you could use that to run some logic to make sure it doesn't jump around.

 

Breaking your curve down into smaller chunks might make that easier. Somewhat related demo where I create bounding boxes around smaller parts of a curve. You can see that progression could follow the order of the boxes.

 

See the Pen jbVPqw by osublake (@osublake) on CodePen

 

 

 

Hi Blake!

In this demo too, the drag is not continous. For example, when traversing an outer arc, if we move the cursor closer to the inner arc, it jumps to the inner arc.

This will break continuity of the drag and correspondingly the fill. I am looking for a workaround so that the draggable knob does not jump around like that from outer to inner arc and vice-versa.

 

If there is going to be a sudden change like that mentioned above, then instead of that jump I want the draggable knob to not move at all from the current position.(the knob should instead be at the current position itself)

 

How can I achieve that ?

Link to comment
Share on other sites

If you look at those boxes, they go in order, and adjacent boxes will not overlap. So you can use that prevent unwanted movement. For example, if the user starts out dragging in the first box, we'll call that box #0, then you can limit dragging to that box and box #1 i.e. the next box on the curve. Once the user has dragged into box #1, then you would limit movement to box #0, #1, and #2. Once the user has dragged into box #2, then you would limit movement to box #1, #2, and #3. You would just continue that pattern until the end.

 

psoM717.png

 

 

Normally I would make a demo, but I don't have a lot of time right now. If @Dipscom or @Sahil wants a challenge, feel free to help out. :-D

 

  • Like 2
  • Haha 1
Link to comment
Share on other sites

Oh no, I can't either... Too many plates still spinning. Would love to but, honestly, do not have the time to dedicate to this.

 

Over to @Sahil...

Link to comment
Share on other sites

I am interested to give it a try, I might be able to do it tomorrow evening but don't consider it a promise.

  • Like 2
Link to comment
Share on other sites

I am looking at the problem from another angle now.

 

Can we stop the draggable knob from being dragged if the mouse pointer is away from the SVG path(the path on which the knob has to be dragged).

 

If I can allow the drag to work only if the mouse is close to the SVG path(let's say mouse pointer is within some threshold value of 5-10 px from the knob), otherwise the drag should not work, then in that case it will solve the problem of sudden jumping of the draggable knob too.

 

Please suggest me how can I achieve that ?

Link to comment
Share on other sites

Did you notice how the line turns green when you are close to the path in my boxes demo. That's kind of what you're asking, but it will still allow you to jump around.

 

Really simple demo showing the problem.

 

See the Pen ELqYpN by osublake (@osublake) on CodePen

 

  • Like 3
Link to comment
Share on other sites

Hi,

I have found a way to make it work for my requirement.

 

I am using the closest point on the path approach and returning bestDistance from the closestPoint function and then I am checking two conditions :

1. bestDistance < some threshold value(for example 10).

2. distance between draggable circle and pointer < some other threshold value(for example 20).

(the second condition prevents from jumping)

 

If both the above conditions are satisfied, then I am returning 'p.point' from the pointModifier function, otherwise I am returning 

{x : draggable.x,  y : draggable.y} so that the draggable does not move.

 

This is kind of a workaround which will work for many cases if not all.

Link to comment
Share on other sites

On 23/05/2018 at 8:03 PM, OSUblake said:

If you look at those boxes, they go in order, and adjacent boxes will not overlap. So you can use that prevent unwanted movement. For example, if the user starts out dragging in the first box, we'll call that box #0, then you can limit dragging to that box and box #1 i.e. the next box on the curve. Once the user has dragged into box #1, then you would limit movement to box #0, #1, and #2. Once the user has dragged into box #2, then you would limit movement to box #1, #2, and #3. You would just continue that pattern until the end.

 

psoM717.png

 

 

Normally I would make a demo, but I don't have a lot of time right now. If @Dipscom or @Sahil wants a challenge, feel free to help out. :-D

 

 

Anyway, I agree this would be the best approach unlike the above workaround that I have posted.

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