├── .gitmodules ├── README.md └── rotate3Di.js /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "jquery-css-transform"] 2 | path = jquery-css-transform 3 | url = git@github.com:zachstronaut/jquery-css-transform.git 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rotate3Di 2 | 3 | Zachary Johnson 4 | 5 | 6 | Rotate3Di is a jQuery Effect Plugin that makes it possible to do an isometric 3D flip or 3D rotation of any HTML content. It also enables custom 3D rotation animations. CSS3 Transforms are used to create this visual "3D" isometric effect. Supported browsers are Safari/Chrome/Webkit, Firefox 3.5+, IE 9+, and Opera 11+. The plugin's functionality includes: setting or animating HTML content to an arbitrary isometric rotation angle, as well as flipping, unflipping, or toggling the flip state of an object. Currently tested with jQuery 1.3.x through 1.6. 7 | 8 | ## Donate to Support this Project 9 | 10 | Rotate3Di is, and will always be, a free plugin. I do spend quite a bit of time answering an increasing number of emails about this project, testing it, and patching bugs. I'd like to be able to add features and work on supporting other browsers, but I work for myself so I can't always find the time. Consider buying me a beer, so that I can happily put more time into this project. Follow the link and click the PayPal donate button. Thank you! 11 | 12 | 13 | 14 | 15 | _.............._ 16 | ,' `. 17 | |`-==============-'| 18 | / \ 19 | \ _ _ _ _ _ _ / 20 | |,-' `-.| <-- Here's where I'd like my beer level to be. 21 | |`-._ _ _ _ _ _ .-'| 22 | | | 23 | | | 24 | | ____________ | 25 | |,-' `-.| <-- Here's where my beer level currently is. 26 | |`-.____________.-'| 27 | hjw |. ' : . : . | 28 | \ . : .: / 29 | `._:_____:____'_.' 30 | 31 | 32 | For more project information, code examples, and documentation visit: 33 | 34 | 35 | This code is currently available for use in all personal or commercial projects under both MIT and GPL licenses, just like jQuery. 36 | 37 | ## Change Log 38 | 39 | 2012.10.04 - v0.9.2: Mainly a fix for Firefox 16, but... $(el).transform() fetches style string for current transform, which in some browsers is a matrix() statement instead of a set of separate transform functions. This made it so I couldn't simply grep for skewY(). I was already tracking the current degrees of animation via $(el).data() anyway... so now I just return that rather than parsing from style string. In future would be good to actually support transforms already set on an element by other code/CSS. 40 | 41 | 2012.07.24 - v0.9.1: Firefox 14 / W3C transforms change... skew() replaced with skewY() 42 | 43 | 2010.11.26 - Added to GitHub, including updated dependencies to enabled IE9 (Platform Preview 7+) support 44 | 45 | 2009.03.11 - First release of project as rotate3Di v0.9 46 | 47 | -------------------------------------------------------------------------------- /rotate3Di.js: -------------------------------------------------------------------------------- 1 | (function ($) { 2 | // rotate3Di v0.9.2 3 | // https://github.com/zachstronaut/rotate3Di 4 | // 2012.10.04 - 2009.03.11 Zachary Johnson http://www.zachstronaut.com 5 | // "3D" isometric rotation and animation using CSS3 transformations 6 | // currently supported in Safari/Chrome/Webkit, Firefox 3.5+, IE 9+, 7 | // and Opera 11+. Tested with jQuery 1.3.x through 1.7.2. 8 | 9 | 10 | var calcRotate3Di = { 11 | direction: function (now) {return (now < 0 ? -1 : 1);}, 12 | degrees: function (now) {return (Math.floor(Math.abs(now))) % 360;}, 13 | scale: function (degrees) {return (1 - (degrees % 180) / 90) 14 | * (degrees >= 180 ? -1 : 1);} 15 | } 16 | 17 | // Custom animator 18 | $.fx.step.rotate3Di = function (fx) { 19 | direction = calcRotate3Di.direction(fx.now); 20 | degrees = calcRotate3Di.degrees(fx.now); 21 | scale = calcRotate3Di.scale(degrees); 22 | 23 | if (fx.options && typeof fx.options['sideChange'] != 'undefined') { 24 | if (fx.options['sideChange']) { 25 | var prevScale = $(fx.elem).data('rotate3Di.prevScale'); 26 | 27 | // negative scale means back side 28 | // positive scale means front side 29 | // if one is pos and one is neg then we have changed sides 30 | // (but one could actually be zero). 31 | if (scale * prevScale <= 0) { 32 | // if one was zero, deduce from the other which way we are 33 | // flipping: to the front (pos) or to the back (neg)? 34 | fx.options['sideChange'].call( 35 | fx.elem, 36 | (scale > 0 || prevScale < 0) 37 | ); 38 | // this was commented out to prevent calling it more than 39 | // once, but then that broke legitimate need to call it 40 | // more than once for rotations of 270+ degrees! 41 | //fx.options['sideChange'] = null; 42 | 43 | // this is my answer to commenting the above thing out... 44 | // if we just flipped sides, flip-flop the old previous 45 | // scale so that we can fire the sideChange event correctly 46 | // if we flip sides again. 47 | $(fx.elem).data( 48 | 'rotate3Di.prevScale', 49 | $(fx.elem).data('rotate3Di.prevScale') * -1 50 | ); 51 | } 52 | } 53 | 54 | // Making scale positive before setting it prevents flip-side 55 | // content from showing up mirrored/reversed. 56 | scale = Math.abs(scale); 57 | } 58 | 59 | // Since knowing the current degrees is important for detecting side 60 | // change, and since Firefox 3.0.x seems to not be able to reliably get 61 | // a value for css('transform') the first time after the page is loaded 62 | // with my flipbox demo... I am storing degrees someplace where I know 63 | // I can get them. 64 | $(fx.elem).data('rotate3Di.degrees', direction * degrees); 65 | $(fx.elem).css( 66 | 'transform', 67 | 'skewY(' + direction * degrees + 'deg)' 68 | + ' scale(' + scale + ', 1)' 69 | ); 70 | } 71 | 72 | // fx.cur() must be monkey patched because otherwise it would always 73 | // return 0 for current rotate3Di value 74 | var proxied = $.fx.prototype.cur; 75 | $.fx.prototype.cur = function () { 76 | if(this.prop == 'rotate3Di') { 77 | return $(this.elem).data('rotate3Di.degrees') || 0; 78 | } 79 | 80 | return proxied.apply(this, arguments); 81 | } 82 | 83 | $.fn.rotate3Di = function (degrees, duration, options) { 84 | if (typeof duration == 'undefined') { 85 | duration = 0; 86 | } 87 | 88 | if (typeof options == 'object') { 89 | $.extend(options, {duration: duration}); 90 | } else { 91 | options = {duration: duration}; 92 | } 93 | 94 | if (degrees == 'toggle') { 95 | // Yes, jQuery has the toggle() event but that's only good for 96 | // clicks, and likewise hover() is only good for mouse in/out. 97 | // What if you want to toggle based on a timer or something else? 98 | if ($(this).data('rotate3Di.flipped')) { 99 | degrees = 'unflip'; 100 | 101 | } else { 102 | degrees = 'flip'; 103 | } 104 | } 105 | 106 | if (degrees == 'flip') { 107 | $(this).data('rotate3Di.flipped', true); 108 | 109 | var direction = -1; 110 | if ( 111 | typeof options == 'object' 112 | && options['direction'] 113 | && options['direction'] == 'clockwise' 114 | ) { 115 | direction = 1; 116 | } 117 | 118 | degrees = direction * 180; 119 | 120 | } else if (degrees == 'unflip') { 121 | $(this).data('rotate3Di.flipped', false); 122 | 123 | degrees = 0; 124 | } 125 | 126 | var d = $(this).data('rotate3Di.degrees') || 0; 127 | $(this).data( 128 | 'rotate3Di.prevScale', 129 | calcRotate3Di.scale(calcRotate3Di.degrees(d)) 130 | ); 131 | $(this).animate({rotate3Di: degrees}, options); 132 | } 133 | })(jQuery); 134 | --------------------------------------------------------------------------------