HTML5已经相当强大,在HTML5平台上,我们可以完成很多非常复杂的动画效果,包括游戏在内。早期我们只能利用flash来实现网络游戏,现在我们又多了一种选择,即用HTML5制作游戏。相比flash,HTML5更加灵活方便,随着浏览器技术的不断升级,HTML5一定会广泛使用,至少在网页动画方面,下面是一些利用HTML5完成的游戏作品。
HTML5版切水果游戏
这曾是风靡全球的一款手机APP游戏切水果,现在JS小组已经将其改版成HTML5,并将其开源。
核心Javascript代码:
Ucren.BasicDrag = Ucren.Class( /* constructor */ function( conf ){ conf = Ucren.fixConfig( conf ); this.type = Ucren.fixString( conf.type, "normal" ); var isTouch = this.isTouch = "ontouchstart" in window; this.TOUCH_START = isTouch ? "touchstart" : "mousedown", this.TOUCH_MOVE = isTouch ? "touchmove" : "mousemove", this.TOUCH_END = isTouch ? "touchend" : "mouseup"; }, /* methods */ { bind: function( el, handle ){ el = Ucren.Element( el ); handle = Ucren.Element( handle ) || el; var evt = {}; evt[this.TOUCH_START] = function( e ){ e = Ucren.Event( e ); this.startDrag(); e.cancelBubble = true; e.stopPropagation && e.stopPropagation(); return e.returnValue = false; }.bind( this ); handle.addEvents( evt ); this.target = el; }, //private getCoors: function( e ){ var coors = []; if ( e.targetTouches && e.targetTouches.length ) { // iPhone var thisTouch = e.targetTouches[0]; coors[0] = thisTouch.clientX; coors[1] = thisTouch.clientY; }else{ // all others coors[0] = e.clientX; coors[1] = e.clientY; } return coors; }, //private startDrag: function(){ var target, draging, e; target = this.target; draging = target.draging = {}; this.isDraging = true; draging.x = parseInt( target.style( "left" ), 10 ) || 0; draging.y = parseInt( target.style( "top" ), 10 ) || 0; e = Ucren.Event(); var coors = this.getCoors( e ); draging.mouseX = coors[0]; draging.mouseY = coors[1]; this.registerDocumentEvent(); }, //private endDrag: function(){ this.isDraging = false; this.unRegisterDocumentEvent(); }, //private registerDocumentEvent: function(){ var target, draging; target = this.target; draging = target.draging; draging.documentSelectStart = Ucren.addEvent( document, "selectstart", function( e ){ e = e || event; e.stopPropagation && e.stopPropagation(); e.cancelBubble = true; return e.returnValue = false; }); draging.documentMouseMove = Ucren.addEvent( document, this.TOUCH_MOVE, function( e ){ var ie, nie; e = e || event; ie = Ucren.isIe && e.button != 1; nie = !Ucren.isIe && e.button != 0; if( (ie || nie ) && !this.isTouch ) this.endDrag(); var coors = this.getCoors( e ); draging.newMouseX = coors[0]; draging.newMouseY = coors[1]; e.stopPropagation && e.stopPropagation(); return e.returnValue = false; }.bind( this )); draging.documentMouseUp = Ucren.addEvent( document, this.TOUCH_END, function(){ this.endDrag(); }.bind( this )); var lx, ly; clearInterval( draging.timer ); draging.timer = setInterval( function(){ var x, y, dx, dy; if( draging.newMouseX != lx && draging.newMouseY != ly ){ lx = draging.newMouseX; ly = draging.newMouseY; dx = draging.newMouseX - draging.mouseX; dy = draging.newMouseY - draging.mouseY; x = draging.x + dx; y = draging.y + dy; if( this.type == "calc" ){ this.returnValue( dx, dy, draging.newMouseX, draging.newMouseY ); }else{ target.left( x ).top( y ); } } }.bind( this ), 10 ); }, //private unRegisterDocumentEvent: function(){ var draging = this.target.draging; Ucren.delEvent( document, this.TOUCH_MOVE, draging.documentMouseMove ); Ucren.delEvent( document, this.TOUCH_END, draging.documentMouseUp ); Ucren.delEvent( document, "selectstart", draging.documentSelectStart ); clearInterval( draging.timer ); }, //private returnValue: function( dx, dy, x, y ){ //todo something } } ); // Ucren.Template Ucren.Template = Ucren.Class( /* constructor */ function(){ this.string = join.call( arguments, "" ); }, /* methods */ { apply: function( conf ){ return this.string.format( conf ); } } ); // Ucren.BasicElement Ucren.BasicElement = Ucren.Class( /* constructor */ function( el ){ this.dom = el; this.countMapping = {}; }, /* methods */ { isUcrenElement: true, attr: function( name, value ){ if( typeof value == "string" ){ this.dom.setAttribute( name, value ); }else{ return this.dom.getAttribute( name ); } return this; }, style: function( /* unknown1, unknown2 */ ){ var getStyle = Ucren.isIe ? function( name ){ return this.dom.currentStyle[name]; } : function( name ){ var style; style = document.defaultView.getComputedStyle( this.dom, null ); return style.getPropertyValue( name ); }; return function( unknown1, unknown2 ){ if( typeof unknown1 == "object" ){ Ucren.each( unknown1, function( value, key ){ this[key] = value; }.bind( this.dom.style )); }else if( typeof unknown1 == "string" && typeof unknown2 == "undefined" ){ return getStyle.call( this, unknown1 ); }else if( typeof unknown1 == "string" && typeof unknown2 != "undefined" ){ this.dom.style[unknown1] = unknown2; } return this; }; }(), hasClass: function( name ){ var className = " " + this.dom.className + " "; return className.indexOf( " " + name + " " ) > -1; }, setClass: function( name ){ if( typeof( name ) == "string" ) this.dom.className = name.trim(); return this; }, addClass: function( name ){ var el, className; el = this.dom; className = " " + el.className + " "; if( className.indexOf( " " + name + " " ) == -1 ){ className += name; className = className.trim(); className = className.replace( / +/g, " " ); el.className = className; } return this; }, delClass: function( name ){ var el, className; el = this.dom; className = " " + el.className + " "; if( className.indexOf( " " + name + " " ) > -1 ){ className = className.replace( " " + name + " ", " " ); className = className.trim(); className = className.replace( / +/g, " " ); el.className = className; } return this; }, html: function( html ){ var el = this.dom; if( typeof html == "string" ){ el.innerHTML = html; }else if( html instanceof Array ){ el.innerHTML = html.join( "" ); }else{ return el.innerHTML; } return this; }, left: function( number ){ var el = this.dom; if( typeof( number ) == "number" ){ el.style.left = number + "px"; this.fireEvent( "infect", [{ left: number }] ); }else{ return this.getPos().x; } return this; }, top: function( number ){ var el = this.dom; if( typeof( number ) == "number" ){ el.style.top = number + "px"; this.fireEvent( "infect", [{ top: number }] ); }else{ return this.getPos().y; } return this; }, width: function( unknown ){ var el = this.dom; if( typeof unknown == "number" ){ el.style.width = unknown + "px"; this.fireEvent( "infect", [{ width: unknown }] ); }else if( typeof unknown == "string" ){ el.style.width = unknown; this.fireEvent( "infect", [{ width: unknown }] ); }else{ return this.getSize().width; } return this; }, height: function( unknown ){ var el = this.dom; if( typeof unknown == "number" ){ el.style.height = unknown + "px"; this.fireEvent( "infect", [{ height: unknown }] ); }else if( typeof unknown == "string" ){ el.style.height = unknown; this.fireEvent( "infect", [{ height: unknown }] ); }else{ return this.getSize().height; } return this; }, count: function( name ){ return this.countMapping[name] = ++ this.countMapping[name] || 1; }, display: function( bool ){ var dom = this.dom; if( typeof( bool ) == "boolean" ){ dom.style.display = bool ? "block" : "none"; this.fireEvent( "infect", [{ display: bool }] ); }else{ return this.style( "display" ) != "none"; } return this; }, first: function(){ var c = this.dom.firstChild; while( c && !c.tagName && c.nextSibling ){ c = c.nextSibling; } return c; }, add: function( dom ){ var el; el = Ucren.Element( dom ); this.dom.appendChild( el.dom ); return this; }, remove: function( dom ){ var el; if( dom ){ el = Ucren.Element( dom ); el.html( "" ); this.dom.removeChild( el.dom ); }else{ el = Ucren.Element( this.dom.parentNode ); el.remove( this ); } return this; }, insert: function( dom ){ var tdom; tdom = this.dom; if( tdom.firstChild ){ tdom.insertBefore( dom, tdom.firstChild ); }else{ this.add( dom ); } return this; }, addEvents: function( conf ){ var blank, el, rtn; blank = {}; rtn = {}; el = this.dom; Ucren.each( conf, function( item, key ){ rtn[key] = Ucren.addEvent( el, key, item ); }); return rtn; }, removeEvents: function( conf ){ var blank, el; blank = {}; el = this.dom; Ucren.each( conf, function( item, key ){ Ucren.delEvent( el, key, item ); }); return this; }, getPos: function(){ var el, parentNode, pos, box, offset; el = this.dom; pos = {}; if( el.getBoundingClientRect ){ box = el.getBoundingClientRect(); offset = Ucren.isIe ? 2 : 0; var doc = document; var scrollTop = Math.max( doc.documentElement.scrollTop, doc.body.scrollTop ); var scrollLeft = Math.max( doc.documentElement.scrollLeft, doc.body.scrollLeft ); return { x: box.left + scrollLeft - offset, y: box.top + scrollTop - offset }; }else{ pos = { x: el.offsetLeft, y: el.offsetTop }; parentNode = el.offsetParent; if( parentNode != el ){ while( parentNode ){ pos.x += parentNode.offsetLeft; pos.y += parentNode.offsetTop; parentNode = parentNode.offsetParent; } } if( Ucren.isSafari && this.style( "position" ) == "absolute" ){ // safari doubles in some cases pos.x -= document.body.offsetLeft; pos.y -= document.body.offsetTop; } } if( el.parentNode ){ parentNode = el.parentNode; }else{ parentNode = null; } while( parentNode && parentNode.tagName.toUpperCase() != "BODY" && parentNode.tagName.toUpperCase() != "HTML" ){ // account for any scrolled ancestors pos.x -= parentNode.scrollLeft; pos.y -= parentNode.scrollTop; if( parentNode.parentNode ){ parentNode = parentNode.parentNode; }else{ parentNode = null; } } return pos; }, getSize: function(){ var dom = this.dom; var display = this.style( "display" ); if ( display && display !== "none" ) { return { width: dom.offsetWidth, height: dom.offsetHeight }; } var style = dom.style; var originalStyles = { visibility: style.visibility, position: style.position, display: style.display }; var newStyles = { visibility: "hidden", display: "block" }; if ( originalStyles.position !== "fixed" ) newStyles.position = "absolute"; this.style( newStyles ); var dimensions = { width: dom.offsetWidth, height: dom.offsetHeight }; this.style( originalStyles ); return dimensions; }, observe: function( el, fn ){ el = Ucren.Element( el ); el.on( "infect", fn.bind( this )); return this; }, usePNGbackground: function( image ){ var dom; dom = this.dom; if( /\.png$/i.test( image ) && Ucren.isIe6 ){ dom.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader( src='" + image + "',sizingMethod='scale' );"; /// _background: none; /// _filter: progid:DXImageTransform.Microsoft.AlphaImageLoader( src='images/pic.png',sizingMethod='scale' ); }else{ dom.style.backgroundImage = "url( " + image + " )"; } return this; }, setAlpha: function(){ var reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/; return function( value ){ var element = this.dom, es = element.style; if( !Ucren.isIe ){ es.opacity = value / 100; /* }else if( es.filter === "string" ){ */ }else{ if ( element.currentStyle && !element.currentStyle.hasLayout ) es.zoom = 1; if ( reOpacity.test( es.filter )) { value = value >= 99.99 ? "" : ( "alpha( opacity=" + value + " )" ); es.filter = es.filter.replace( reOpacity, value ); } else { es.filter += " alpha( opacity=" + value + " )"; } } return this; }; }(), fadeIn: function( callback ){ if( typeof this.fadingNumber == "undefined" ) this.fadingNumber = 0; this.setAlpha( this.fadingNumber ); var fading = function(){ this.setAlpha( this.fadingNumber ); if( this.fadingNumber == 100 ){ clearInterval( this.fadingInterval ); callback && callback(); }else this.fadingNumber += 10; }.bind( this ); this.display( true ); clearInterval( this.fadingInterval ); this.fadingInterval = setInterval( fading, Ucren.isIe ? 20 : 30 ); return this; }, fadeOut: function( callback ){ if( typeof this.fadingNumber == "undefined" ) this.fadingNumber = 100; this.setAlpha( this.fadingNumber ); var fading = function(){ this.setAlpha( this.fadingNumber ); if( this.fadingNumber == 0 ){ clearInterval( this.fadingInterval ); this.display( false ); callback && callback(); }else this.fadingNumber -= 10; }.bind( this ); clearInterval( this.fadingInterval ); this.fadingInterval = setInterval( fading, Ucren.isIe ? 20 : 30 ); return this; }, useMouseAction: function( className, actions ){ /** * 调用示例: el.useMouseAction( "xbutton", "over,out,down,up" ); * 使用效果: el 会在 "xbutton xbutton-over","xbutton xbutton-out","xbutton xbutton-down","xbutton xbutton-up" * 等四个 className 中根据相应的鼠标事件来进行切换。 * 特别提示: useMouseAction 可使用不同参数多次调用。 */ if( !this.MouseAction ) this.MouseAction = new Ucren.MouseAction({ element: this }); this.MouseAction.use( className, actions ); return this; } } ); if( Ucren.isIe ) document.execCommand( "BackgroundImageCache", false, true ); for( var i in Ucren ){ exports[i] = Ucren[i]; }; return exports; });