Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 5616e5bc1bb6118969cba3c6fa88bc0a206af340 0 parents
@boblemarin authored
514 assets/Sprite3D.js
@@ -0,0 +1,514 @@
+/*
+* Sprite3D.js - v2 (1)
+* Visit the internets for documentation, updates and examples.
+* https://github.com/boblemarin/Sprite3D.js
+* http://minimal.be/lab/Sprite3D
+*
+* (1) this is a working version of Sprite3D 2.0,
+* it is not yet finished. Please go to the githu
+* repo to get the most up-to-date file.
+*
+* Copyright (c) 2010 boblemarin emeric@minimal.be http://www.minimal.be
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+function Sprite3D(element) {
+ // init engine if needed
+ if ( !Sprite3D.prototype._isInit ) Sprite3D.isSupported();
+
+ // create an empty <div> if no element is provided
+ if (arguments.length == 0) {
+ element = document.createElement("div");
+ element.style.margin = "0px";
+ element.style.padding = "0px";
+ element.style.position = "absolute";
+ } else {
+ if ( element.style.position == "static" ) element.style.position = "relative";
+ }
+
+ // Firefox 10 empty div fix
+ //if ( element.localName == "DIV" && element.innerHTML == "" ) element.innerHTML = "&nbsp;";
+
+ // prepare for 3D positionning
+ element.style[ this._browserPrefix + "TransformStyle" ] = "preserve-3d";
+ element.style[ this._transformProperty ] = "translateZ(0px)";
+
+
+ this.domElement = element;
+ this.children = [];
+ this._style = element.style;
+ this._listeners = {};
+
+}
+
+// properties, should be private in an ideal world...
+Sprite3D.prototype._px = 0;
+Sprite3D.prototype._py = 0;
+Sprite3D.prototype._pz = 0;
+Sprite3D.prototype._rx = 0;
+Sprite3D.prototype._ry = 0;
+Sprite3D.prototype._rz = 0;
+Sprite3D.prototype._sx = 1;
+Sprite3D.prototype._sy = 1;
+Sprite3D.prototype._sz = 1;
+Sprite3D.prototype._ox = 0;
+Sprite3D.prototype._oy = 0;
+Sprite3D.prototype._oz = 0;
+Sprite3D.prototype._transformString = "_p _rx _ry _rz _s";
+Sprite3D.prototype._a = 1;
+Sprite3D.prototype._style = null;
+Sprite3D.prototype._listeners = null;
+Sprite3D.prototype.__p = "";
+Sprite3D.prototype.__s = "";
+Sprite3D.prototype.__rx = "";
+Sprite3D.prototype.__ry = "";
+Sprite3D.prototype.__rz = "";
+Sprite3D.prototype.__ts = "";
+Sprite3D.prototype.__i = 0;
+
+/** The width (in pixels) of the tiles in the spritesheet */
+Sprite3D.prototype.tileWidth = 0;
+/** The height (in pixels) of the tiles in the spritesheet */
+Sprite3D.prototype.tileHeight = 0;
+
+/** A reference to the DOM element associated with this Sprite3D object */
+Sprite3D.prototype.domElement = null;
+
+/** An array holding references of the Sprite3D's children object */
+Sprite3D.prototype.children = null;
+
+/** The number of child objects */
+Sprite3D.prototype.numChildren = 0;
+
+
+Sprite3D.prototype.transformString = function(ts) {
+ this._transformString = ts;
+ return this;
+};
+
+/********** Position / absolute ***********/
+Sprite3D.prototype.x = function(px) {
+ if ( arguments.length ) {
+ this._px = px;
+ return this;
+ } else {
+ return this._px;
+ }
+};
+Sprite3D.prototype.y = function(py) {
+ if ( arguments.length ) {
+ this._py = py;
+ return this;
+ } else {
+ return this._py;
+ }
+};
+Sprite3D.prototype.z = function(pz) {
+ if ( arguments.length ) {
+ this._pz = pz;
+ return this;
+ } else {
+ return this._pz;
+ }
+};
+Sprite3D.prototype.position = function(px,py,pz) {
+ this._px = px;
+ this._py = py;
+ this._pz = pz;
+ return this;
+};
+/********** Position / relative ***********/
+Sprite3D.prototype.move = function(px,py,pz) {
+ this._px += px;
+ this._py += py;
+ if ( arguments.length == 3 ) this._pz += pz;
+ return this;
+};
+
+/********** Rotation / absolute ***********/
+Sprite3D.prototype.rotationX = function(rx) {
+ if ( arguments.length ) {
+ this._rx = rx;
+ return this;
+ } else {
+ return this._rx;
+ }
+};
+Sprite3D.prototype.rotationY = function(ry) {
+ if ( arguments.length ) {
+ this._ry = ry;
+ return this;
+ } else {
+ return this._ry;
+ }
+};
+Sprite3D.prototype.rotationZ = function(rz) {
+ if ( arguments.length ) {
+ this._rz = rz;
+ return this;
+ } else {
+ return this._rz;
+ }
+};
+Sprite3D.prototype.rotation = function(rx,ry,rz) {
+ this._rx = rx;
+ this._ry = ry;
+ this._rz = rz;
+ return this;
+};
+/********** Rotation / relative ***********/
+Sprite3D.prototype.rotate = function(rx,ry,rz) {
+ this._rx += rx;
+ this._ry += ry;
+ this._rz += rz;
+ return this;
+};
+
+/********** Scale ***********/
+Sprite3D.prototype.scaleX = function(sx) {
+ if ( arguments.length ) {
+ this._sx = sx;
+ return this;
+ } else {
+ return this._sx;
+ }
+};
+Sprite3D.prototype.scaleY = function(sy) {
+ if ( arguments.length ) {
+ this._sy = sy;
+ return this;
+ } else {
+ return this._sy;
+ }
+};
+Sprite3D.prototype.scaleZ = function(sz) {
+ if ( arguments.length ) {
+ this._sz = sz;
+ return this;
+ } else {
+ return this._sz;
+ }
+};
+Sprite3D.prototype.scale = function(sx,sy,sz) {
+ switch(arguments.length){
+ case 0:
+ return this._sx;
+ case 1:
+ this._sx = sx;
+ this._sy = sx;
+ this._sz = sx;
+ return this;
+ case 2:
+ this._sx = sx;
+ this._sy = sy;
+ this._sz = 1;
+ return this;
+ case 3:
+ this._sx = sx;
+ this._sy = sy;
+ this._sz = sz;
+ return this;
+ }
+ return this;
+}
+
+/********** Alpha ***********/
+Sprite3D.prototype.alpha = function(alpha) {
+ if ( arguments.length ) {
+ this._style.opacity = this._a = alpha;
+ return this;
+ } else {
+ return this._a;
+ }
+};
+
+/********** Origin (former registrationPoint) ***********/
+Sprite3D.prototype.origin = function(ox,oy,oz) {
+ this._ox = ox;
+ this._oy = oy;
+ this._oz = (arguments.length==3)?oz:0;
+ return this;
+};
+
+/********** Transform Origin ***********/
+Sprite3D.prototype.transformOrigin = function(tx,ty) {
+ this._style[ this._browserPrefix + "TransformOrigin" ] = (Number(tx)?tx+"px":tx) + " " + (Number(ty)?ty+"px":ty);
+ return this;
+};
+
+/********** CSS ClassName manipulation ***********/
+Sprite3D.prototype.className = function(c) {
+ if (arguments.length) {
+ this.domElement.className = c;
+ return this;
+ } else {
+ return this.domElement.className;
+ }
+};
+Sprite3D.prototype.addClassName = function(c) {
+ this.domElement.className += " " + c + " ";
+ return this;
+};
+Sprite3D.prototype.removeClassName = function(c) {
+ this.domElement.className = this.domElement.className.replace(c, '');
+ return this;
+};
+
+/********** ID ***********/
+Sprite3D.prototype.id = function(id) {
+ if ( arguments.length){
+ this.domElement.id = id;
+ return this;
+ } else {
+ return this.domElement.id;
+ }
+
+};
+
+/********** CSS properties manipulation ***********/
+Sprite3D.prototype.css = function(name, value) {
+ switch(arguments.length) {
+ case 0:
+ return this._style;
+ case 1:
+ return this._style[name];
+ case 2:
+ this._style[name] = value;
+ }
+ return this;
+};
+
+/********** HTML content ***********/
+Sprite3D.prototype.html = function(value) {
+ if (arguments.length){
+ this.domElement.innerHTML = value;
+ return this;
+ }else{
+ return this.domElement.innerHTML;
+ }
+ return this;
+};
+
+/********** custom property setter ***********/
+Sprite3D.prototype.set = function(name, value) {
+ this[name] = value;
+ return this;
+};
+
+/********** SpriteSheet system ***********/
+Sprite3D.prototype.tileSize = function(width, height) {
+ this.tileWidth = width;
+ this.tileHeight = height;
+ return this;
+};
+Sprite3D.prototype.tilePosition = function(tilePosX, tilePosY) {
+ this._style.backgroundPosition = "-" + (tilePosX * this.tileWidth) + "px -" + (tilePosY * this.tileHeight) + "px";
+ return this;
+};
+
+/**
+ * Sets the order in which transformations are applied.
+ * If true, rotations are applied before translations. If false, translations are applied before rotations.
+ * Note that, when applying rotations, the axis of the object rotate, and subsequent translations follow the modified orientation of the axis.
+ * For a more accurate control, you should use the transformString property.
+ * @param {boolean} rf true to rotate first, false to translate first
+ * @return {Sprite3D} The reference to this Sprite3D object
+ */
+Sprite3D.prototype.rotateFirst = function(rf) {
+ this.rotateFirst = rf;
+ if ( rf ) {
+ this._transformString = "_rx _ry _rz _p _s";
+ } else {
+ this._transformString = "_p _rz _ry _rx _s";
+ }
+ return this;
+};
+
+/************ Transform application **************/
+Sprite3D.prototype.update = function() {
+ this.__p = "translate3d(" + (this._px - this._ox) + "px," + (this._py - this._oy) + "px," + (this._pz - this._oz) + "px) ";
+ this.__rx = "rotateX(" + this._rx + "deg) ";
+ this.__ry = "rotateY(" + this._ry + "deg) ";
+ this.__rz = "rotateZ(" + this._rz + "deg) ";
+ this.__s = "scale3d(" + this._sx + ", " + this._sy + ", " + this._sz + ") ";
+
+ // var transformString = "_rx _ry _rz _p _s";
+ this.__ts = this._transformString;
+ this.__ts = this.__ts.replace( "_p", this.__p );
+ this.__ts = this.__ts.replace( "_rx", this.__rx );
+ this.__ts = this.__ts.replace( "_ry", this.__ry );
+ this.__ts = this.__ts.replace( "_rz", this.__rz );
+ this.__ts = this.__ts.replace( "_s", this.__s );
+ this._style[this._transformProperty] = this.__ts;
+
+ return this;
+};
+Sprite3D.prototype.update2D = function() {
+ this.__p = "translate(" + (this._px - this._ox) + "px," + (this._py - this._oy) + "px) ";
+ this.__rz = "rotate(" + this._rz + "deg) ";
+ this.__s = "scale(" + this._sx + ", " + this._sy + ") ";
+
+ this.__ts = this._transformString;
+ this.__ts = this.__ts.replace( "_p", this.__p );
+ this.__ts = this.__ts.replace( "_rx", "" );
+ this.__ts = this.__ts.replace( "_ry", "" );
+ this.__ts = this.__ts.replace( "_rz", this.__rz );
+ this.__ts = this.__ts.replace( "_s", this.__s );
+ this._style[this._transformProperty] = this.__ts;
+
+ return this;
+};
+Sprite3D.prototype.updateWithChildren = function(recursive) {
+ this.update();
+
+ for (this.i = 0; this.i < this.numChildren; this.i++) {
+ if (recursive) {
+ this.children[this.i].updateWithChildren(recursive);
+ } else {
+ this.children[this.i].update();
+ }
+ }
+
+ return this;
+};
+
+/************ Scenography **************/
+Sprite3D.prototype.addChild = function(e) {
+ this.numChildren = this.children.push(e);
+ this.domElement.appendChild(e.domElement);
+ return e;
+};
+Sprite3D.prototype.removeChild = function(child) {
+ var n = this.children.indexOf(child);
+ if (n > -1) {
+ return this.removeChildAt(n);
+ }
+ return null;
+};
+Sprite3D.prototype.removeChildAt = function(n) {
+ --this.numChildren;
+ this.domElement.removeChild(this.children[n].domElement);
+ return this.children.splice(n, 1)[0];
+};
+Sprite3D.prototype.findFromDOMElement = function(element) {
+ for (this.i = 0; this.i < this.numChildren; this.i++) {
+ if (element == this.children[this.i].domElement) { return this.children[this.i]; }
+ }
+ return null;
+};
+
+/************ Event handling **************/
+Sprite3D.prototype.addEventListener = function(event,callback,capture) {
+ var fname = event + "_" + callback.name;
+ if ( this._listeners[fname] == null ) {
+ var sprite = this;
+ var fn = function(e) { callback(e,sprite); }
+ this._listeners[fname] = fn;
+ this.domElement.addEventListener(event,fn,capture);
+ }
+ return this;
+};
+Sprite3D.prototype.removeEventListener = function(event,callback,capture) {
+ var fname = event + "_" + callback.name;
+ if ( this._listeners[fname] != null ) {
+ this.domElement.removeEventListener(event,this._listeners[fname],capture);
+ delete this._listeners[fname];
+ }
+ return this;
+};
+
+/************ Helper functions [static] **************/
+Sprite3D.stage = function(element) {
+ if ( !Sprite3D.prototype._isInit ) Sprite3D.isSupported();
+
+ var c,s;
+ if (element){
+ c = element;
+ s = element.style;
+ if(s.position == "static" ) s.position = "relative";
+ } else {
+ c = document.createElement("div");
+ s = c.style;
+ s[Sprite3D.prototype._browserPrefix+"PerspectiveOrigin"] = "0 0";
+ s[Sprite3D.prototype._browserPrefix+"TransformOrigin"] = "0 0";
+ s.position = "absolute";
+ s.top = "50%";
+ s.left = "50%";
+ s.margin = "0px";
+ s.padding = "0px";
+ document.body.appendChild(c);
+ }
+
+ s[Sprite3D.prototype._browserPrefix+"Perspective"] = "800px";
+ s[Sprite3D.prototype._browserPrefix+"Transform"] = "translateZ(0px)";
+ s[Sprite3D.prototype._browserPrefix+"TransformStyle"] = "preserve-3d";
+
+ return new Sprite3D(c);
+};
+
+
+/** Private static property. Used internally for browser checking. You should not change its value. */
+Sprite3D.prototype._isInit = false;
+
+/** Private static property. Used internally for cross-browser compatibility. You should not change its value. */
+Sprite3D.prototype._transformProperty = "webkitTransform";
+
+/** Private static property. Used internally for cross-browser compatibility. You should not change its value. */
+Sprite3D.prototype._browserPrefix = "webkit";
+
+/**
+ * Test for CSS 3D transforms support in the current browser.
+ * If 3D transforms are not supported, the update() method is replaced by the update2D() method,
+ * providing an automatic fallback that might save some bits :)
+ * @return {boolean} True if the 3D transforms are supported by the browser
+ */
+Sprite3D.isSupported = function() {
+ var d = document.createElement("div"),
+ prefixes = ["", "webkit", "Moz", "o", "ms" ],
+ n = prefixes.length, i;
+
+ // check for 3D transforms
+ for( i = 0; i < n; i++ ) {
+ if ( ( prefixes[i] + "Perspective" ) in d.style ) {
+ Sprite3D.prototype._transformProperty = prefixes[i] + "Transform";
+ Sprite3D.prototype._isInit = true;
+ Sprite3D.prototype._browserPrefix = prefixes[i];
+ //console.log( "found support for 3D transforms using prefix: " + prefixes[i] );
+ return true;
+ }
+ }
+
+ // check for 2D transforms
+ for( i = 0; i < n; i++ ) {
+ if ( ( prefixes[i] + "Transform" ) in d.style ) {
+ Sprite3D.prototype._transformProperty = prefixes[i] + "Transform";
+ Sprite3D.prototype._isInit = true;
+ Sprite3D.prototype._browserPrefix = prefixes[i];
+ Sprite3D.prototype.update = Sprite3D.prototype.update2D;
+ //console.log( "found support for 2D transforms using prefix: " + prefixes[i] );
+ return false;
+ }
+ }
+ //console.log( "no support for CSS transforms.");
+ return false;
+};
71 assets/face.css
@@ -0,0 +1,71 @@
+html, body { height: 100%; }
+
+body {
+ background: #dfebeb url(images/bg.jpg) no-repeat center;
+ background-size: contain;
+ font-family: Helvetica, Geneva, Arial;
+ line-height: 1.4em;
+ color: black;
+ margin: 0px;
+ padding: 0px;
+ overflow: hidden;
+}
+
+span {
+ display: block;
+ opacity: 1;
+}
+
+.selected {
+ /*border: 1px dashed #880000;*/
+ background-color: rgba(200,0,0,.2);
+}
+
+.selected2 {
+ /*border: 1px solid #CC0000;*/
+ background-color: rgba(200,0,0,.4);
+}
+
+div {
+ position: absolute;
+ z-index: 1;
+}
+div#img1 {
+ background-image: url(images/mouth1.png);
+ width: 200px;
+ height: 101px;
+}
+div#img2 {
+ background-image: url(images/mouth2.png);
+ width: 200px;
+ height: 115px;
+}
+div#img3 {
+ background-image: url(images/nose1.png);
+ width: 160px;
+ height: 132px;
+}
+div#img4 {
+ background-image: url(images/nose2.png);
+ width: 150px;
+ height: 201px;
+}
+div#img5 {
+ background-image: url(images/eye1.png);
+ width: 147px;
+ height: 101px;
+}
+div#img6 {
+ background-image: url(images/eye2.png);
+ width: 160px;
+ height: 121px;
+}
+
+div#warning {
+ top: 5px;
+ right: 5px;
+ width: 220px;
+ display: none;
+ padding: 10px;
+ background: rgba(255,255,255,.5);
+}
271 assets/face.js
@@ -0,0 +1,271 @@
+var stage,
+ EMPTY_TOUCH = -999,
+ z = 1,
+ mouseTarget,
+ simulateMultitouch = false,
+ numTargets = 6;
+
+function init() {
+ // prepare the stage
+ stage = Sprite3D.stage( document.body );
+
+ // wraps divs with sprite3D objects
+ for( var i = 0; i < numTargets; i++ )
+ {
+ new Sprite3D( document.getElementById( "img" + (i+1) ) )
+ .origin( 0, 0, 0 )
+ .transformOrigin( "0%", "0%" )
+ .position( 20, 20, 0 )
+ .rotateFirst(false)
+ .addEventListener( "touchstart", onTouchStart )
+ .addEventListener( "touchmove", onTouchMove )
+ .addEventListener( "touchend", onTouchEnd )
+ .addEventListener( "mousedown", onMouseDown )
+ .set( 'numTouches', 0 )
+ .set( 'touch1ID', EMPTY_TOUCH )
+ .set( 'touch2ID', EMPTY_TOUCH )
+ .set( 'angle', 0 )
+ .set( 'distance', 1 )
+ .update();
+ }
+
+ if ( !('ontouchstart' in window) ) {
+ document.getElementById("warning").style.display = "block";
+ document.addEventListener( "keydown", onKeyDown, false );
+ }
+
+ // listen for document touch to prevent scrolling behavior
+ document.addEventListener( "touchstart", onDocumentTouchStart, false );
+}
+
+function onDocumentTouchStart( event, target ) {
+ // prevent user from scrolling the page
+ event.preventDefault();
+}
+
+function onTouchStart( event, target ) {
+ var ts = event.changedTouches,
+ n = ts.length,
+ t,i=0;
+
+ for(i;i<n;i++){
+ t = ts[i];
+ switch( target.numTouches ) {
+ case 0:
+ target.className( "selected" );
+ target.css( "zIndex", z++ );
+ target.touch1X = t.pageX;
+ target.touch1Y = t.pageY;
+ target.touch1ID = t.identifier;
+ target.numTouches = 1;
+ break;
+ case 1:
+ target.className( "selected2" );
+ target.touch2X = t.pageX;
+ target.touch2Y = t.pageY;
+ target.touch2ID = t.identifier;
+ target.numTouches = 2;
+ target.touchAngle = Math.atan2( target.touch2Y - target.touch1Y, target.touch2X - target.touch1X );
+ target.touchDistance = distance( target.touch2X - target.touch1X, target.touch2Y - target.touch1Y );
+ target.angle = Math.atan2( target.y() - target.touch1Y, target.x() - target.touch1X );
+ target.distance = distance( target.x() - target.touch1X, target.y() - target.touch1Y );
+ target.startRotation = target.rotationZ();
+ target.startScale = target.scaleX();
+ break;
+ }
+ }
+ event.preventDefault();
+}
+
+function onTouchMove( event, target ) {
+ var ta = event.changedTouches,
+ n = ta.length,
+ t, px, py;
+
+ switch( target.numTouches )
+ {
+ case 1:
+ while( n-- ) {
+ t = ta[n];
+ if ( t.identifier == target.touch1ID )
+ {
+ px = t.pageX;
+ py = t.pageY;
+ target.move( px - target.touch1X, py - target.touch1Y ).update();
+ target.touch1X = px;
+ target.touch1Y = py;
+ continue;
+ }
+ }
+ break;
+
+ case 2:
+ // update touch positions
+ while( n-- ) {
+ t = ta[n];
+ if ( t.identifier == target.touch1ID )
+ {
+ target.touch1X = t.pageX;
+ target.touch1Y = t.pageY;
+ }
+ else if ( t.identifier == target.touch2ID )
+ {
+ target.touch2X = t.pageX;
+ target.touch2Y = t.pageY;
+ }
+ }
+
+ // compute new position
+ var modAngle = Math.atan2( target.touch2Y - target.touch1Y, target.touch2X - target.touch1X ) - target.touchAngle,
+ modDistance = distance( target.touch2X - target.touch1X, target.touch2Y - target.touch1Y ) / target.touchDistance,
+ newCornerAngle = target.angle + modAngle,
+ newCornerDistance = target.distance * modDistance;
+ target
+ .position(
+ target.touch1X + Math.cos( newCornerAngle ) * newCornerDistance,
+ target.touch1Y + Math.sin( newCornerAngle ) * newCornerDistance,
+ 0 )
+ .scale( target.startScale * modDistance )
+ .rotationZ( target.startRotation + ( modAngle / Math.PI * 180 ) )
+ .update();
+ break;
+ }
+ event.preventDefault();
+}
+
+function onTouchEnd( event, target ) {
+ var t, ta = event.changedTouches;
+ n = ta.length;
+ while( n-- )
+ {
+ t = ta[n];
+
+ if ( t.identifier == target.touch2ID )
+ {
+ //debug.innerHTML = "released touch2 id " + t.identifier;
+ target.touch2ID = EMPTY_TOUCH;
+ target.numTouches = 1;
+ }
+ else if ( t.identifier == target.touch1ID )
+ {
+ if ( target.touch2ID != EMPTY_TOUCH )
+ {
+ //debug.innerHTML = "released touch1 id " + t.identifier;
+ target.touch1X = target.touch2X;
+ target.touch1Y = target.touch2Y;
+ target.touch1ID = target.touch2ID;
+ target.touch2ID = EMPTY_TOUCH;
+ target.numTouches = 1;
+ }
+ else
+ {
+ //debug.innerHTML = "released touch1 id " + t.identifier;
+ target.touch1ID = EMPTY_TOUCH;
+ target.numTouches = 0;
+ }
+ }
+ }
+
+ switch( target.numTouches )
+ {
+ case 2:
+ target.className( "selected2" );
+ break;
+ case 1:
+ target.className( "selected" );
+ break;
+ case 0:
+ target.className( "" );
+ break;
+ }
+ event.preventDefault();
+}
+
+function onMouseDown( event, target ) {
+ if ( mouseTarget == null ) {
+ target.className( "selected" );
+ target.css( "zIndex", z+=5 );
+ target.touch1X = event.pageX;
+ target.touch1Y = event.pageY;
+ target.touch1ID = 999;
+ target.numTouches = 1;
+ mouseTarget = target;
+ document.addEventListener("mousemove", onDocumentMouseMove, false );
+ document.addEventListener("mouseup", onDocumentMouseUp, false );
+ console.log( target.css() );
+ }
+ event.preventDefault();
+}
+
+function onDocumentMouseMove( event ) {
+ if ( simulateMultitouch ) {
+ // update positions
+ mouseTarget.touch1X = event.pageX;
+ mouseTarget.touch1Y = event.pageY;
+
+ // compute new position
+ var modAngle = Math.atan2( mouseTarget.touch2Y - mouseTarget.touch1Y, mouseTarget.touch2X - mouseTarget.touch1X ) - mouseTarget.touchAngle,
+ modDistance = distance( mouseTarget.touch2X - mouseTarget.touch1X, mouseTarget.touch2Y - mouseTarget.touch1Y ) / mouseTarget.touchDistance,
+ newCornerAngle = mouseTarget.angle + modAngle,
+ newCornerDistance = mouseTarget.distance * modDistance;
+ mouseTarget
+ .position(
+ mouseTarget.touch1X + Math.cos( newCornerAngle ) * newCornerDistance,
+ mouseTarget.touch1Y + Math.sin( newCornerAngle ) * newCornerDistance,
+ 0 )
+ .scale( mouseTarget.startScale * modDistance )
+ .rotationZ( mouseTarget.startRotation + ( modAngle / Math.PI * 180 ) )
+ .update();
+ } else {
+ px = event.pageX;
+ py = event.pageY;
+ mouseTarget.move( px - mouseTarget.touch1X, py - mouseTarget.touch1Y ).update();
+ mouseTarget.touch1X = px;
+ mouseTarget.touch1Y = py;
+ }
+ event.preventDefault();
+}
+
+function onDocumentMouseUp( event ) {
+ mouseTarget.touch1ID = EMPTY_TOUCH;
+ mouseTarget.numTouches = 0;
+ mouseTarget.className( "" );
+ mouseTarget = null;
+ document.removeEventListener("mousemove", onDocumentMouseMove, false );
+ document.removeEventListener("mouseup", onDocumentMouseUp, false );
+ if ( simulateMultitouch ) {
+ simulateMultitouch = false;
+ document.removeEventListener( "keyup", onKeyUp, false );
+ }
+ event.preventDefault();
+}
+
+function onKeyDown( event ) {
+ if ( mouseTarget != null && simulateMultitouch == false ) {
+ simulateMultitouch = true;
+ document.addEventListener( "keyup", onKeyUp, false );
+ mouseTarget.className( "selected2" );
+
+ mouseTarget.touch2X = mouseTarget.x();
+ mouseTarget.touch2Y = mouseTarget.y();
+ mouseTarget.numTouches = 2;
+ mouseTarget.touchAngle = Math.atan2( mouseTarget.touch2Y - mouseTarget.touch1Y, mouseTarget.touch2X - mouseTarget.touch1X );
+ mouseTarget.touchDistance = distance( mouseTarget.touch2X - mouseTarget.touch1X, mouseTarget.touch2Y - mouseTarget.touch1Y );
+ mouseTarget.angle = Math.atan2( mouseTarget.y() - mouseTarget.touch1Y, mouseTarget.x() - mouseTarget.touch1X );
+ mouseTarget.distance = distance( mouseTarget.x() - mouseTarget.touch1X, mouseTarget.y() - mouseTarget.touch1Y );
+ mouseTarget.startRotation = mouseTarget.rotationZ();
+ mouseTarget.startScale = mouseTarget.scaleX();
+ e.preventDefault();
+ }
+}
+
+function onKeyUp( event ) {
+ mouseTarget.className("selected");
+ simulateMultitouch = false;
+ document.removeEventListener( "keyup", onKeyUp, false );
+}
+
+function distance( dx, dy )
+{
+ return Math.sqrt( dx * dx + dy * dy );
+}
BIN  assets/images/bg.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/ear.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/eye1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/eye2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/icon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/mouth1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/mouth2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/nose1.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  assets/images/nose2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 cache.manifest
@@ -0,0 +1,18 @@
+CACHE MANIFEST
+#v2
+
+CACHE:
+index.html
+cache.manifest
+assets/face.css
+assets/face.js
+assets/Sprite3D.js
+assets/images/bg.jpg
+assets/images/ear.png
+assets/images/eye1.png
+assets/images/eye2.png
+assets/images/icon.png
+assets/images/mouth1.png
+assets/images/mouth2.png
+assets/images/nose1.png
+assets/images/nose2.png
29 index.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en" cache="cache.manifest">
+ <head>
+ <meta charset="utf-8" />
+ <meta name='HandheldFriendly' content='True' />
+ <meta name='viewport' content='width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0' />
+ <meta name="apple-mobile-web-app-capable" content="yes">
+ <meta name="apple-mobile-web-app-status-bar-style" content="black">
+ <link rel="apple-touch-icon-precomposed" href="assets/images/icon.png" />
+ <title>The Face Builder</title>
+ <link rel="stylesheet" href="assets/face.css" type="text/css">
+ <script src="assets/Sprite3D.js" type="text/javascript"></script>
+ <script src="assets/face.js" type="text/javascript"></script>
+ <!--
+ I know, this application lacks some important features,
+ but time is passing so quickly that I really had no choice.
+ Sorry.
+ -->
+ </head>
+ <body onload="init();">
+ <div id="img6">&nbsp;</div>
+ <div id="img5">&nbsp;</div>
+ <div id="img4">&nbsp;</div>
+ <div id="img3">&nbsp;</div>
+ <div id="img2">&nbsp;</div>
+ <div id="img1">&nbsp;</div>
+ <div id="warning"><p>This page requires a multitouch enabled browser to be fully functional, but you can still drag the elements with your mouse.</p><p>Press and hold any key during dragging to simulate a multitouch behavior.</p></div>
+ </body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.