1 /* 2 * Sprite3D.js 3 * Visit the internets for documentation, updates and examples. 4 * https://github.com/boblemarin/Sprite3D.js 5 * http://minimal.be/lab/Sprite3D 6 * 7 * Copyright (c) 2010 boblemarin emeric@minimal.be http://www.minimal.be 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 * Creates an instance of Sprite3D 33 * 34 * @constructor 35 * @author boblemarin 36 * @this {Sprite3D} 37 * @param {Object} element The DOM element to wrap the Sprite3D object around. When no element is provided, a empty div is created and added to the document. 38 */ 39 function Sprite3D(element) { 40 41 if ( !Sprite3D.prototype._isInit ) Sprite3D.isSupported(); 42 43 // private variables 44 var p = "", 45 s = "", 46 rx = "", 47 ry = "", 48 rz = "", 49 ts = "", 50 i, 51 alpha = 1; 52 // listeners = {}; 53 54 this.listeners = {}; 55 56 // create an empty <div> if no element is provided 57 if (element == null) { element = document.createElement("div"); } 58 59 // prepare for 3D positionning 60 element.style[ this._browserPrefix + "TransformStyle" ] = "preserve-3d"; 61 element.style.margin = "0px"; 62 element.style.padding = "0px"; 63 element.style.position = "absolute"; 64 65 // trigger hardware acceleration even if no property is set 66 element.style[ this._transformProperty ] = "translateZ(0px)"; 67 68 // debug style 69 //element.style.border = '1px solid red'; 70 this.domElement = element; 71 this.style = element.style; 72 this.children = []; 73 } 74 75 /** The X-axis position of the Sprite3D */ 76 Sprite3D.prototype.x = 0; 77 /** The Y-axis position of the Sprite3D */ 78 Sprite3D.prototype.y = 0; 79 /** The Z-axis position of the Sprite3D */ 80 Sprite3D.prototype.z = 0; 81 82 /** The X-axis rotation of the Sprite3D */ 83 Sprite3D.prototype.rotationX = 0; 84 /** The Y-axis rotation of the Sprite3D */ 85 Sprite3D.prototype.rotationY = 0; 86 /** The Z-axis rotation of the Sprite3D */ 87 Sprite3D.prototype.rotationZ = 0; 88 89 /** The X-axis scale of the Sprite3D */ 90 Sprite3D.prototype.scaleX = 1; 91 /** The Y-axis scale of the Sprite3D */ 92 Sprite3D.prototype.scaleY = 1; 93 /** The Z-axis scale of the Sprite3D */ 94 Sprite3D.prototype.scaleZ = 1; 95 96 /** The width of the HTML element associated with the Sprite3D object */ 97 Sprite3D.prototype.width = 0; 98 /** The height of the HTML element associated with the Sprite3D object */ 99 Sprite3D.prototype.height = 0; 100 101 /** The X-axis registration point of the Sprite3D object used for 3D positionning */ 102 Sprite3D.prototype.regX = 0; 103 /** The Y-axis registration point of the Sprite3D object used for 3D positionning */ 104 Sprite3D.prototype.regY = 0; 105 /** The Y-axis registration point of the Sprite3D object used for 3D positionning */ 106 Sprite3D.prototype.regZ = 0; 107 108 /** The width (in pixels) of the tiles in the spritesheet */ 109 Sprite3D.prototype.tileWidth = 0; 110 /** The height (in pixels) of the tiles in the spritesheet */ 111 Sprite3D.prototype.tileHeight = 0; 112 113 /** A reference to the DOM element associated with this Sprite3D object */ 114 Sprite3D.prototype.domElement = null; 115 116 /** A reference to the CSS style object of the DOM element */ 117 Sprite3D.prototype.style = null; 118 119 /** An array holding references of the Sprite3D's children object */ 120 Sprite3D.prototype.children = []; 121 122 /** The number of child objects */ 123 Sprite3D.prototype.numChildren = 0; 124 125 /** A boolean value to decide in which order transformations are applied. If true, rotations are applied before translations. If false, translations are applied before rotations. For a more accurate control over transformations order, you should use the transformString property. This property is now BROKEN. */ 126 Sprite3D.prototype.rotateFirst = false; 127 128 /** The transform string. You can use this property to fine control the order in which transformations are applied. 129 * The following values will be replaced by their respective transformations : 130 * _p for position/translations 131 * _s for scaling 132 * _rx for rotationX 133 * _ry for rotationY 134 * _rz for rotationZ 135 * Example: sprite.transformString = "_rx _ry _rz _p _s"; 136 */ 137 Sprite3D.prototype.transformString = "_p _rx _ry _rz _s"; 138 139 /** 140 * Sets the value of the transformString property, allowing to control transformations order. 141 * A valid value may be "_rx _ry _rz _p _s". See the transformString property for more informations. 142 * @param {String} ts The string that will be used to swap 143 * @return {Sprite3D} The reference to this Sprite3D object 144 */ 145 Sprite3D.prototype.setTransformString = function(ts) { 146 this.transformString = ts; 147 return this; 148 }; 149 150 /** 151 * Sets the X-axis position of the Sprite3D. 152 * @param {Number} px The position 153 * @return {Sprite3D} The reference to this Sprite3D object 154 */ 155 Sprite3D.prototype.setX = function(px) { 156 this.x = px; 157 return this; 158 }; 159 160 /** 161 * Sets the Y-axis position of the Sprite3D. 162 * @param {Number} py The position 163 * @return {Sprite3D} The reference to this Sprite3D object 164 */ 165 Sprite3D.prototype.setY = function(py) { 166 this.y = py; 167 return this; 168 }; 169 170 /** 171 * Sets the Z-axis position of the Sprite3D. 172 * @param {Number} pz The position 173 * @return {Sprite3D} The reference to this Sprite3D object 174 */ 175 Sprite3D.prototype.setZ = function(pz) { 176 this.z = pz; 177 return this; 178 }; 179 180 /** 181 * Sets the 3D position of the Sprite. 182 * @param {Number} px The position on the X-axis 183 * @param {Number} py The position on the Y-axis 184 * @param {Number} pz The position on the Z-axis 185 * @return {Sprite3D} The reference to this Sprite3D object 186 */ 187 Sprite3D.prototype.setPosition = function(px, py, pz) { 188 this.x = px; 189 this.y = py; 190 this.z = pz; 191 return this; 192 }; 193 194 /** 195 * Applies a relative translation in 3D space on the X-axis. 196 * @param {Number} px The value of the translation 197 * @return {Sprite3D} The reference to this Sprite3D object 198 */ 199 Sprite3D.prototype.moveX = function(px) { 200 this.x += px; 201 return this; 202 }; 203 204 /** 205 * Applies a relative translation in 3D space on the Y-axis. 206 * @param {Number} py The value of the translation 207 * @return {Sprite3D} The reference to this Sprite3D object 208 */ 209 Sprite3D.prototype.moveY = function(py) { 210 this.y += py; 211 return this; 212 }; 213 214 /** 215 * Applies a relative translation in 3D space on the Z-axis. 216 * @param {Number} pz The value of the translation 217 * @return {Sprite3D} The reference to this Sprite3D object 218 */ 219 Sprite3D.prototype.moveZ = function(pz) { 220 this.z += pz; 221 return this; 222 }; 223 224 /** 225 * Applies a relative translation in 3D space. 226 * @param {Number} px The value of the translation on the X-axis 227 * @param {Number} py The value of the translation on the Y-axis 228 * @param {Number} pz The value of the translation on the Z-axis 229 * @return {Sprite3D} The reference to this Sprite3D object 230 */ 231 Sprite3D.prototype.move = function(px, py, pz) { 232 this.x += px; 233 this.y += py; 234 this.z += pz; 235 return this; 236 }; 237 238 239 240 /** 241 * Sets the amount of rotation around the X-axis of the Sprite3D. 242 * @param {Number} rx The value of the rotation 243 * @return {Sprite3D} The reference to this Sprite3D object 244 */ 245 Sprite3D.prototype.setRotationX = function(rx) { 246 this.rotationX = rx; 247 return this; 248 }; 249 250 /** 251 * Sets the amount of rotation around the Y-axis of the Sprite3D. 252 * @param {Number} ry The value of the rotation 253 * @return {Sprite3D} The reference to this Sprite3D object 254 */ 255 Sprite3D.prototype.setRotationY = function(ry) { 256 this.rotationY = ry; 257 return this; 258 }; 259 260 /** 261 * Sets the amount of rotation around the Z-axis of the Sprite3D. 262 * @param {Number} rz The value of the rotation 263 * @return {Sprite3D} The reference to this Sprite3D object 264 */ 265 Sprite3D.prototype.setRotationZ = function(rz) { 266 this.rotationZ = rz; 267 return this; 268 }; 269 270 /** 271 * Sets the 3D rotation of the Sprite. 272 * @param {Number} rx The rotation around the X-axis 273 * @param {Number} ry The rotation around the Y-axis 274 * @param {Number} rz The rotation around the Z-axis 275 * @return {Sprite3D} The reference to this Sprite3D object 276 */ 277 Sprite3D.prototype.setRotation = function(rx, ry, rz) { 278 this.rotationX = rx; 279 this.rotationY = ry; 280 this.rotationZ = rz; 281 return this; 282 }; 283 284 285 /** 286 * Applies a relative rotation in 3D space around the X-axis. 287 * @param {Number} rx The value of the rotation 288 * @return {Sprite3D} The reference to this Sprite3D object 289 */ 290 Sprite3D.prototype.rotateX = function(rx) { 291 this.rotationX += rx; 292 return this; 293 }; 294 295 /** 296 * Applies a relative rotation in 3D space around the Y-axis. 297 * @param {Number} ry The value of the rotation 298 * @return {Sprite3D} The reference to this Sprite3D object 299 */ 300 Sprite3D.prototype.rotateY = function(ry) { 301 this.rotationY += ry; 302 return this; 303 }; 304 305 /** 306 * Applies a relative rotation in 3D space around the Z-axis. 307 * @param {Number} rz The value of the rotation 308 * @return {Sprite3D} The reference to this Sprite3D object 309 */ 310 Sprite3D.prototype.rotateZ = function(rz) { 311 this.rotationZ += rz; 312 return this; 313 }; 314 315 /** 316 * Applies a relative rotation in 3D space. 317 * @param {Number} rx The value of the rotation around the X-axis 318 * @param {Number} ry The value of the rotation around the Y-axis 319 * @param {Number} rz The value of the rotation around the Z-axis 320 * @return {Sprite3D} The reference to this Sprite3D object 321 */ 322 Sprite3D.prototype.rotate = function(rx, ry, rz) { 323 this.rotationX += rx; 324 this.rotationY += ry; 325 this.rotationZ += rz; 326 return this; 327 }; 328 329 /** 330 * Sets the scaling of the Sprite3D object on the X-axis. 331 * @param {Number} sx The value of the scaling on the X-axis 332 * @return {Sprite3D} The reference to this Sprite3D object 333 */ 334 Sprite3D.prototype.setScaleX = function( sx ) { 335 this.scaleX = sx; 336 return this; 337 }; 338 339 /** 340 * Sets the scaling of the Sprite3D object on the Y-axis. 341 * @param {Number} sy The value of the scaling on the Y-axis 342 * @return {Sprite3D} The reference to this Sprite3D object 343 */ 344 Sprite3D.prototype.setScaleY = function( sy ) { 345 this.scaleY = sy; 346 return this; 347 }; 348 349 /** 350 * Sets the scaling of the Sprite3D object on the Z-axis. 351 * @param {Number} sz The value of the scaling on the Z-axis 352 * @return {Sprite3D} The reference to this Sprite3D object 353 */ 354 Sprite3D.prototype.setScaleZ = function( sz ) { 355 this.scaleZ = sz; 356 return this; 357 }; 358 359 /** 360 * Sets the scaling of the Sprite3D object on the 3 axis. 361 * @param {Number} sx The value of the scaling on the X-axis 362 * @param {Number} sy The value of the scaling on the Y-axis 363 * @param {Number} sz The value of the scaling on the Z-axis 364 * @return {Sprite3D} The reference to this Sprite3D object 365 */ 366 Sprite3D.prototype.setScale = function( sx, sy, sz ) { 367 this.scaleX = sx; 368 this.scaleY = sy; 369 this.scaleZ = sz; 370 return this; 371 }; 372 373 /** 374 * Sets the registrations point for the Sprite3D object. 375 * By default, CSS positionning is relative to the top left corner of the element. 376 * The registration point values are simply substracted from the position when applied 377 * @param {Number} rx The registration point value for the X-axis 378 * @param {Number} ry The registration point value for the Y-axis 379 * @param {Number} rz The registration point value for the Z-axis 380 * @return {Sprite3D} The reference to this Sprite3D object 381 */ 382 Sprite3D.prototype.setRegistrationPoint = function(rx, ry, rz) { 383 this.regX = rx; 384 this.regY = ry; 385 this.regZ = rz; 386 return this; 387 }; 388 389 /** 390 * Sets the origin of the 3D transforms. 391 * By default, CSS transforms are relative to the center of the element. 392 * @param {Number} px The transform origin value for the X-axis 393 * @param {Number} py The transform origin value for the Y-axis 394 * @return {Sprite3D} The reference to this Sprite3D object 395 */ 396 Sprite3D.prototype.setTransformOrigin = function(px, py) { 397 // this.style.webkitTransformOrigin = px + " " + py; 398 this.style[ this._browserPrefix + "TransformOrigin" ] = px + " " + py; 399 return this; 400 }; 401 402 403 /** 404 * Sets the size of the HTML element linked to the Sprite3D object, using the width and height css properties. 405 * Note that animating using these properties does not provide an optimal performance. 406 * You should rather try to use CSS scale using the scale() method 407 * This method applies the changes to the style object, so it does not require a call to the update methods 408 * @param {Number} width The desired width 409 * @param {Number} height The desired height 410 * @return {Sprite3D} The reference to this Sprite3D object 411 */ 412 Sprite3D.prototype.setSize = function(width, height) { 413 this.style.width = (this.width = width) + "px"; 414 this.style.height = (this.height = height) + "px"; 415 return this; 416 }; 417 418 /** 419 * Sets the opacity of the element. 420 * This method applies the changes to the style object, so it does not require a call to the update methods 421 * @param {Number} alpha The desired opacity, ranging from 0 to 1 422 * @return {Sprite3D} The reference to this Sprite3D object 423 */ 424 Sprite3D.prototype.setOpacity = function(alpha) { 425 this.style.opacity = this.alpha = alpha; 426 return this; 427 }; 428 429 /** 430 * Returns the opacity of the element. 431 * @return {Number} The opacity of the element 432 */ 433 Sprite3D.prototype.getOpacity = function() { 434 return this.alpha; 435 }; 436 437 /** 438 * Sets the CSS class name of the DOM element associated with the Sprite3D object. 439 * When applying multiple class names, provide a single string with space-separated class names like you would do in pure CSS manipulation. 440 * This method does not require a call to the update methods. 441 * @param {String} className The name of the class to be set 442 * @return {Sprite3D} The reference to this Sprite3D object 443 */ 444 Sprite3D.prototype.setClassName = function(className) { 445 this.domElement.className = className; 446 return this; 447 }; 448 449 /** 450 * Returns the name of the CSS class of the DOM element. 451 * @return {String} The CSS class name 452 */ 453 Sprite3D.prototype.getClassName = function() { 454 return this.domElement.className; 455 }; 456 457 /** 458 * Adds a CSS class to the DOM element 459 * This method does not require a call to the update methods. 460 * @param {String} className The name of the class to be added 461 * @return {Sprite3D} The reference to this Sprite3D object 462 */ 463 Sprite3D.prototype.addClassName = function(className) { 464 this.domElement.className += " " + className + " "; 465 return this; 466 }; 467 468 /** 469 * [BETA] Removes a CSS class from the DOM element 470 * This method does not require a call to the update methods. 471 * @param {String} className The name of the class to be removed 472 * @return {Sprite3D} The reference to this Sprite3D object 473 */ 474 Sprite3D.prototype.removeClassName = function(className) { 475 this.domElement.className = this.domElement.className.replace(className, ''); 476 //this.domElement.className += " " + className; 477 return this; 478 }; 479 480 /** 481 * Sets the ID of the DOM element in the document. 482 * This method is just a helper allowing neverending chaining in the Sprite3D creation syntax. 483 * You can also simply access the <code>domElement</code> property of the Sprite3D and set its <code>id</code> property. 484 * This method does not require a call to the update methods. 485 * @param {String} id The ID 486 * @return {Sprite3D} The reference to this Sprite3D object 487 */ 488 Sprite3D.prototype.setId = function(id) { 489 this.domElement.id = id; 490 return this; 491 }; 492 493 /** 494 * Returns the ID of the DOM element associated with the Sprite3D. 495 * @return {String} The CSS class name 496 */ 497 Sprite3D.prototype.getId = function() { 498 return this.domElement.id; 499 }; 500 501 /** 502 * Allows to set any value in any CSS property of the style object of the DOM element. 503 * This method is just a helper allowing neverending chaining in the Sprite3D creation syntax. 504 * For one time modifications, you can simply use the <code>style</code> property of the Sprite3D. 505 * This method does not require a call to the update methods. 506 * @param {String} name The name of the CSS property in which the value will be stored 507 * @param {String} value The value to assign to the property 508 * @return {Sprite3D} The reference to this Sprite3D object 509 */ 510 Sprite3D.prototype.setCSS = function(name, value) { 511 this.domElement.style[name] = value; 512 return this; 513 }; 514 515 /** 516 * Returns the value assigned to the provided CSS property. 517 * @param {String} name The name of the property to get the value from 518 * @return {String} The value of the CSS property 519 */ 520 Sprite3D.prototype.getCSS = function(name) { 521 return this.domElement.style[name]; 522 }; 523 524 /** 525 * Allows direct write access to the innerHTML property of the DOM element. 526 * @param {String} value The string to write into the innerHTML property 527 * @return {Sprite3D} The reference to this Sprite3D object 528 */ 529 Sprite3D.prototype.setInnerHTML = function(value) { 530 this.domElement.innerHTML = value; 531 return this; 532 }; 533 534 535 /** 536 * Sets the size of the tiles in the spritesheet used as background image. 537 * @param {Number} width The desired width 538 * @param {Number} height The desired height 539 * @return {Sprite3D} The reference to this Sprite3D object 540 */ 541 Sprite3D.prototype.setTileSize = function(width, height) { 542 this.tileWidth = width; 543 this.tileHeight = height; 544 return this; 545 }; 546 547 /** 548 * Modifies the sprites's background image position to display the selected tile. 549 * For this method to work, you are supposed to set a background image and limit the size of the element using CSS styles, 550 * and use a sprite sheet where all tiles have the same size. No checking is performed on the provided values. 551 * @param {Number} tilePosX The horizontal index of the tile to be displayed 552 * @param {Number} tilePosY The vertical index of the tile to be displayed 553 * @return {Sprite3D} The reference to this Sprite3D object 554 */ 555 Sprite3D.prototype.setTilePosition = function(tilePosX, tilePosY) { 556 this.style.backgroundPosition = "-" + (tilePosX * this.tileWidth) + "px -" + (tilePosY * this.tileHeight) + "px"; 557 return this; 558 }; 559 560 /** 561 * Allows to set a arbitary property value while using the chaining syntax. 562 * @param {String} label The name of the property 563 * @param {Object} value The value for that property 564 * @return {Sprite3D} The reference to this Sprite3D object 565 */ 566 Sprite3D.prototype.setProperty = function(label, value) { 567 this[label] = value; 568 return this; 569 }; 570 571 /** 572 * Sets the order in which transformations are applied. 573 * If true, rotations are applied before translations. If false, translations are applied before rotations. 574 * Note that, when applying rotations, the axis of the object rotate, and subsequent translations follow the modified orientation of the axis. 575 * For a more accurate control, you should use the transformString property. 576 * @param {boolean} rf true to rotate first, false to translate first 577 * @return {Sprite3D} The reference to this Sprite3D object 578 */ 579 Sprite3D.prototype.setRotateFirst = function(rf) { 580 this.rotateFirst = rf; 581 if ( rf ) { 582 this.transformString = "_rx _ry _rz _p _s"; 583 } else { 584 this.transformString = "_p _rz _ry _rx _s"; 585 } 586 return this; 587 }; 588 589 /** 590 * Applies position and rotation values. 591 * @return {Sprite3D} The reference to this Sprite3D object 592 */ 593 Sprite3D.prototype.update = function() { 594 this.p = "translate3d(" + (this.x - this.regX) + "px," + (this.y - this.regY) + "px," + (this.z - this.regZ) + "px) "; 595 this.rx = "rotateX(" + this.rotationX + "deg) "; 596 this.ry = "rotateY(" + this.rotationY + "deg) "; 597 this.rz = "rotateZ(" + this.rotationZ + "deg) "; 598 this.s = "scale3d(" + this.scaleX + ", " + this.scaleY + ", " + this.scaleX + ") "; 599 /* 600 if (this.rotateFirst) 601 this.style.webkitTransform = this.rz + this.ry + this.rx + this.p + this.s; 602 else 603 this.style.webkitTransform = this.p + this.rx + this.ry + this.rz + this.s; 604 */ 605 606 // var transformString = "_rx _ry _rz _p _s"; 607 this.ts = this.transformString; 608 this.ts = this.ts.replace( "_p", this.p ); 609 this.ts = this.ts.replace( "_rx", this.rx ); 610 this.ts = this.ts.replace( "_ry", this.ry ); 611 this.ts = this.ts.replace( "_rz", this.rz ); 612 this.ts = this.ts.replace( "_s", this.s ); 613 //this.style.webkitTransform = this.ts; 614 this.style[this._transformProperty] = this.ts; 615 616 return this; 617 }; 618 619 620 /** 621 * Applies 2D position, rotation and scaling values. 622 * This method allows to use Sprite3D with browsers that only support 2D transforms. 623 * When applying the transforms, it uses the x and y position, z rotation and x and y scaling. 624 * The other values are ignored. 625 * @return {Sprite3D} The reference to this Sprite3D object 626 */ 627 Sprite3D.prototype.update2D = function() { 628 this.p = "translate(" + (this.x - this.regX) + "px," + (this.y - this.regY) + "px) "; 629 this.rz = "rotate(" + this.rotationZ + "deg) "; 630 this.s = "scale(" + this.scaleX + ", " + this.scaleY + ") "; 631 632 this.ts = this.transformString; 633 this.ts = this.ts.replace( "_p", this.p ); 634 this.ts = this.ts.replace( "_rx", "" ); 635 this.ts = this.ts.replace( "_ry", "" ); 636 this.ts = this.ts.replace( "_rz", this.rz ); 637 this.ts = this.ts.replace( "_s", this.s ); 638 //this.style.webkitTransform = this.ts; 639 this.style[this._transformProperty] = this.ts; 640 641 //console.log( "apply 2D transforms using " + this._transformProperty ); 642 643 return this; 644 }; 645 646 647 /** 648 * Applies position and rotation values, as well as opacity and size. 649 * @return {Sprite3D} The reference to this Sprite3D object 650 */ 651 Sprite3D.prototype.updateAll = function() { 652 this.update(); 653 this.style.opacity = this.alpha; 654 this.style.width = this.width + "px"; 655 this.style.height = this.height + "px"; 656 return this.update(); 657 }; 658 659 660 /** 661 * Calls the update() method on every child of the Sprite3D object. 662 * @return {Sprite3D} The reference to this Sprite3D object 663 */ 664 Sprite3D.prototype.updateChildren = function() { 665 for (this.i = 0; this.i < this.numChildren; this.i++) { 666 this.children[this.i].update(); 667 } 668 return this; 669 }; 670 671 /** 672 * Calls the updateAll() method on every child of the Sprite3D object. 673 * @return {Sprite3D} The reference to this Sprite3D object 674 */ 675 Sprite3D.prototype.updateChildrenAll = function() { 676 for (this.i = 0; this.i < this.numChildren; this.i++) { 677 this.children[this.i].updateAll(); 678 } 679 return this; 680 }; 681 682 /** 683 * Updates itself, then calls the update() method on every child of the Sprite3D object. 684 * @param {boolean} recursive If set to true, make the update call recursive, update every child's children 685 * @return {Sprite3D} The reference to this Sprite3D object 686 */ 687 Sprite3D.prototype.updateWithChildren = function(recursive) { 688 this.update(); 689 690 for (this.i = 0; this.i < this.numChildren; this.i++) { 691 if (recursive) { 692 this.children[this.i].updateWithChildren(recursive); 693 } else { 694 this.children[this.i].update(); 695 } 696 } 697 698 return this; 699 }; 700 701 /** 702 * Adds a Sprite3D object to this Sprite3D children. 703 * @param {Sprite3D} e The Sprite3D object to add 704 * @return {Sprite3D} The reference to the added Sprite3D object 705 */ 706 Sprite3D.prototype.addChild = function(e) { 707 this.numChildren = this.children.push(e); 708 this.domElement.appendChild(e.domElement); 709 return e; 710 }; 711 712 /** 713 * Removes a Sprite3D object from this Sprite3D children. 714 * @param {Sprite3D} child The Sprite3D object to remove 715 * @return {Sprite3D} The reference to the removed Sprite3D object. null if the child was not found in this Sprite3D children list 716 */ 717 Sprite3D.prototype.removeChild = function(child) { 718 var n = this.children.indexOf(child); 719 if (n > -1) { 720 return this.removeChildAt(n); 721 } 722 return null; 723 }; 724 725 /** 726 * Removes the nth Sprite3D object from this Sprite3D children. 727 * @param {number} n The index of the Sprite3D object to remove 728 * @return {Sprite3D} The reference to the removed Sprite3D object. 729 */ 730 Sprite3D.prototype.removeChildAt = function(n) { 731 --this.numChildren; 732 this.domElement.removeChild(this.children[n].domElement); 733 return this.children.splice(n, 1)[0]; 734 }; 735 736 /** 737 * Finds and return the Sprite3D object associated with the provided DOM element 738 * @param {Object} element The DOM element 739 * @return {Sprite3D} The reference to the associated Sprite3D object. Returns null if no relevant Sprite3D object was found 740 */ 741 Sprite3D.prototype.findFromDOMElement = function(element) { 742 for (this.i = 0; this.i < this.numChildren; this.i++) { 743 if (element == this.children[this.i].domElement) { return this.children[this.i]; } 744 } 745 return null; 746 }; 747 748 749 Sprite3D.prototype.listeners = {}; 750 751 /** 752 * Adds an event listener to the DOM element for the provided event id. 753 * @param {String} event The name of the event to watch 754 * @param {Function} callback The callback function 755 * @return {Sprite3D} The reference to this Sprite3D object 756 */ 757 Sprite3D.prototype.addEventListener = function(event, callback) { 758 var fname = event + "_" + callback.name; 759 if ( this.listeners[fname] == null ) { 760 var sprite = this; 761 var fn = function(e) { callback(e, sprite); } 762 this.listeners[fname] = fn; 763 this.domElement.addEventListener(event, fn ); 764 } 765 return this; 766 }; 767 768 /** 769 * Removes an event listener to the DOM element for the provided event id. 770 * @param {String} event The name of the event to watch 771 * @param {Function} callback The callback function 772 * @return {Sprite3D} The reference to this Sprite3D object 773 */ 774 Sprite3D.prototype.removeEventListener = function(event, callback) { 775 var fname = event + "_" + callback.name; 776 if ( this.listeners[fname] != null ) { 777 this.domElement.removeEventListener(event, this.listeners[fname] ); 778 delete this.listeners[fname]; 779 } 780 return this; 781 }; 782 783 784 /** 785 * Creates a centered empty HTML div element to be used as root container for the other Sprite3D objects. 786 * @return {Sprite3D} The created Sprite3D object 787 */ 788 Sprite3D.createCenteredContainer = function() { 789 var c = document.createElement('div'), 790 s = c.style; 791 792 if ( !Sprite3D.prototype._isInit ) Sprite3D.isSupported(); 793 794 s[Sprite3D.prototype._browserPrefix+"Perspective"] = "800" + (Sprite3D.prototype._browserPrefix=="Moz"?"px":""); 795 s[Sprite3D.prototype._browserPrefix+"PerspectiveOrigin"] = "0 0"; 796 s[Sprite3D.prototype._browserPrefix+"TransformOrigin"] = "0 0"; 797 s[Sprite3D.prototype._browserPrefix+"Transform"] = "translateZ(0px)"; 798 799 s.position = "absolute"; 800 s.top = "50%"; 801 s.left = "50%"; 802 s.margin = "0px"; 803 s.padding = "0px"; 804 //s.border = "1px solid red"; // <- this one is for debug 805 document.body.appendChild(c); 806 807 return new Sprite3D(c); 808 }; 809 810 /** 811 * Creates a top-left aligned empty HTML div element to be used as root container for the other Sprite3D objects. 812 * @return {Sprite3D} The created Sprite3D object 813 */ 814 Sprite3D.createTopLeftCenteredContainer = function() { 815 var c = document.createElement('div'), 816 s = c.style; 817 818 if ( !Sprite3D.prototype._isInit ) Sprite3D.isSupported(); 819 820 s[Sprite3D.prototype._browserPrefix+"Perspective"] = "800" + (Sprite3D.prototype._browserPrefix=="Moz"?"px":""); 821 //s[Sprite3D.prototype._browserPrefix+"PerspectiveOrigin"] = "0 0"; 822 //s[Sprite3D.prototype._browserPrefix+"TransformOrigin"] = "0 0"; 823 s[Sprite3D.prototype._browserPrefix+"Transform"] = "translateZ(0px)"; 824 825 826 //s.webkitPerspective = "800"; 827 // s.webkitPerspectiveOrigin = "0 0"; 828 // s.webkitTransformOrigin = "0 0"; 829 //s.webkitTransform = "translateZ(0px)"; 830 s.position = "relative"; 831 /* 832 s.position = "absolute"; 833 s.top = "0px"; 834 s.left = "0px"; 835 s.right = "0px" 836 s.bottom = "0px" 837 s.margin = "0px"; 838 s.padding = "0px"; 839 s.border = "1px solid red"; 840 */ 841 /* i left all those comments above because they might be useful in some use cases */ 842 document.body.appendChild(c); 843 844 return new Sprite3D(c); 845 }; 846 847 848 /** Private static property. Used internally for browser checking. You should not change its value. */ 849 Sprite3D.prototype._isInit = false; 850 851 /** Private static property. Used internally for cross-browser compatibility. You should not change its value. */ 852 Sprite3D.prototype._transformProperty = "webkitTransform"; 853 854 /** Private static property. Used internally for cross-browser compatibility. You should not change its value. */ 855 Sprite3D.prototype._browserPrefix = "webkit"; 856 857 /** 858 * Test for CSS 3D transforms support in the current browser. 859 * If 3D transforms are not supported, the update() method is replaced by the update2D() method, 860 * providing an automatic fallback that might save some bits :) 861 * @return {boolean} True if the 3D transforms are supported by the browser 862 */ 863 Sprite3D.isSupported = function() { 864 var d = document.createElement("div"), 865 prefixes = ["", "webkit", "Moz", "o", "ms" ], 866 n = prefixes.length, i; 867 868 // check for 3D transforms 869 for( i = 0; i < n; i++ ) { 870 if ( ( prefixes[i] + "Perspective" ) in d.style ) { 871 Sprite3D.prototype._transformProperty = prefixes[i] + "Transform"; 872 Sprite3D.prototype._isInit = true; 873 Sprite3D.prototype._browserPrefix = prefixes[i]; 874 //console.log( "found support for 3D transforms using prefix: " + prefixes[i] ); 875 return true; 876 } 877 } 878 879 // check for 2D transforms 880 for( i = 0; i < n; i++ ) { 881 if ( ( prefixes[i] + "Transform" ) in d.style ) { 882 Sprite3D.prototype._transformProperty = prefixes[i] + "Transform"; 883 Sprite3D.prototype._isInit = true; 884 Sprite3D.prototype._browserPrefix = prefixes[i]; 885 Sprite3D.prototype.update = Sprite3D.prototype.update2D; 886 //console.log( "found support for 2D transforms using prefix: " + prefixes[i] ); 887 return false; 888 } 889 } 890 //console.log( "no support for CSS transforms."); 891 return false; 892 }; 893