Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
bvkdigital

Draggable + pixi.js 360 product rotator

Recommended Posts

Hey all, I think I have a fun one for Blake, since he's done something very similar. We're about to launch the new website for Carmex lip balm, and we got some awesome 3D product renders made. On the single product pages in the hero area is where these 360 rotators will be featured. 

 

What I can't get working is the throwProps! I think it has something to do with how I'm updating the texture frame onDrag... I'm simply incrementing a counter and setting the texture frame to that. I tried really hard to break down the Mario example, but was unable to determine exactly what math to use or how to write the changing of the frame into a tween so throwProps will work. These product rotators would be twice as nice with that feature!

 

Do you think I'm close, or that throwProps is possible with my more basic implementation? Thank you eternally in advance.

See the Pen eEeqEZ by joshkirk (@joshkirk) on CodePen

Link to comment
Share on other sites

Using getVelocity won't work without the throwProps. But even with that working, your function is going to change the frame at a constant rate regardless of how fast you are dragging.

 

Is this more like what you were going for?

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

 

  • Like 2
Link to comment
Share on other sites

Absolutely that is what I was looking for, thank you. You can mark this as completed, and I'll leave my codepen for before/after illustration purposes.. Would you mind commenting your codepen, specifically inside the updateImage function? (or explain here)... How you so quickly whipped up the math for taking the product rotation += deltaX * speed, why 360 is the magic number (seems odd because it's not actually a 3D object, but rather a 2d sprite), why the % operator works here..

 

Since this seems to be the best option for a 360 product rotator, I hope this can help others looking for a solid, basic pixi.js implementation. My fascination with this is mostly how the math works, now that it works. :D

Link to comment
Share on other sites

Hi @bvkdigital

 

The code for my Mario product rotator might be a little confusing because it was part of a larger app, so it's set up a little differently. It could do other stuff, like mouse wheel zooming.

 

360 is the magic number because while this is not a 3d object, that's exactly what we're trying to simulate. Something that looks and functions a little like this...

 

So we need to figure out 2 things. How to convert the dragging motion into a rotational value, and what frame should be showing at that angle.

 

deltaX and deltaY are new properties for Draggable. They report the amount of change since the last drag. So if x is at 75, and on the next drag x is at 100, deltaX would be 25. If you added that 25 to the rotation value, it's essentially the same as adding 25 degrees to it. So a 1:1 ratio. 

 

The delta value could also be considered the velocity at that moment in time. I'm multiplying the delta value by a speed value just as a way to let you control how fast it will rotate. The number I choose is completely arbitrary. You can use whatever value you want.

productRotation += this.deltaX * speed; // use whatever value you want for speed

 

The productRotation value is really just a running total of the (deltaX * speed) values, so we need to convert it into an angle. That value could be very high, and even negative, and the remainder operator (%) will give us a number in the range of +/-360.

 

-55555 % 360 // => -115
361 % 360 // => 1
270 % 360 // => 270

 

And dividing that value by 360 will give us a ratio, which we can multiply and by our frame count to give us an index value.

 

var count = numFrames - 1; // subtract 1 because arrays start at 0

var ratio = (productRotation % 360) / 360
var index = Math.round(ratio * count);

 

There's a couple problems with that. The ratio might be negative, giving you a negative frame index. You could compensate for this in the ratio calculation by adding the remainder value to 360.

 

var ratio = (360 + (productRotation % 360)) / 360;

 

I did something a little a different for no particular reason, but it works out the same. I'm adding the index to the count in another step if it's less than 1, otherwise I subtract 1 from the index.

 

var index = Math.round((productRotation % 360) / 360 * count);

index = index < 1 ? count + index : index - 1;

 

Now the reason for subtracting 1 might be a little confusing. The frame for an angle of 0 and 360 should be the same, so the last sprite sheet frame should be for an angle that is less then 360, but our ratio was calculated using 360, giving us an extra frame index. 

 

Does that help?

 

For anybody else trying to do this, my description is much longer than the actual code.

 

var speed = 0.35;
var numFrames = frames.length;
var productRotation = 0;

Draggable.create(proxy, {
  throwProps: true,
  trigger: proxyTrigger,
  onDrag: updateImage,
  onThrowUpdate: updateImage,
  cursor: "ew-resize",
  maxDuration: 0.65,
});
    
function updateImage() {
        
  productRotation += this.deltaX * speed;
    
  var count = numFrames - 1;
  var index = Math.round((productRotation % 360) / 360 * count);
    
  index = index < 1 ? count + index : index - 1;
        
  singleProduct360Anim.gotoAndStop(index); // Pixi animated sprite
}

 

  • Like 3
Link to comment
Share on other sites

Wonderful explanation, Blake!

  • Like 1
Link to comment
Share on other sites

You heard it here everyone, math is sexy.

 

Blake, thanks so much for explaining your code. Very smart stuff.

 

Anyone trying to make a 3D product rotator, if you made it this far you can probably figure it out, but it goes something like this:

  • Create the sprite sheets and json files for loading into pixi.js (Hint Texture Packer can export for pixi.js Hint)
  • Get your sprite sheet animation working, watch that sucker animate
  • Create a draggable instance and updateImage function as seen in Blake's example
  • instead of .play() on the anim, use goToAndStop(), also seen in Blake's example

 

 

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