Jump to content
Search Community

Draggable Rotation - Snap at various degrees

Joe Hakooz 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

First thanks to Jamie and Jack for answering a similar question. Turns out I was asking the wrong question :-(

 

What I'm failing to achieve is something very similar to the Draggable Spin demo...

http://www.greensock.com/draggable

 

My requirement has two differences:

  1. I need to snap to a bunch of degrees from an array that are not in even increments. For example [0,  88, 185, 268]. 
  2. I need a callback so I can display information related to the "snapped" degree. 

You can think of this as the Wheel of Fortune with uneven distances between each pin.

 

A few things to note:

I tried supplying an array to the snap option, but once the dial turns more than one rotation, it comes whipping back like it's attached to a rubber band. In addition, I can't use a callback with this technique (I don't think). But the GreenSock Spin demo allows you to spin the dial around and around, and it smoothly lands on a "snap" degree. 

 

Thanks for any help!

 

Link to comment
Share on other sites

This is entirely possible, yes. The behavior you described when passing the array to Draggable's snap is actually quite appropriate - it should snap back once the user spins past the boundary (like if your max value is 268 and they try spinning to 1045 which is several rotations past the max, it should come back) but it sounds like you want to allow folks to have no maximum or minimum, only make sure that they land on a value that's a 360-degree increment of the values in your array. Right? 

 

I don't have time to code all the logic for you right now, but the basic idea would be to:

  1. Use the modulus thing I showed you in your other post to force the end value to its corresponding one between 0 and 360. 
  2. Find the closest value in your array
  3. Figure out how many full rotations there are between the original endValue and the new one you just found. For example, if the original endValue is 990, the modulus thing would show that it'll land at 268 from your array, and there are two additional full rotations (720 degrees), so add that back in to the endValue that you return. In this case it'd be 988. Think of it like:
arrayValue + Math.floor((originalValue - arrayValue) / 360) * 360

I hope that helps. 

Link to comment
Share on other sites

Thanks Jack!

I was actually considering doing exactly that but thought I was reinventing the wheel (so to speak) so decided to come back to the forum for ideas. 

 

I'm now comfortable with where to take this and will post back my code once I have a solution.

Link to comment
Share on other sites

I finally got this working, but I'm curious...

"snap" appears to fire 3 times when you release the mouse. Is that by design?

 

Notes: Works just like the Draggable Spin demo, but allows us to use an array of varying degrees. And since it's a function we can easily execute any other code we want. 

var dialarray = [0,14,55,87,133,150,222,299,301,330]; 
// Snap option inside Draggable.create()
snap:function(originalValue) { 
  // suppress originalValue to 0-360
  var endValue = Math.round(originalValue % 360);
  // change negative degree to positive
  if(endValue < 0){
    endValue = 360 + endValue;
  }
  // get closest value from array
  var arrayValue = parseFloat(closestDeg(endValue, dialarray));
  // get extra rotations to add to our arrayValue
  var addValue = Math.floor((originalValue - arrayValue) / 360) * 360;
  // adjust for shortest rotation
  if((endValue-arrayValue+360)%360>180){
    addValue += 360;
  }
  return arrayValue + addValue;	
}

// get nearest degree
function closestDeg(num, arr) {
  var ds = arr.map(function( {
    var d = Math.abs(num - ;
    return d > 180 ? 360 - d : d;
  });
  return arr[ds.indexOf(Math.min.apply(null, ds))];
};

Thanks again Jack for everything!

Link to comment
Share on other sites

  • 8 months later...

Hi Scotty,

 

You are posting in our HTML5 / JavaScript forum so all the code you see in this thread is not for AS3.

And don't worry, its a common mistake.

 

So if you need a JavaScript solution for your problem you are definitely in the right place. 

 

However, if you need to do this in Flash, we don't really have an exact product that matches Draggable (as AS3 has a fairly reliable drag API natively).

On our ThrowPropsPlugin page there is a dial demo. can download the demo file from a link in the faq and take a look at the code to see how it was built but the dial itself is only a demo and not a product that we plan to support or build additional features on, its really just a freebie. If you want the dial to to support the physics-based throwing that would require a purchase of Shockingly Green membership as described on that page.

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