Skip to content

Instantly share code, notes, and snippets.

@shshaw
Created April 20, 2018 19:11
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 shshaw/e3991c94f8a0be9a124ca4c5f5c72017 to your computer and use it in GitHub Desktop.
Save shshaw/e3991c94f8a0be9a124ca4c5f5c72017 to your computer and use it in GitHub Desktop.
@keyframers 1.2.0 | Reactive Animations with RxJS | CodePen Houston
<a href="https://youtu.be/H7FEK6geguM" target="_blank" data-keyframers-credit style="color: #000"></a>
<script src="https://codepen.io/shshaw/pen/QmZYMG.js"></script>
<h1 id="heading">@davidkpiano<span id="pos"></span></h1>
<h2 style="text-align: center"><a href="http://reactivex.io/rxjs">reactivex.io/rxjs</a><br/>
</h2>
<div id="card">
<div id="title"></div>
</div>

@keyframers 1.2.0 | Reactive Animations with RxJS | CodePen Houston

This week's @keyframers episode featured David Khourshid giving a short talk and live coding demonstration at CodePen Houston on Reactive Animations with RxJS followed by a Q&A.

A Pen by Shaw on CodePen.

License.

console.clear();
const { body } = document;
const { clientWidth, clientHeight } = body;
const pos = document.querySelector('#pos');
const cardElm = document.querySelector('#card');
const mouseMove$ = Rx.Observable
.fromEvent(body, 'mousemove')
.map(event => ({
x: event.clientX,
y: event.clientY
}));
const touchMove$ = Rx.Observable
.fromEvent(body, 'touchmove')
.map(event => ({
x: event.touches[0].clientX,
y: event.touches[0].clientY
}));
const move$ = Rx.Observable
.merge(mouseMove$, touchMove$);
const animationFrame$ = Rx.Observable
.interval(0, Rx.Scheduler.animationFrame);
const smoothMove$ = animationFrame$
.withLatestFrom(move$, (tick, move) => move)
.scan((fullValue, move) => {
return lerp(fullValue, move);
});
function lerp(start, end) {
const dx = end.x - start.x;
const dy = end.y - start.y;
const rate = 0.05;
return {
x: start.x + dx * rate,
y: start.y + dy * rate
};
}
smoothMove$.subscribe(pos => {
const rotX = (pos.y / clientHeight * -50) + 25;
const rotY = (pos.x / clientWidth * 50) - 25;
cardElm.style.cssText = `
transform: rotateX(${rotX}deg) rotateY(${rotY}deg)
`;
});
<script src="https://unpkg.com/@reactivex/rxjs@latest/dist/global/Rx.min.js"></script>
#heading {
margin: 0;
}
a {
color: #888;
}
#card {
height: 50vmin;
width: 90vmin;
background-color: white;
background-image: url(https://images.unsplash.com/photo-1521916396286-3f65e9f0eddc?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=4eb92aa01a62d3c6bb783370514dcb7a&auto=format&fit=crop&w=1050&q=80); background-size: cover;
// background-image: url(http://reactivex.io/rxjs/img/withLatestFrom.png); background-size: contain;
background-repeat: no-repeat;
background-position: center center;
box-shadow: 0 1rem 3rem rgba(black, 0.2);
transform-style: preserve-3d;
&:before, &:after {
content: '';
position: absolute;
display: block;
height: 2px;
width: 2px;
border-radius: 50%;
background: rgba(white, 0.2);
filter: blur(1px);
}
&:before {
transform: translateZ(1rem);
$shadows: ();
@for $i from 1 through 50 {
$shadows: append($shadows, random(90) * 1vmin random(50) * 1vmin 0 white, comma);
}
box-shadow: $shadows;
}
&:after {
height: 3px;
width: 3px;
transform: translateZ(2rem);
$shadows: ();
@for $i from 1 through 50 {
$shadows: append($shadows, random(90) * 1vmin random(50) * 1vmin 0 white, comma);
}
box-shadow: $shadows;
}
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transform-style: preserve-3d;
perspective: 1000px;
}
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
html {
background: linear-gradient(to bottom, #dbe6ed, #cfdde5);
}
*, *:before, *:after {
box-sizing: border-box;
position: relative;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment