metro.js: recreating Windows 8 UI as a web interface


/ Published in: jQuery
Save to your folder(s)

Hi everyone, a while ago i posted a little script that reproduced a little animation effect seen in Windows 8 Developer Preview. I thought about expanding it some more, and in the end i started actually recreating the whole Metro interface in HTML5/CSS3/jQuery. if anyone gets interested in it and desires to give a hand i'll soon upload everything on a public github repository

THE RESULT: http://claudiobonifazi.com/snippets/metro

THE SCRIPT: http://claudiobonifazi.com/snippets/metro/script/metro.js

THE MINIFIED SCRIPT: http://claudiobonifazi.com/snippets/metro/script/metro.min.js

hope you enjoy


Copy this code and paste it in your HTML
  1. /*
  2.  * metro.js - Windows 8 Metro UI [v1.2]
  3.  * Distributed under the Do-wathever-the-hell-you-want-with-it License
  4.  *
  5.  * Web site: http://claudiobonifazi.com
  6.  * Blog: http://claudiobonifazi.com?p=4
  7.  * Email: claudio.bonifazi@gmail.com
  8.  * Twitter: @ClaudioBonifazi
  9.  */
  10.  
  11. (function($){
  12. $.fn.metro = function( draggable ){
  13.  
  14. var allEl = $(this);
  15. if( allEl.filter('.sidebar').length > 0 ){
  16. $('body').append('<div id="metroSidebar"></div>')
  17. $(window).resize(function(){
  18. $('#metroSidebar')
  19. .width($(document).width()/5-100)
  20. .height($(document).height()-75)
  21. })
  22. $(window).resize()
  23. allEl.filter('.sidebar').click(function(){ return false })
  24. }
  25.  
  26. return allEl.each(function(i,e){
  27.  
  28. var el = $(this),
  29. duration = 100;
  30. /* foundamental animation data */
  31. el.data('metro',{
  32. clicking: false,
  33. origin: 0,
  34. ang: 10,
  35. orizorvert: 0
  36. })
  37. el.data('drag',{
  38. possible: draggable==undefined ? false : draggable,
  39. left: 0,
  40. top: 0,
  41. happening: false,
  42. afterWhich: 0
  43. })
  44.  
  45.  
  46. /* for a better antialiasing */
  47. if(el.css('box-shadow')=='none')
  48. el.css({'box-shadow':'0 0 1px transparent'})
  49. el.parent().css({'-webkit-perspective':el.outerWidth()*5})
  50.  
  51.  
  52.  
  53. el.mousedown(function(e){
  54.  
  55. var mouse = {
  56. x:e.pageX-el.offset().left,
  57. y:e.pageY-el.offset().top
  58. },
  59. metro=$(this).data('metro');
  60. metro.clicking=true;
  61.  
  62.  
  63.  
  64. if( mouse.x < el.outerWidth()/3 ){
  65. metro.orizorvert = 1;
  66. metro.origin = 100;
  67. metro.ang = -metro.ang;
  68. /* left */
  69.  
  70. }else if(mouse.x > parseInt(el.outerWidth()*2/3)){
  71. metro.orizorvert = 1;
  72. /* right */
  73.  
  74. }else{
  75. if(mouse.y < el.outerHeight()/3){
  76. metro.orizorvert = 2;
  77. metro.origin = 100;
  78. /* top */
  79.  
  80. }else if(mouse.y > parseInt(el.outerHeight()*2/3)){
  81. metro.orizorvert = 2;
  82. metro.ang = -metro.ang;
  83. /* bottom */
  84.  
  85. }
  86. }
  87. el.data('metro',metro)
  88.  
  89. if( el.data('drag').possible ){
  90. e.preventDefault()
  91.  
  92. el.data('drag').left = e.pageX;
  93. el.data('drag').top = e.pageY;
  94. el.data('drag').afterWhich = allEl.index(el);
  95.  
  96. if( el.css('position')=='static' )
  97. el.css({ 'position':'relative' })
  98. }
  99.  
  100. if( metro.orizorvert > 0 && $.browser.webkit){
  101. el
  102. .css({'-webkit-transform-origin':(metro.orizorvert==1 ? metro.origin+'% 0%' : '0% '+metro.origin+'%')})
  103. .animate({'text-indent':el.css('text-indent')},{duration:duration, step: function(now,fx){
  104. /* anim = rotateX(number) or rotateY(number) */
  105. anim = 'rotate'+ (metro.orizorvert==1 ? 'Y':'X')+ '('+( metro.ang*Math.sin((fx.pos*Math.PI/2)) )+'deg)'
  106. el.css({'-webkit-transform' : anim })
  107. },queue:false})
  108. .delay(duration)
  109. }else if( metro.orizorvert==0 || !$.browser.webkit ){
  110. el
  111. .css({'-webkit-transform-origin':''})
  112. .animate({'text-indent':el.css('text-indent')},{duration:duration, step: function(now,fx){
  113. /* anim = scale(number) */
  114. anim = 'scale('+(1- Math.sin(fx.pos*Math.PI/2)/10)+')'
  115. el.css({
  116. '-webkit-transform' : anim,
  117. '-moz-transform' : anim,
  118. '-o-transform' : anim
  119. })
  120. },queue:false})
  121. .delay(duration)
  122. }
  123. if( el.data('drag').possible ){
  124. el.css({ 'cursor':'move' })
  125. }
  126.  
  127.  
  128.  
  129. }).mouseup(function(e){
  130. var a = el.data('metro');
  131.  
  132. if( a.clicking==true ){
  133. if( a.orizorvert > 0 && $.browser.webkit){
  134. el
  135. .css({ '-webkit-transform-origin' : (a.orizorvert==1 ? a.origin+'% 0%' : '0% '+a.origin+'%') })
  136. .animate({'text-indent':el.css('text-indent')},{duration:duration, step: function(now,fx){
  137. /* anim = rotateX(number) or rotateY(number) */
  138. anim = 'rotate'+(a.orizorvert==1 ? 'Y':'X')+'('+a.ang*Math.cos((fx.pos*Math.PI/2))+'deg)';
  139. el.css({'-webkit-transform' : anim })
  140. },queue:false})
  141. .delay(duration)
  142. }else if( a.orizorvert==0 || !$.browser.webkit){
  143. el
  144. .animate({'text-indent': el.css('text-indent')},{duration:duration, step: function(now,fx){
  145. /* anim = scale(number) */
  146. anim = 'scale('+(1- Math.cos(fx.pos*Math.PI/2)/10)+')';
  147. el.css({
  148. '-webkit-transform' : anim,
  149. '-moz-transform' : anim,
  150. '-o-transform' : anim
  151. })
  152. },queue:false})
  153. .delay(duration)
  154. }
  155. el.data('metro',{
  156. clicking: false,
  157. origin: 0,
  158. ang: 10,
  159. orizorvert: 0
  160. })
  161.  
  162. if( el.hasClass('sidebar') && !el.data('drag').happening ){
  163. if( allEl.index(el) == $('#metroSidebar').data('whoOpenedIt') )
  164. $('#metroSidebar').animate({'width':'hide'},'fast').empty().removeData('whoOpenedIt')
  165. else
  166. $('#metroSidebar').load(el.attr('href')).animate({'width':'show'},'fast').data('whoOpenedIt',allEl.index(el))
  167. }
  168.  
  169. if( el.data('drag').possible ){
  170. e.preventDefault();
  171. el.css({ 'cursor':'auto','z-index':0})
  172. if( el.data('drag').happening ){
  173. el
  174. .css({ 'z-index':0}).fadeTo(duration,1)
  175. .animate({left:0,top:0},Math.min(2*duration,200))
  176. }
  177. el.data( 'drag',{ possible:true, left: e.pageX, top: e.pageY, happening:false } )
  178. }
  179.  
  180. }
  181.  
  182.  
  183.  
  184. }).mouseout(function(){
  185. if( el.data('metro').clicking ){
  186. if( el.data('drag').possible )
  187. el.parent().mousemove(e)
  188. else
  189. el.mouseup()
  190. }
  191.  
  192. })
  193.  
  194.  
  195.  
  196.  
  197. $('body>*').not('#metroSidebar').click(function(){
  198. if( allEl.filter('.sidebar').length>0 ){
  199. $('#metroSidebar').animate({'width':'hide'},'fast').empty().removeData('whoOpenedIt')
  200. }
  201. })
  202.  
  203.  
  204.  
  205.  
  206. if( el.data('drag').possible ){
  207. el.parent()
  208. .mousemove(function(e){
  209. if( el.data('metro').clicking && el.data('drag').possible ){
  210. el.data('drag').happening = true;
  211. if(el.css('opacity')==1)
  212. el.fadeTo(duration,0.9)
  213. el.css({ 'z-index':9999,left: e.pageX-el.data('drag').left, top: -el.data('drag').top+e.pageY })
  214.  
  215. e.preventDefault()
  216. }
  217. })
  218.  
  219. }
  220. })
  221. }
  222. })(jQuery)

URL: http://claudiobonifazi.com/snippets/metro

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.