CSS Exploration: Origami like plane creation.
A Pen by Mathias Paumgarten on CodePen.
| <div id="container"></div> | |
| <div id="tag" class="before"> | |
| <h1>SPREAD</h1> | |
| <p>Click anywhere to have the plane spread</p> | |
| <ul> | |
| <li><a href="https://github.com/MathiasPaumgarten/spread">Github</a></li> | |
| </ul> | |
| <span>by <a href="http://mathias-paumgarten.com">Mathias Paumgarten</a></span> | |
| </div> |
| /* | |
| * The original code uses AMD and can be | |
| * found here: | |
| * https://github.com/MathiasPaumgarten/spread | |
| */ | |
| var container = document.getElementById( "container" ); | |
| var tag = document.getElementById( "tag" ); | |
| var orientation = { | |
| TOP: 0, | |
| RIGHT: 1, | |
| BOTTOM: 2, | |
| LEFT: 3 | |
| } | |
| var options = { | |
| tileSize: 80, | |
| color: "#4fb0ca", | |
| randomColor: true | |
| } | |
| var color = function() { | |
| var values = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ]; | |
| var color = "#", i = 7; | |
| while ( --i ) color += values[ ~~( Math.random() * 16 ) ]; | |
| return color; | |
| } | |
| var random = function( min, max ) { | |
| return min + Math.random() * ( max - min ); | |
| } | |
| var Tile = function( x, y, color, onComplete ) { | |
| var div, inlay, cover; | |
| var neighbors = []; | |
| var isShown = false; | |
| function initUI() { | |
| div = document.createElement( "div" ); | |
| div.className = "tile"; | |
| div.style.width = options.tileSize + "px"; | |
| div.style.height = options.tileSize + "px"; | |
| div.style.top = y * options.tileSize + "px"; | |
| div.style.left = x * options.tileSize + "px"; | |
| inlay = document.createElement( "div" ); | |
| inlay.className = "inlay"; | |
| inlay.style.backgroundColor = color; | |
| cover = document.createElement( "div" ); | |
| cover.className = "cover"; | |
| div.appendChild( inlay ); | |
| inlay.appendChild( cover ); | |
| } | |
| // ------ | |
| // PUBLIC | |
| // ------ | |
| this.isShown = function() { | |
| return isShown; | |
| } | |
| this.getElement = function() { | |
| return div; | |
| } | |
| this.addNeighbor = function( direction, neighbor ) { | |
| neighbors[ direction ] = neighbor; | |
| } | |
| this.fromTop = function() { | |
| div.classList.add( "from-top" ); | |
| show(); | |
| } | |
| this.fromBottom = function() { | |
| div.classList.add( "from-bottom" ); | |
| show(); | |
| } | |
| this.fromRight = function() { | |
| div.classList.add( "from-right" ); | |
| show(); | |
| } | |
| this.fromLeft = function() { | |
| div.classList.add( "from-left" ); | |
| show(); | |
| } | |
| function onTransitionEnd() { | |
| for ( var i = 0; i < neighbors.length; i++ ) { | |
| if ( neighbors[ i ] && ! neighbors[ i ].isShown() ) { | |
| neighbors[ i ][ getFunctionName( i ) ](); | |
| setTimeout( onTransitionEnd, random( 10, 200 ) ); | |
| break; | |
| } | |
| } | |
| } | |
| // ------- | |
| // PRIVATE | |
| // ------- | |
| function getFunctionName( index ) { | |
| return [ "fromBottom", "fromLeft", "fromTop", "fromRight" ][ index ]; | |
| } | |
| function show() { | |
| isShown = true; | |
| setTimeout( function() { | |
| inlay.classList.add( "show" ); | |
| setTimeout( onTransitionEnd, random( 200, 300 ) ); | |
| setTimeout( onComplete, 300 ); | |
| }, 50 ); | |
| } | |
| initUI(); | |
| } | |
| var Controller = function( container, size, position ) { | |
| var width = Math.ceil( size.width / options.tileSize ); | |
| var height = Math.ceil( size.height / options.tileSize ); | |
| var tiles = []; | |
| var onComplete = null; | |
| var completeCount = 0; | |
| var tileColor = options.randomColor ? color() : options.color; | |
| function init() { | |
| fillScreen(); | |
| snowball(); | |
| } | |
| // ------ | |
| // PUBLIC | |
| // ------ | |
| this.onComplete = function( closure ) { | |
| onComplete = closure | |
| } | |
| this.getColor = function() { | |
| return tileColor; | |
| } | |
| // ------- | |
| // PRIVATE | |
| // ------- | |
| function fillScreen() { | |
| var tile; | |
| var length = width * height; | |
| for ( var y = 0; y < height; y++ ) { | |
| for ( var x = 0; x < width; x++ ) { | |
| tile = new Tile( x, y, tileColor, tileComplete ); | |
| container.appendChild( tile.getElement() ); | |
| tiles.push( tile ); | |
| } | |
| } | |
| for ( var i = 0; i < length; i++ ) { | |
| tile = tiles[ i ]; | |
| row = ~~( i / width ); | |
| col = i % width; | |
| if ( col < width - 1 ) | |
| tile.addNeighbor( orientation.RIGHT, tiles[ i + 1 ] ); | |
| if ( col > 0 ) | |
| tile.addNeighbor( orientation.LEFT, tiles[ i - 1 ] ); | |
| if ( row > 0 ) | |
| tile.addNeighbor( orientation.TOP, tiles[ i - width ] ); | |
| if ( row < height - 1 ) | |
| tile.addNeighbor( orientation.BOTTOM, tiles[ i + width ] ); | |
| } | |
| } | |
| function snowball() { | |
| var row = ~~( position.y / options.tileSize ); | |
| var col = ~~( position.x / options.tileSize ); | |
| tiles[ col + row * width ].fromTop(); | |
| } | |
| function tileComplete() { | |
| completeCount++; | |
| if ( completeCount === tiles.length && onComplete ) { | |
| onComplete(); | |
| } | |
| } | |
| init(); | |
| } | |
| function initListeners() { | |
| document.addEventListener( "click", onClick, false ); | |
| document.addEventListener( "touchstart", onTouchEnd, false ); | |
| } | |
| function onClick( event ) { | |
| var div = document.createElement( "div" ); | |
| var size = { | |
| width: window.innerWidth, | |
| height: window.innerHeight | |
| } | |
| var position = { | |
| x: event.pageX, | |
| y: event.pageY | |
| } | |
| var controller = new Controller( div, size, position ); | |
| controller.onComplete( function() { | |
| document.body.style.backgroundColor = controller.getColor(); | |
| container.removeChild( div ); | |
| } ); | |
| container.appendChild( div ); | |
| } | |
| function onTouchEnd( event ) { | |
| var touch = event.touches[ 0 ]; | |
| event.pageX = touch.pageX; | |
| event.pageY = touch.pageY; | |
| onClick( event ); | |
| } | |
| function setTag() { | |
| tag.className = "before in"; | |
| setTimeout( function() { | |
| tag.className = ""; | |
| }, 300 ); | |
| } | |
| function start() { | |
| var event = { | |
| pageX: window.innerWidth / 2, | |
| pageY: window.innerHeight / 2 | |
| } | |
| onClick( event ); | |
| } | |
| initListeners(); | |
| setTag(); | |
| setTimeout( start, 1000 ); |
CSS Exploration: Origami like plane creation.
A Pen by Mathias Paumgarten on CodePen.
| @import "compass"; | |
| @import url( http://fonts.googleapis.com/css?family=Quicksand ); | |
| html, body { | |
| width: 100%; | |
| height: 100%; | |
| margin: 0; | |
| padding: 0; | |
| overflow: hidden; | |
| } | |
| .tile { | |
| position: absolute; | |
| display: none; | |
| @include perspective( 300px ); | |
| @include transform-style( preserve-3d ); | |
| &.from-top { | |
| display: block; | |
| @include perspective-origin( 50% 0 ); | |
| .inlay { | |
| @include transform-origin( 50%, 0, 0 ); | |
| @include transform( rotateX( -90deg ) ); | |
| } | |
| } | |
| &.from-bottom { | |
| display: block; | |
| @include perspective-origin( 50% 100% ); | |
| .inlay { | |
| @include transform-origin( 50%, 100%, 0 ); | |
| @include transform( rotateX( 90deg ) ); | |
| } | |
| } | |
| &.from-left { | |
| display: block; | |
| @include perspective-origin( 0 50% ); | |
| .inlay { | |
| @include transform-origin( 0, 50%, 0 ); | |
| @include transform( rotateY( 90deg ) ); | |
| } | |
| } | |
| &.from-right { | |
| display: block; | |
| @include perspective-origin( 100% 50% ); | |
| .inlay { | |
| @include transform-origin( 100%, 50%, 0 ); | |
| @include transform( rotateY( -90deg ) ); | |
| } | |
| } | |
| } | |
| .inlay { | |
| width: 100%; | |
| height: 100%; | |
| @include single-transition( all, 0.3s, ease-in-out ); | |
| } | |
| .cover { | |
| width: 100%; | |
| height: 100%; | |
| background-color: rgba( 0, 0, 0, 0.4 ); | |
| @include single-transition( background-color, 0.3s, ease-in-out ); | |
| } | |
| .tile .inlay.show { | |
| @include transform( rotateX( 0 ) rotateY( 0 ) ); | |
| .cover { | |
| background-color: rgba( 0, 0, 0, 0 ); | |
| } | |
| } | |
| #tag.before { | |
| width: 0; | |
| left: 0; | |
| padding: 15px 0 0 0; | |
| h1, p, ul, span { | |
| opacity: 0; | |
| @include transform( translate3d( -50px, 0, 0 ) ); | |
| } | |
| } | |
| #tag.in { | |
| width: 220px; | |
| } | |
| #tag { | |
| @include single-transition( all, 0.3s, cubic-bezier( 0.8, 0, 0.2, 1 ) ); | |
| position: fixed; | |
| width: 180px; | |
| height: 180px; | |
| top: 20px; | |
| left: 20px; | |
| font-family: "Quicksand", sans-serif; | |
| padding: 15px 0 0 20px; | |
| background-color: #000; | |
| color: #fff; | |
| h1, p, ul, span { | |
| opacity: 1; | |
| @include transform( translate3d( 0, 0, 0 ) ); | |
| } | |
| h1 { | |
| @include single-transition( all, 0.3s, ease-in-out, 0.3s ); | |
| font-size: 30px; | |
| font-weight: 400; | |
| margin: 0; | |
| } | |
| p { | |
| @include single-transition( all, 0.3s, ease-in-out, 0.4s ); | |
| } | |
| ul { | |
| @include single-transition( all, 0.3s, ease-in-out, 0.6s ); | |
| } | |
| p , ul a { | |
| font-size: 12px; | |
| font-weight: 700; | |
| } | |
| a { | |
| color: #fff; | |
| text-decoration: none; | |
| } | |
| a:hover { | |
| background-color: #333; | |
| } | |
| span { | |
| @include single-transition( all, 0.3s, ease-in-out, 0.7s ); | |
| display: inline-block; | |
| margin-top: 40px; | |
| font-size: 10px; | |
| } | |
| ul { | |
| list-style: none; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| } |