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

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

Report this snippet


Comments

RSS Icon Subscribe to comments

You need to login to post a comment.