1 /* 2 * jquery.transform.js 3 * Visit the internets for documentation, updates and examples. 4 * https://github.com/pwhisenhunt/jquery.transform.js 5 * 6 * 7 * Copyright (c) 2010 Phillip J. Whisenhunt phillip.whisenhunt@gmail.com http://phillipwhisenhunt.com 8 * 9 * Permission is hereby granted, free of charge, to any person 10 * obtaining a copy of this software and associated documentation 11 * files (the "Software"), to deal in the Software without 12 * restriction, including without limitation the rights to use, 13 * copy, modify, merge, publish, distribute, sublicense, and/or sell 14 * copies of the Software, and to permit persons to whom the 15 * Software is furnished to do so, subject to the following 16 * conditions: 17 * 18 * The above copyright notice and this permission notice shall be 19 * included in all copies or substantial portions of the Software. 20 * 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 * OTHER DEALINGS IN THE SOFTWARE. 29 */ 30 31 32 /** @fileoverview jQuery Transform - A jQuery plugin for 3D and 2D transformations. 33 * @author Phillip J. Whisenhunt 34 * @version 1.0 35 * @requires jQuery 1.6 + 36 */ 37 (function( $ ){ 38 /** @class jQuery.Transform 39 */ 40 var methods = { 41 /** Decrease the height of the given element. 42 * @param {int} value The amount in pixels to decrease height of the element. 43 * @return {void} none 44 * @name decreaseHeight 45 * @function 46 */ 47 decreaseHeight : function( value ) { 48 return this.each(function(){ 49 $(this).data({ 'height' : ($(this).data("height") - value) }); 50 $(this).animate({ height: $(this).data("height") }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 51 }); 52 }, 53 54 /** Decrease the width of the given element. 55 * @param {int} value The amount in pixels to decrease the width of the element. 56 * @return {void} none 57 * @name decreaseWidth 58 * @function 59 */ 60 decreaseWidth : function( value ) { 61 return this.each(function(){ 62 $(this).data({ 'width' : ($(this).data("width") - value) }); 63 $(this).animate({ width: $(this).data("width") }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 64 }); 65 }, 66 67 /** Returns the x-axis position of the element 68 * @return {int} x-axis value 69 * @name getX 70 * @function 71 */ 72 getX : function() { if(!isNaN($(this).data('x'))){ return $(this).data('x'); } else{ init(this); return 0; }; }, 73 /** Returns the y-axis position of the element 74 * @return {int} y-axis value 75 * @name getY 76 * @function 77 */ 78 getY : function() { if(!isNaN($(this).data('y'))){ return $(this).data('y'); } else{ init(this); return 0; }; }, 79 /** Returns the z-axis position of the element 80 * @return {int} z-axis value 81 * @name getZ 82 * @function 83 */ 84 getZ : function() { if(!isNaN($(this).data('z'))){ return $(this).data('z'); } else{ init(this); return 0; }; }, 85 /** Returns the scale of the element 86 * @return {int} scale value 87 * @name getScale 88 * @function 89 */ 90 getScale : function() { if(!isNaN($(this).data('scale'))){ return $(this).data('scale'); } else{ init(this); return 0; }; }, 91 /** Returns the animation duration of the element 92 * @return {float} animation duration value 93 * @name getAnimationDuration 94 * @function 95 */ 96 getAnimationDuration : function() { if(!isNaN($(this).data('animationDuration'))){ return $(this).data('animationDuration'); } else{ init(this); return 0; }; }, 97 /** Returns the width of the element 98 * @return {int} width value 99 * @name getWidth 100 * @function 101 */ 102 getWidth : function() { if(!isNaN($(this).data('width'))){ return $(this).data('width'); } else{ init(this); return $(this).outerWidth(); }; }, 103 /** Returns the height of the element 104 * @return {int} height value 105 * @name getHeight 106 * @function 107 */ 108 getHeight : function() { if(!isNaN($(this).data('width'))){ return $(this).data('width'); } else{ init(this); return $(this).outerHeight(); }; }, 109 /** Returns the elements amount of rotation about the x-axis 110 * @return {int} x rotation value 111 * @name getRotationX 112 * @function 113 */ 114 getRotationX : function() { if(!isNaN($(this).data('rotationX'))){ return $(this).data('rotationX'); } else{ init(this); return 0; }; }, 115 /** Returns the elements amount of rotation about the y-axis 116 * @return {int} y rotation value 117 * @name getRotationY 118 * @function 119 */ 120 getRotationY : function() { if(!isNaN($(this).data('rotationY'))){ return $(this).data('rotationY'); } else{ init(this); return 0; }; }, 121 /** Returns the elements amount of rotation about the z-axis 122 * @return {int} z rotation value 123 * @name getRotationZ 124 * @function 125 */ 126 getRotationZ : function() { if(!isNaN($(this).data('rotationZ'))){ return $(this).data('rotationZ'); } else{ init(this); return 0; }; }, 127 128 /** 129 * Increases the height of the given element. 130 * @param {int} value The amount in pixels to increase the height of the element. 131 * @return {void} none 132 * @name increaseHeight 133 * @function 134 */ 135 increaseHeight : function( value ) { 136 return this.each(function(){ 137 $(this).data({ 'height' : (value + $(this).data("height")) }); 138 $(this).animate({ height: $(this).data("height") }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 139 }); 140 }, 141 142 /** 143 * Increases the width of the given element. 144 * @param {int} value The amount in pixels to increase the width of the element. 145 * @return {void} none 146 * @name increaseWidth 147 * @function 148 */ 149 increaseWidth : function( value ) { 150 return this.each(function(){ 151 $(this).data({ 'width' : (value + $(this).data("width")) }); 152 $(this).animate({ width: $(this).data("width") }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 153 }); 154 }, 155 156 /** 157 * Rotates the element along the x axis in addition to the current rotation. 158 * @param {int} value The degree of rotation along the x-axis 159 * @return {int} none 160 * @name rotateX 161 * @function 162 */ 163 rotateX : function( value ){ 164 return this.each(function(){ 165 if(isNaN($(this).data('rotationX'))){ 166 init(this); 167 $(this).transform('rotateX', value); 168 } 169 else{ 170 $(this).data( { 'rotationX' : $(this).data('rotationX') + value } ); 171 updateTransform(this); 172 } 173 }); 174 }, 175 176 /** 177 * Rotates the element along the y axis in addition to the current rotation. 178 * @param {int} value The degree of rotation along the y-axis 179 * @return {int} none 180 * @name rotateY 181 * @function 182 */ 183 rotateY : function( value ){ 184 return this.each(function(){ 185 if(isNaN($(this).data('rotationY'))){ 186 init(this); 187 $(this).transform('rotateY', value); 188 } 189 else{ 190 $(this).data( { 'rotationY' : $(this).data('rotationY') + value } ); 191 updateTransform(this); 192 } 193 }); 194 }, 195 196 /** 197 * Rotates the element along the z axis in addition to the current rotation. 198 * @param {int} value The degree of rotation along the z-axis 199 * @return {int} none 200 * @name rotateZ 201 * @function 202 */ 203 rotateZ : function( value ){ 204 return this.each(function(){ 205 if(isNaN($(this).data('rotationZ'))){ 206 init(this); 207 $(this).transform('rotateZ', value); 208 } 209 else{ 210 $(this).data( { 'rotationZ' : $(this).data('rotationZ') + value } ); 211 updateTransform(this); 212 } 213 }); 214 }, 215 216 /** 217 * Rotates the element along the x, y, and z-axis. 218 * @param {int} y The amount of rotation along x-axis. 219 * @param {int} x The amount of rotation along y-axis. 220 * @param {int} z The amount of rotation along z-axis. 221 * @return {void} none 222 * @name rotateXYZ 223 * @function 224 */ 225 rotateXYZ : function( x, y, z ){ 226 return this.each(function(){ 227 if(isNaN($(this).data('rotationX')) || isNaN($(this).data('rotationY')) || isNaN($(this).data('rotationZ'))){ 228 init(this); 229 $(this).transform('rotateXYZ', x, y, z); 230 } 231 else{ 232 $(this).data( { 'rotationX' : $(this).data('rotationX') + x } ); 233 $(this).data( { 'rotationY' : $(this).data('rotationY') + y } ); 234 $(this).data( { 'rotationZ' : $(this).data('rotationZ') + z } ); 235 updateTransform(this); 236 } 237 }); 238 }, 239 240 /** 241 * Sets the animation duration of the given element. 242 * @param {int} value The animation duration for the given element. 243 * @return {void} none 244 * @name setAnimationDuration 245 * @function 246 */ 247 setAnimationDuration : function( value ){ 248 return this.each(function(){ 249 if(isNaN($(this).data('animationDuration'))){ 250 init(this); 251 $(this).transform('setAnimationDuration', value); 252 } 253 else{ 254 $(this).data({ 'animationDuration' : value }); 255 updateTransform(this); 256 } 257 }); 258 }, 259 260 /** 261 * Sets the height of the given element. 262 * @param {int} value The height of the element. 263 * @return {void} none 264 * @name setHeight 265 * @function 266 */ 267 setHeight : function( value ){ 268 return this.each(function(){ 269 $(this).animate({ height: value }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 270 $(this).data({ 'height' : value }); 271 }); 272 }, 273 274 /** 275 * Sets the width of the given element. 276 * @param {int} value The width of the element. 277 * @return {void} none 278 * @name setWidth 279 * @function 280 */ 281 setWidth : function( value ) { 282 return this.each(function(){ 283 $(this).animate({ width: value }, $(this).data('animationDuration') * 1000); //multiply by 1000 since animationDuration is in secs. 284 $(this).data({ 'width' : value }); 285 }); 286 }, 287 288 /** 289 * Sets the scale of the given element. 290 * @param {int} value The scale of the given element. 291 * @return {void} none 292 * @name setScale 293 * @function 294 */ 295 setScale : function( value ){ 296 return this.each(function(){ 297 if(isNaN($(this).data('scale'))){ 298 init(this); 299 $(this).transform('setScale', value); 300 } 301 else{ 302 $(this).data({ 'scale' : value }); 303 updateTransform(this); 304 } 305 }); 306 }, 307 308 /** 309 * Sets the elements x position. 310 * @param {int} value The position along the x-axis to set the element. 311 * @return {void} none 312 * @name setX 313 * @function 314 */ 315 setX : function( value ){ 316 return this.each(function(){ 317 if(isNaN($(this).data('x'))){ 318 init(this); 319 $(this).transform('setX', value); 320 } 321 else{ 322 $(this).data({ 'x' : value }); 323 updateTransform(this); 324 } 325 }); 326 }, 327 328 /** 329 * Sets the elements y position. 330 * @param {int} value The position along the y-axis to set the element. 331 * @return {void} none 332 * @name setY 333 * @function 334 */ 335 setY : function( value ){ 336 return this.each(function(){ 337 if(isNaN($(this).data('y'))){ 338 init(this); 339 $(this).transform('setY', value); 340 } 341 else{ 342 $(this).data({ 'y' : value }); 343 updateTransform(this); 344 } 345 }); 346 }, 347 348 /** 349 * Sets the elements z position. 350 * @param {int} value The position along the z-axis to set the element. 351 * @return {void} none 352 * @name setZ 353 * @function 354 */ 355 setZ : function( value ){ 356 return this.each(function(){ 357 if(isNaN($(this).data('z'))){ 358 init(this); 359 $(this).transform('setZ', value); 360 } 361 else{ 362 $(this).data({ 'z' : value }); 363 updateTransform(this); 364 } 365 }); 366 }, 367 368 /** Sets the amount of rotation of the x-axis. 369 * @param {int} value The amount of rotation along the x-axis. 370 * @return {void} none 371 * @name setRotationX 372 * @function 373 */ 374 setRotationX : function( value ){ 375 return this.each(function(){ 376 if(isNaN($(this).data('rotationX'))){ 377 init(this); 378 $(this).transform('setRotationX', value); 379 } 380 else{ 381 $(this).data({ 'rotationX' : value }); 382 updateTransform(this); 383 } 384 }); 385 }, 386 387 /** 388 * Sets the amount of rotation along the x, y, and z-axis. 389 * @param {int} x The amount of rotation along the x-axis. 390 * @param {int} y The amount of rotation along the y-axis. 391 * @param {int} z The amount of rotation along the z-axis. 392 * @return {void} none 393 * @name setRotationXYZ 394 * @function 395 */ 396 setRotationXYZ : function( x, y, z ){ 397 return this.each(function(){ 398 if(isNaN($(this).data('rotationX')) || isNaN($(this).data('rotationY')) || isNaN($(this).data('rotationZ'))){ 399 init(this); 400 $(this).transform('setRotationXYZ', x, y, z); 401 } 402 else{ 403 $(this).data( { 'rotationX' : x } ); 404 $(this).data( { 'rotationY' : y } ); 405 $(this).data( { 'rotationZ' : z } ); 406 updateTransform(this); 407 } 408 }); 409 }, 410 411 /** 412 * Sets the amount of rotation of the y-axis. 413 * @param {int} value The amount of rotation along the y-axis. 414 * @return {void} none 415 * @name setRotationY 416 * @function 417 */ 418 setRotationY : function( value ){ 419 return this.each(function(){ 420 if(isNaN($(this).data('rotationY'))){ 421 init(this); 422 $(this).transform('setRotationY', value); 423 } 424 else{ 425 $(this).data({ 'rotationY' : value }); 426 updateTransform(this); 427 } 428 }); 429 }, 430 431 /** 432 * Sets the amount of rotation of the z-axis. 433 * @param {int} value The amount of rotation along the z-axis. 434 * @return {void} none 435 * @name setRotationZ 436 * @function 437 */ 438 setRotationZ : function( value ){ 439 return this.each(function(){ 440 if(isNaN($(this).data('rotationZ'))){ 441 init(this); 442 $(this).transform('setRotationZ', value); 443 } 444 else{ 445 $(this).data({ 'rotationZ' : value }); 446 updateTransform(this); 447 } 448 }); 449 }, 450 451 /** 452 * Translates the element along the x axis. 453 * @param {int} value The amount to translate on the x-axis 454 * @return {void} none 455 * @name translateX 456 * @function 457 */ 458 translateX : function( value ){ 459 return this.each(function(){ 460 if(isNaN($(this).data('x'))){ 461 init(this); 462 $(this).transform('translateX', value); 463 } 464 else{ 465 $(this).data({ 'x' : $(this).data('x') + value }); 466 updateTransform(this); 467 } 468 }); 469 }, 470 471 /** 472 * Translates the element along the x, y, and z-axis. 473 * @param {int} x The amount of translation along x-axis. 474 * @param {int} y The amount of translation along y-axis. 475 * @param {int} z The amount of translation along z-axis. 476 * @return {void} none 477 * @name translateXYZ 478 * @function 479 */ 480 translateXYZ : function( x, y, z ){ 481 return this.each(function(){ 482 if(isNaN($(this).data('x')) || isNaN($(this).data('y')) || isNaN($(this).data('z'))){ 483 init(this); 484 $(this).transform('translateXYZ', x, y, z); 485 } 486 else{ 487 $(this).data({ 'x' : $(this).data('x') + x }); 488 $(this).data({ 'y' : $(this).data('y') + y }); 489 $(this).data({ 'z' : $(this).data('z') + z }); 490 updateTransform(this); 491 } 492 }); 493 }, 494 495 /** 496 * Translates the element along the y axis. 497 * @param {int} value The amount to translate on the y-axis 498 * @return {void} none 499 * @name translateY 500 * @function 501 */ 502 translateY : function( value ){ 503 return this.each(function(){ 504 if(isNaN($(this).data('y'))){ 505 init(this); 506 $(this).transform('translateY', value); 507 } 508 else{ 509 $(this).data({ 'y' : $(this).data('y') + value }); 510 updateTransform(this); 511 } 512 }); 513 }, 514 515 /** 516 * Translates the element along the z axis. 517 * @param {int} value The amount to translate on the z-axis 518 * @return {void} none 519 * @name translateZ 520 * @function 521 */ 522 translateZ : function( value ){ 523 return this.each(function(){ 524 if(isNaN($(this).data('z'))){ 525 init(this); 526 $(this).transform('translateZ', value); 527 } 528 else{ 529 $(this).data({ 'z' : $(this).data('z') + value }); 530 updateTransform(this); 531 } 532 }); 533 } 534 }; 535 536 /** 537 * Updates the webkit, moz, and transform transformation of the element based on stored data. 538 * @param {DOM element} element The element to transform. 539 * @return {void} none 540 * @name updateTransform 541 * @function 542 */ 543 function updateTransform(element){ 544 $(element).css({ "-webkit-transition": "-webkit-transform " + $(element).data('animationDuration') + "s", 545 "-webkit-transform-style": "preserve-3d", 546 "-webkit-transform": "translateX(" + $(element).data('x') + "px)" + " translateY(" + $(element).data('y') + "px)" + " translateZ(" + $(element).data('z') + "px)" + " scale(" + $(element).data('scale') + ")" + " rotateX(" + $(element).data('rotationX') + "deg)" + " rotateY(" + $(element).data('rotationY') + "deg)" + " rotateZ(" + $(element).data('rotationZ') + "deg)", 547 "-moz-transform": "translateX(" + $(element).data('x') + "px)" + " translateY(" + $(element).data('y') + "px)" + " translateZ(" + $(element).data('z') + "px)" + " scale(" + $(element).data('scale') + ")" + " rotateX(" + $(element).data('rotationX') + "deg)" + " rotateY(" + $(element).data('rotationY') + "deg)" + " rotateZ(" + $(element).data('rotationZ') + "deg)", 548 "-moz-transition": "-moz-transform " + $(element).data('animationDuration') + "s", 549 "-moz-transform-style": "preserve-3d", 550 "transform": "translateX(" + $(element).data('x') + "px)" + " translateY(" + $(element).data('y') + "px)" + " translateZ(" + $(element).data('z') + "px)" + " scale(" + $(element).data('scale') + ")" + " rotateX(" + $(element).data('rotationX') + "deg)" + " rotateY(" + $(element).data('rotationY') + "deg)" + " rotateZ(" + $(element).data('rotationZ') + "deg)", 551 "transition": "transform " + $(element).data('animationDuration') + "s", 552 "transform-style": "preserve-3d", 553 }); 554 } 555 556 /** 557 * Sets 3D data corresponding to a DOM element. 558 * @param {element} element the element to update. 559 * @param {int} rotationX 560 * @param {int} rotationY 561 * @param {int} rotationZ 562 * @param {int} x 563 * @param {int} y 564 * @param {int} z 565 * @param {int} scale 566 * @param {int} animationDuration 567 * @param {int} width 568 * @param {int} height 569 * @return {void} none 570 * @name init 571 * @function 572 */ 573 function init(element, options){ 574 // default values 575 defaults = { 576 x: 0, 577 y: 0, 578 z: 0, 579 rotationX: 0, 580 rotationY: 0, 581 rotationZ: 0, 582 scale: 1, 583 animationDuration: 0.01, 584 width: $(element).outerWidth(), 585 height: $(element).outerHeight() 586 }; 587 // override defaults values with those passed in by the user 588 options = $.extend(defaults, options); 589 590 //trigger 3D hardware accelleration 591 $(element).css({"-webkit-transition": "translateZ(0px) translateX(0px) translateY(0px)", "-webkit-transform-style": "preserve-3d", "-moz-transition": "translateZ(0px) translateX(0px) translateY(0px)", "-moz-transform-style": "preserve-3d", "transition": "translateZ(0px) translateX(0px) translateY(0px)", "transform-style": "preserve-3d",}); 592 593 //store the data associated with the dom element. 594 $(element).data({ 595 "x" : options.x, 596 "y" : options.y, 597 "z" : options.z, 598 "rotationX" : options.rotationX, 599 "rotationY" : options.rotationY, 600 "rotationZ" : options.rotationX, 601 "scale": 1, 602 "animationDuration": options.animationDuration, 603 "width" : options.width, 604 "height" : options.height 605 }); 606 } 607 608 /** 609 * Extending the jQuery namespace for the plugin. 610 * @param {string} method The method to call. 611 * @return {void} none 612 * @name $.fn.tranform 613 * @function 614 */ 615 $.fn.transform = function( method ) { 616 if ( methods[method] ) { 617 return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); 618 } 619 else if ( typeof method === 'object' || ! method ) { 620 return methods.init.apply( this, arguments ); 621 } 622 else { 623 $.error( 'Method ' + method + ' does not exist on jQuery.transform' ); 624 } 625 }; 626 })( jQuery );