Fx.Rotate: Animated Element Rotation with MooTools

By  on  
MooTools Rotate

I was recently perusing the MooTools Forge and I saw a neat little plugin that allows for static element rotation: Fx.Rotate. Fx.Rotate is an extension of MooTools' native Fx class and rotates the element via CSS within each A-grade browser it supports. Let's examine how you can easily incorporate animated element rotation within your website.

The MooTools JavaScript

How you use the plugin and when you instantiate the Fx.Rotate class is up to you. For the sake of this being an introduction to the class, we'll keep it simple and make the element rotate when a button is clicked:

window.addEvent('domready',function() {
	var rotate = new Fx.Rotate('rotate-me',{duration:'long'});
	document.id('do-rotate').addEvent('click',function() {
		rotate.start(0,45); //showtime!
	});
});

When the DOM is set, we assign a click listener to the button which rotates the element from 0 degrees (its original state) to 45 degrees. You can probably already tell that the start method is the animator. The class is super small because it extends Fx; Fx is where the animation logic is housed.

The MooTools Class

I cannot say that the code, as it's presently available, is up to MooTools' standards:

(function (window,undef){

var deg2radians = Math.PI * 2 / 360
    , prefix = "";

function getMatrix(deg){
    rad = deg * deg2radians ;
    costheta = Math.cos(rad);
    sintheta = Math.sin(rad);

    a = parseFloat(costheta).toFixed(8);
    c = parseFloat(-sintheta).toFixed(8);
    b = parseFloat(sintheta).toFixed(8);
    d = parseFloat(costheta).toFixed(8);
    return [a,b,c,d];
}


if (Browser.Engine.gecko) prefix = 'moz';
if (Browser.Engine.webkit) prefix = 'webkit';
if (Browser.Engine.presto) prefix = 'o';

Fx.Rotate = new Class({
    Extends : Fx
    , element : null
    , initialize : function(el,options){
        this.element = $(el);
        this.element.setStyle("-"+prefix+"-transform-origin","center center");

        if (Browser.Engine.trident){
            this.element.setStyle("filter","progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand')");
        }

        this.parent(options);
    }
    , start : function(from,to){
        this.parent(from,to);
    }
    , set : function (current){
        if (Browser.Engine.trident) current *=-1;
        var matrix = getMatrix(current);

        if (Browser.Engine.trident){
            this.element.filters.item(0).M11 = matrix[0];
            this.element.filters.item(0).M12 = matrix[1];
            this.element.filters.item(0).M21 = matrix[2];
            this.element.filters.item(0).M22 = matrix[3];
        }else{
            this.element.setStyle("-"+prefix+"-transform","matrix("+matrix[0]+","+matrix[1]+","+matrix[2]+", "+matrix[3]+", 0, 0)");
        }
    }
});
})(this);

While this code works (and that's what's most important), I'd prefer to see the class look like this:

	Fx.Rotate = new Class({
		Extends: Fx,
		initialize: function(element,options) {
			this.element = document.id(element);
			this.prefix = (Browser.Engine.gecko ? 'moz' : (Browser.Engine.webkit ? 'webkit' : 'o'));
			this.radions = Math.PI * 2 / 360;

			if(Browser.Engine.trident) { // IE
				this.element.setStyle('filter','progid:DXImageTransform.Microsoft.Matrix(sizingMethod="auto expand")');
			}
			else {
				this.element.setStyle('-' + this.prefix + '-transform-origin','center center');
			}

			this.parent(options);
		},
		start: function(from,to) {
			this.parent(from,to);
		},
		set: function(current) {

			if (Browser.Engine.trident) current *=-1;
			var matrix = getMatrix(current);

			if (Browser.Engine.trident){
				this.element.filters.item(0).M11 = matrix[0];
				this.element.filters.item(0).M12 = matrix[1];
				this.element.filters.item(0).M21 = matrix[2];
				this.element.filters.item(0).M22 = matrix[3];
			}else{
				this.element.setStyle('-' + this.prefix + '-transform','matrix(' + matrix[0] + ',' + matrix[1] + ',' + matrix[2] + ', ' + matrix[3] + ', 0, 0)');
			}
		},
		getMatrix: function(deg) {
			var rad = deg * (this.radions), costheta = Math.cos(rad), sintheta = Math.sin(rad);
			var a = parseFloat(costheta).toFixed(8),
				c = parseFloat(-sintheta).toFixed(8),
				b = parseFloat(sintheta).toFixed(8),
				d = parseFloat(costheta).toFixed(8);
			return [a,b,c,d];
		}
	});

Just a bit of reorganization; no real change of logic. Mine is a bit prettier -- at that cost is the re-check of logic for each instance but the processing to do that is so negligible that I'm not concerned about it.

While it's a tad hard to think of an "every day, practical" use of this class, I think that this snippet has its merits and would probably work out great for some purposes of someone's website! Also, take a trip down memory lane and check out Fx.Explode!

Recent Features

  • By
    Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

  • By
    Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() - this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

Incredible Demos

  • By
    Duplicate the jQuery Homepage Tooltips Using MooTools

    The jQuery homepage has a pretty suave tooltip-like effect as seen below: Here's how to accomplish this same effect using MooTools. The XHTML The above XHTML was taken directly from the jQuery homepage -- no changes. The CSS The above CSS has been slightly modified to match the CSS rules already...

  • By
    Implement jQuery’s hover() Method in MooTools

    jQuery offers a quick event shortcut method called hover that accepts two functions that represent mouseover and mouseout actions. Here's how to implement that for MooTools Elements. The MooTools JavaScript We implement hover() which accepts to functions; one will be called on mouseenter and the other...

Discussion

  1. Doesn’t work in My IE8 :(

  2. Um, he spelled “radians” correctly. :-)

  3. It’s really fun to see my code used by others :)
    I’ll think of implementing it that way, though, if we’re at it, there’s no reason to put the prefix in the initialize:

    var Fx.Rotate = new Class({
       ...
       prefix : (Browser.Engine.gecko ? 'moz' : (Browser.Engine.webkit ? 'webkit' : 'o'))
       , initialize : ...
    });
    

    I usually use public methods only for stuff that should be extended. I don’t see why creating an extra instance of getMatrix makes the code cleaner or better. But, i guess you can never know…

    Also, the IE version has a very odd behavior… no idea why

  4. This guy seems to have come up with a fix using jQuery for the “drifting” rotation in IE, but I can’t get my head around producing a mooTools equivalent.

    Take a look at the source code of http://jsbin.com/adiwa3/53

  5. Implemented the fixes. Should have JSlinted before submitting to noticed all the implied global decelerations on the original code (taken from MSDN…)…
    All fixed now.
    I reckon putting the getMatrix as a method makes since as it will probably be a good place to fix the IE travel problem

  6. It doesn’t work in Google Chrome 9.0.597.98

  7. Peter. I gave up on this library, it’s flawed. I started using jQueryRotate which is a very good implementation of element rotation.

  8. here is the same thing only on jquery.
    sorry for my English, I use google translator.
    And jquery sign a couple of days, so do not scold severely.
    Greetings from Russia:)

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!