rotateImage: Javascript Rotatable Image Plugin With Touch and Mouse Support

September 18, 2014

rotateImage is a touch enabled image rotation script based on the jQuery.threesixty plugin by Mathieu Dumais-Savard.  It uses canvas, implements inertial scrolling, and is under 4 kb.  A demo of it can be found here:

http://andyfitz.me/rotateImage

It works in Internet Explorer 9+ and current versions of other browsers.  If a browser doesn't support canvas, the script exits without changing the page.  If you use a canvas shim, it might work but hasn't been tested.

How it Works

The script adds a canvas element to the page right after the indicated image.  It then adds the image to canvas and hides the original.  At the bottom of the page, it creates a hidden element that preloads the other images.

Event handlers for touch and mouse are created that track movement across canvas.  After you move a certain distance, the canvas changes the image simulating rotation.  When the mouse leaves the canvas or the user lifts their finger, the image continues rotating for a short period.

Setup

First, you need 30-60 images of a rotating subject.  The images have to be sequentially named in the form, subjectA-0.jpg, subjectA-1.jpg, etc.  The offset property sets the starting number (0 by default).  Also, the script does a simple replace that updates the first occurrence of the offset (so subject0-0.jpg would not work).

See this The Next Web article for a novel approach to taking 360 degree product photos.

Next you need to reference jQuery 1.6+ and add an img tag to the page with the default image.  The img tag needs to have a data-image-count attribute that specifies the total number of images like the following:

<img src="http://www.mathieusavard.info/threesixty/MAT_1450.jpg" class="rotate" data-image-count="30">

Finally, right before the closing body tag you need to reference the rotateImage script and initialize the script like the following:

<script type="text/javascript" src="rotateImage.js"></script>
<script>
	$(window).load(function() {
		$(".rotate").rotateImage({ offset: 1450, timeConstant: 100 });
	});
</script>

Properties

There are 3 properties that you can pass into the initialization:

  • amplitudeFactor: the amplitudeFactor is used in the exponential decay function to slow the rate of rotation.  Lower = slower.
  • offset: the number that your image names start from.  In the example above it is 1450 (MAT_1450.jpg).
  • timeConstant: a description can be found in the references below but Higher = Longer.

References

Most of the intertial scrolling code came from an article, Javascript Kinetic Scrolling by Ariya Hidayat.  It took a lot of tweaking to get it to look right.  That is why the amplitudeFactor and timeConstant are exposed as properties (in case you have to tweak the defaults).

Mathieu Dumais-Savard's jQuery.threesixty plugin was the inspiration for rotateImage.  I've modifed the code substantially and structured it in an IIFE but the concepts are similar.

Download

Licensing

This plugin retains the same licensing as the threesixty plugin:

Basically, it's free to use how you want, you need to include the copyright notice and MIT License, and I'm not liable.

Support

There should be no expectation of support.  This developed out of a work concept.  If I develop updates through my work, I will post them here.  If you ask a question in the comments, I might answer it.

How to Make it Better

rotateImage checks if the browser supports the canvas element but not if it can create a 2d context.  If maximum compatibility is important to you, see the Stack Overflow discussion on checking for canvas support.

The original version used requestAnimationFrame, but there were compatibility issues and I never got the timing right.  It could probably be added back in with a shim, but I didn't see a noticeable difference in my tests.

The touch events are different from the mouse events in that they don't check for when the touch leaves the canvas bounds.  Rather the inertial scrolling kicks in on the touch end event.  I prefer this, but see the Stack Overflow discussion on TouchLeave if you want to change it.

The image is set to rotate 1.5 times in one pass.  Change the literal on Line 46 if you want it to rotate more or less.  This could also be made into a new property.

Finally, I'm not a JavaScript expert and I'm sure that this could be re-written simpler with better performance.  Someone with time could probably refactor the code into something more readable and extensible.