Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A CodePen by PrithvirajBilla. Spread - CSS Exploration: Origami like plane creation.
<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 );
@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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment