Draggable Spin - Getting it to fully rotate instead of stopping.

Moderator Tag

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

Hi everyone!

I was wondering if it is possible to get my project to continually spin instead of stopping at the top and having to scroll back. It is clicking into position perfectly other than that, but just thought I might be missing something. Any input would be appreciated, thank you!

The Codepen:

See the Pen WRBRMg by JR150 (@JR150) on CodePen

See the Pen WRBRMg  by JR150 (@JR150) on CodePen

Share on other sites

I know PointC is working on an answer (which will no doubt be helpful), but I figured I'd sneak in and offer my perspective....

Here's a forked version that I think does what you're asking:

http://codepen.io/GreenSock/pen/JEgwZR?editors=0010

Notice I'm using a function for the liveSnap and running some logic in there that finds the closest value and uses the modulus operator to keep it between 0 and 360. I removed the bounds because that's redundant and actually gets in the way anyway. I also simplified that logic you're running on every drag to figure out the positional index - this way is much faster and easier.

Here's the pertinent code:

```var knob = document.getElementById("knob");
var previousPosition = 0;
var position = 0;
var currentRotation = 0;
var snaps = [0, 45, 90, 120, 150, 180, 210, 240, 270, 315, 360]; //array of rotational snapping points (in degrees)

//create the knob Draggable
Draggable.create(knob, {
type: "rotation",
edgeResistance: 0.85,
onDrag: onRotateKnob,
onThrowUpdate: onRotateKnob,
liveSnap: function(value) {
position = getClosestIndex((value + 360 * 99999999) % 360, snaps); //adding 360 * 999999999 in order to ensure it's always a positive rotational value
return snaps[position];
}
});

//when the user drags the knob, we must update the scroll position. We're using the special scrollProxy object of Draggable because it allows us to overscroll (normal browser behavior won't allow it to scroll past the top/bottom).
function onRotateKnob() {
//do stuff
}

function getClosestIndex(value, choices) {
var i = choices.length;
var closest = 0;
var absDif = 9999999999;
var dif, val;
while (--i > -1) {
val = choices[i];
dif = Math.abs(val - value);
if (dif < absDif) {
closest = i;
absDif = dif;
}
}
return closest;
}```

Does this help?

• 3
Share on other sites

Hi JR150

Yes - you can have the knob keep spinning through the various snap points. You'll have to do a couple of things to make that happen. You'll have to remove the min/max rotations and we can also eliminate the snap array and use a Math function to take care of that.

I've made a fork of your pen (minus all the extra divs so it's just the knob) You'll see that as you rotate the knob the actual element rotation is shown along with a modified rotation. By using a remainder operator when the rotation meets or exceeds 360, we can return a modified rotation and a position number. You'll also see that you have to account for a user dragging the knob in reverse. That again is just a little arithmetic with a remainder. By doing it this way, you can also eliminate a lot of code with all those if/else statements.

See the Pen OWKBrL by PointC (@PointC) on CodePen

Hopefully that helps.

Happy tweening.

• 2
Share on other sites

Good solution, Craig. I like the demo that prints out values. I went about things slightly differently mostly because his array of values aren't equidistant. Like 0, 45, 90, 120... (notice it doesn't always jump by 45).

Cheers!

• 1
Share on other sites

Ha! Yes I saw that after I finished my demo.

That's why I was so slow to post after I claimed this topic. As I was typing my answer I looked at JR150s pen again and noticed the snap array was set up like that. I went back to modify my pen, but then you posted so I just left my demo alone.

I took the lazy mans approach and mine will only work for equidistant snaps, but maybe it will help someone.

My solution in case any future readers want to see it:

```var theSnap = 36;
TweenMax.set("#data, #knob", {xPercent:-50});

Draggable.create("#knob", {
type: "rotation",
onDrag: updateData,
liveSnap: function(endValue) {
return Math.round(endValue / theSnap) * theSnap;
}
});

function updateData() {
rt = this.rotation;
\$( "#actualRotation strong" ).html( rt );
if (rt>=360) {rt = rt % 360};
if (rt<0) { rt % 360 == 0 ? rt = 0 : rt = 360 + (rt % 360) }
\$( "#modifiedRotation strong" ).html( rt );
\$( "#currentPosition strong" ).html( rt/theSnap+1 );
} ```

See the Pen OWKBrL by PointC (@PointC) on CodePen

• 2
Share on other sites

This worked perfectly. Thank you both for replying quickly and being amazing as usual!

• 1