css3d_youtube.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  6. <title>three.js css3d - youtube</title>
  7. <style>
  8. html, body {
  9. height: 100%;
  10. }
  11. body {
  12. background-color: #000000;
  13. margin: 0;
  14. font-family: Arial;
  15. overflow: hidden;
  16. }
  17. #search {
  18. position: absolute;
  19. bottom: 30px;
  20. width: 100%;
  21. text-align: center;
  22. }
  23. #search input {
  24. color: #ffffff;
  25. background-color: transparent;
  26. border: 1px solid #0080ff;
  27. padding: 10px;
  28. font-size: 20px;
  29. text-transform: uppercase;
  30. -webkit-border-radius: 0px; /* workaround for ios safari */
  31. }
  32. #search button {
  33. color: #0080ff;
  34. background-color: transparent;
  35. border: 1px solid #0080ff;
  36. padding: 10px;
  37. font-size: 20px;
  38. text-transform: uppercase;
  39. cursor: pointer;
  40. }
  41. </style>
  42. </head>
  43. <body>
  44. <script src="../build/three.min.js"></script>
  45. <script src="js/libs/tween.min.js"></script>
  46. <script src="js/renderers/CSS3DRenderer.js"></script>
  47. <div id="container"></div>
  48. <div id="search"><input id="query" type="text" value="cats"><button id="button">search</button></div>
  49. <script>
  50. var camera, scene, renderer;
  51. var objects = [], player;
  52. var auto = true;
  53. init();
  54. animate();
  55. function init() {
  56. camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 );
  57. camera.position.y = - 25;
  58. scene = new THREE.Scene();
  59. renderer = new THREE.CSS3DRenderer();
  60. renderer.setSize( window.innerWidth, window.innerHeight );
  61. renderer.domElement.style.position = 'absolute';
  62. renderer.domElement.style.top = 0;
  63. document.getElementById( 'container' ).appendChild( renderer.domElement );
  64. //
  65. var query = document.getElementById( 'query' );
  66. query.addEventListener( 'keyup', function ( event ) {
  67. if ( event.keyCode === 13 ) {
  68. search( query.value );
  69. }
  70. }, false );
  71. var button = document.getElementById( 'button' );
  72. button.addEventListener( 'click', function ( event ) {
  73. search( query.value );
  74. }, false );
  75. if ( window.location.hash.length > 0 ) {
  76. query.value = window.location.hash.substr( 1 );
  77. }
  78. search( query.value );
  79. document.body.addEventListener( 'mousewheel', onMouseWheel, false );
  80. document.body.addEventListener( 'click', function ( event ) {
  81. auto = true;
  82. if ( player !== undefined ) {
  83. player.parentNode.removeChild( player );
  84. player = undefined;
  85. }
  86. new TWEEN.Tween( camera.position )
  87. .to( { x: 0, y: - 25 }, 1500 )
  88. .easing( TWEEN.Easing.Exponential.Out )
  89. .start();
  90. }, false );
  91. window.addEventListener( 'resize', onWindowResize, false );
  92. }
  93. function search( query ) {
  94. window.location.hash = query;
  95. for ( var i = 0, l = objects.length; i < l; i ++ ) {
  96. var object = objects[ i ];
  97. var delay = Math.random() * 1000;
  98. new TWEEN.Tween( object.position )
  99. .to( { y: - 3000 }, 1000 )
  100. .delay( delay )
  101. .easing( TWEEN.Easing.Exponential.In )
  102. .start();
  103. new TWEEN.Tween( object )
  104. .to( {}, 2000 )
  105. .delay( delay )
  106. .onComplete( function () {
  107. scene.remove( this );
  108. renderer.cameraElement.removeChild( this.element );
  109. var index = objects.indexOf( this );
  110. objects.splice( index, 1 );
  111. } )
  112. .start();
  113. }
  114. var request = new XMLHttpRequest();
  115. request.addEventListener( 'load', onData, false );
  116. request.open( 'GET', 'https://gdata.youtube.com/feeds/api/videos?v=2&alt=json&max-results=50&q=' + query, true );
  117. request.send( null );
  118. }
  119. function onData( event ) {
  120. var data = JSON.parse( event.target.responseText );
  121. var entries = data.feed.entry;
  122. // console.log( entries );
  123. for ( var i = 0; i < entries.length; i ++ ) {
  124. var entry = entries[ i ];
  125. var element = document.createElement( 'div' );
  126. element.style.width = '480px';
  127. element.style.height = '360px';
  128. var image = document.createElement( 'img' );
  129. image.addEventListener( 'load', function ( event ) {
  130. var object = this.properties.object;
  131. var button = this.properties.button;
  132. button.style.visibility = 'visible';
  133. new TWEEN.Tween( object.position )
  134. .to( { y: Math.random() * 2000 - 1000 }, 2000 )
  135. .easing( TWEEN.Easing.Exponential.Out )
  136. .start();
  137. }, false );
  138. image.style.position = 'absolute';
  139. image.style.width = '480px';
  140. image.style.height = '360px';
  141. image.src = entry.media$group.media$thumbnail[ 2 ].url;
  142. element.appendChild( image );
  143. var button = document.createElement( 'img' );
  144. button.style.position = 'absolute';
  145. button.style.left = ( ( 480 - 86 ) / 2 ) + 'px';
  146. button.style.top = ( ( 360 - 61 ) / 2 ) + 'px';
  147. button.style.visibility = 'hidden';
  148. button.style.WebkitFilter = 'grayscale()';
  149. button.src = 'data:image/png;base64,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';
  150. element.appendChild( button );
  151. var blocker = document.createElement( 'div' );
  152. blocker.style.position = 'absolute';
  153. blocker.style.width = '480px';
  154. blocker.style.height = '360px';
  155. blocker.style.background = 'rgba(0,0,0,0.5)';
  156. blocker.style.cursor = 'pointer';
  157. element.appendChild( blocker );
  158. var object = new THREE.CSS3DObject( element );
  159. object.position.x = Math.random() * 4000 - 2000;
  160. // object.position.y = Math.random() * 2000 - 1000;
  161. object.position.y = 3000;
  162. object.position.z = Math.random() * - 5000;
  163. scene.add( object );
  164. objects.push( object );
  165. //
  166. var properties = { data: entry, blocker: blocker, button: button, object: object }
  167. element.properties = properties;
  168. image.properties = properties;
  169. element.addEventListener( 'mouseover', function () {
  170. this.properties.button.style.WebkitFilter = '';
  171. this.properties.blocker.style.background = 'rgba(0,0,0,0)';
  172. }, false );
  173. element.addEventListener( 'mouseout', function () {
  174. this.properties.button.style.WebkitFilter = 'grayscale()';
  175. this.properties.blocker.style.background = 'rgba(0,0,0,0.75)';
  176. }, false );
  177. element.addEventListener( 'click', function ( event ) {
  178. event.stopPropagation();
  179. var data = this.properties.data;
  180. var object = this.properties.object;
  181. auto = false;
  182. if ( player !== undefined ) {
  183. player.parentNode.removeChild( player );
  184. player = undefined;
  185. }
  186. player = document.createElement( 'iframe' );
  187. player.style.position = 'absolute';
  188. player.style.width = '480px';
  189. player.style.height = '360px';
  190. player.style.border = '0px';
  191. player.src = 'http://www.youtube.com/embed/' + data.id.$t.split( ':' ).pop() + '?rel=0&autoplay=1&controls=1&showinfo=0';
  192. this.appendChild( player );
  193. //
  194. var prev = object.position.z + 400;
  195. new TWEEN.Tween( camera.position )
  196. .to( { x: object.position.x, y: object.position.y - 25 }, 1500 )
  197. .easing( TWEEN.Easing.Exponential.Out )
  198. .start();
  199. new TWEEN.Tween( { value: prev } )
  200. .to( { value: 0 }, 2000 )
  201. .onUpdate( function () {
  202. move( this.value - prev );
  203. prev = this.value;
  204. } )
  205. .easing( TWEEN.Easing.Exponential.Out )
  206. .start();
  207. }, false );
  208. }
  209. }
  210. function move( delta ) {
  211. for ( var i = 0; i < objects.length; i ++ ) {
  212. var object = objects[ i ];
  213. object.position.z += delta;
  214. if ( object.position.z > 0 ) {
  215. object.position.z -= 5000;
  216. } else if ( object.position.z < - 5000 ) {
  217. object.position.z += 5000;
  218. }
  219. }
  220. }
  221. function onMouseWheel( event ) {
  222. move( event.wheelDelta );
  223. }
  224. function onWindowResize() {
  225. camera.aspect = window.innerWidth / window.innerHeight;
  226. camera.updateProjectionMatrix();
  227. renderer.setSize( window.innerWidth, window.innerHeight );
  228. }
  229. function animate() {
  230. requestAnimationFrame( animate );
  231. TWEEN.update();
  232. if ( auto === true ) {
  233. move( 1 );
  234. }
  235. renderer.render( scene, camera );
  236. }
  237. </script>
  238. </body>
  239. </html>