Skip to content

Instantly share code, notes, and snippets.

@chrisbolin
Last active January 25, 2016 05:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisbolin/541f47e6accadba57c88 to your computer and use it in GitHub Desktop.
Save chrisbolin/541f47e6accadba57c88 to your computer and use it in GitHub Desktop.
Codepen Preview
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title>chris bolin 2</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="app"></div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/react/0.13.0/react.min.js'></script>
<script src="js/index.js"></script>
</body>
</html>
'use strict';
var fx = {
limitUnit: function limitUnit(x) {
return x < 0 ? 0 : x < 1 ? x : 1;
}
};
var ColorBar = React.createClass({
displayName: 'ColorBar',
render: function render() {
var height = fx.limitUnit(this.props.x) * 100;
return React.createElement('div', { style: {
width: this.props.width,
height: height + '%',
backgroundColor: this.props.color,
left: this.props.left,
position: 'absolute',
bottom: 0
} });
}
});
var CardFront = React.createClass({
displayName: 'CardFront',
render: function render() {
var x = this.props.x;
var zIndex = x < 0.5 ? 1 : 0;
var scrollStyle = {
opacity: 1 - 10 * x
};
return React.createElement(
'div',
{ className: 'card-face front', style: { zIndex: zIndex } },
React.createElement(
'div',
{ className: 'title' },
'chris bolin',
React.createElement('hr', null)
),
React.createElement(
'div',
{ className: 'scroll', style: scrollStyle },
'(scroll)'
),
React.createElement(ColorBar, { color: '#EDC919', left: '0%', width: '20%', x: x * 5.2 }),
React.createElement(ColorBar, { color: '#76919A', left: '20%', width: '20%', x: x * 4.7 }),
React.createElement(ColorBar, { color: '#257A97', left: '40%', width: '20%', x: x * 4.4 }),
React.createElement(ColorBar, { color: '#7A486E', left: '60%', width: '20%', x: x * 4 }),
React.createElement(ColorBar, { color: '#FD556F', left: '80%', width: '20%', x: x * 3.5 })
);
}
});
var CardBack = React.createClass({
displayName: 'CardBack',
render: function render() {
var x = this.props.x;
var zIndex = x > 0.5 ? 1 : 0;
var colorH = 0.06;
// if (!zIndex) return null;
return React.createElement(
'div',
{ className: 'card-face back', style: { zIndex: zIndex } },
React.createElement(ColorBar, { color: '#EDC919', width: '10%', left: '0%', x: 2.5 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#76919A', width: '10%', left: '10%', x: 9 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#257A97', width: '10%', left: '20%', x: 4 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#7A486E', width: '10%', left: '30%', x: 6 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#EDC919', width: '10%', left: '40%', x: 5 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#76919A', width: '10%', left: '50%', x: 2 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#257A97', width: '10%', left: '60%', x: 4 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#7A486E', width: '10%', left: '70%', x: 8 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#EDC919', width: '10%', left: '80%', x: 7 * (1 - x) + colorH }),
React.createElement(ColorBar, { color: '#76919A', width: '10%', left: '90%', x: 3 * (1 - x) + colorH })
);
}
});
var CardPlane = React.createClass({
displayName: 'CardPlane',
getStyle: function getStyle() {
var x = this.props.x;
var transform = '\n rotateZ(' + 90 * x + 'deg)\n rotateX(' + 180 * x + 'deg)\n translate3d(' + -50 * x + 'px, 0, 0)\n ';
return {
transform: transform,
WebkitTransform: transform
};
},
render: function render() {
var zFront = this.props.x < 0.5 ? 1 : 0;
var zBack = !zFront;
return React.createElement(
'div',
{ style: this.getStyle(), className: 'card-plane' },
React.createElement(CardFront, { x: this.props.x }),
React.createElement(CardBack, { x: this.props.x })
);
}
});
var Typer = React.createClass({
displayName: 'Typer',
render: function render() {
var x = fx.limitUnit(this.props.x);
if (!x) {
return null;
}
var letters = this.props.children.reduce(function (agg, element) {
if (element.length) {
agg = agg.concat(element.split(''));
} else {
agg.push(element);
}
return agg;
}, []);
letters.push(' ');
var cursor = x < 1 ? '|' : '';
var childrenSubset = letters.slice(0, x * letters.length);
return React.createElement(
'span',
null,
childrenSubset,
' ',
cursor,
' '
);
}
});
var Arrow = React.createClass({
displayName: 'Arrow',
render: function render() {
var x = this.props.x;
var grey = Math.floor(255 * (1 - x));
var transform = 'translateY(' + 10 * x + 'px)';
var style = {
transform: transform,
WebkitTransform: transform,
color: 'rgb(' + grey + ',' + grey + ',' + grey + ')',
opacity: 10 * (1 - x)
};
return React.createElement(
'div',
{ className: 'arrow', style: style },
'↓'
);
}
});
var BackText = React.createClass({
displayName: 'BackText',
render: function render() {
return React.createElement(
'div',
{ className: 'back-text' },
React.createElement(
Typer,
{ x: this.props.x },
'chris bolin',
React.createElement('br', null),
'wannabe polymath',
React.createElement('br', null),
'cambridge, mass, usa',
React.createElement('br', null),
React.createElement('br', null),
'bolin.chris@gmail.com'
)
);
}
});
var App = React.createClass({
displayName: 'App',
getInitialState: function getInitialState() {
return { x: 0 };
},
appStyle: {
height: window.innerHeight + 200
},
handleScrollChange: function handleScrollChange(e) {
var x = fx.limitUnit(window.scrollY / (this.appStyle.height - window.innerHeight));
this.setState({ x: x });
},
componentDidMount: function componentDidMount() {
window.addEventListener('scroll', this.handleScrollChange);
window.addEventListener('resize', this.handleScrollChange);
this.container = document.getElementsByClassName('main');
},
render: function render() {
var x = this.state.x;
var planeW = 0.9; // plane annimation weight (0-1)
var planeX = fx.limitUnit(x / planeW);
var typerX = fx.limitUnit(1 / (1 - planeW) * (-planeW + x));
return React.createElement(
'div',
{ className: 'app', style: this.appStyle },
React.createElement(
'div',
{ className: 'container' },
React.createElement(CardPlane, { x: planeX }),
React.createElement(Arrow, { x: x }),
React.createElement(BackText, { x: typerX })
)
);
}
});
React.render(React.createElement(App, null), document.getElementById('app'));
@import url(https://fonts.googleapis.com/css?family=Inconsolata);
@import url(https://fonts.googleapis.com/css?family=Playfair+Display:400italic);
body {
background-color: white;
margin: 0;
}
.container {
position: fixed;
}
.card-plane {
position: absolute;
width: 200px;
height: 350px;
margin: 50px calc(50vw - 100px);
}
.card-plane .card-face {
width: 100%;
height: 100%;
position: absolute;
}
.card-plane .card-face.front {
background-color: black;
color: white;
font-style: italic;
font-family: 'Playfair Display', Serif;
}
.card-plane .card-face.front .title {
font-size: 21px;
padding: 22px 22px;
}
.card-plane .card-face.front .title hr {
margin: 7px 0;
}
.card-plane .card-face.front .scroll {
position: absolute;
text-align: center;
width: 100%;
color: #7D7D7D;
bottom: -30px;
font-size: 12px;
}
.card-plane .card-face.back {
color: white;
background-color: #FD556F;
/* reversed for the back of the card */
width: 350px;
height: 200px;
-webkit-transform: rotateZ(90deg) rotateX(180deg) translate3d(75px, -75px, 0px);
transform: rotateZ(90deg) rotateX(180deg) translate3d(75px, -75px, 0px);
}
.back-text {
position: fixed;
left: calc(50vw - 200px + 40px);
top: 90px;
font-family: Inconsolata, monospace;
color: white;
font-size: 14px;
width: 300px;
}
.arrow {
font-size: 24px;
font-family: 'Times New Roman', serif;
position: fixed;
text-align: center;
width: 100%;
top: 350px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment