Skip to content

Instantly share code, notes, and snippets.

@ibreathebsb
Last active June 25, 2018 10:34
Show Gist options
  • Save ibreathebsb/1af5cc236ef3ae2acdc95a10f1dcb1d5 to your computer and use it in GitHub Desktop.
Save ibreathebsb/1af5cc236ef3ae2acdc95a10f1dcb1d5 to your computer and use it in GitHub Desktop.
NumberFlip
// NumberFlip.ts
import * as React from 'react';
import cStyle from './NumberFlip.scss'
class NumberFlip extends React.Component {
private static Nums = Array.from({ length: 11 }).map((v, i) => i % 10);
private num: number = 0;
private $content: HTMLElement | null;
private $scroller: HTMLElement | null;
private height: number = 0;
constructor(props: any) {
super(props)
this.num = props.num || 0
}
public render() {
return (
<div>
<div className={cStyle.scroller} ref={$scroller => this.$scroller = $scroller}>
<div className={cStyle.content} ref={$content => this.$content = $content}>
{NumberFlip.Nums.map((value, index) => <div key={index} className={cStyle.num}>{value}</div>)}
</div>
</div>
</div>
)
}
public componentDidMount () {
this.height = (this.$scroller as HTMLElement).clientHeight
}
public flipTo = (num: number, duration: number): void => {
const old = this.num
const diff = num - old
const start = +new Date()
const end = start + duration
let curr = old
const draw = () => {
const now = +new Date()
if (now >= end) {
this.num = num;
(this.$content as HTMLElement).style.transform = `translateY(-${(num % 10) * this.height}px)`;
return
}
const percentage = (now - start) / duration;
const per = this.ease(percentage);
curr = old + per * diff
const transform = `translateY(-${curr % 10 * this.height}px)`;
(this.$content as HTMLElement).style.transform = transform;
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw)
}
private ease(percentage: number): number {
const x = percentage
return x * x * x * x * x;
}
}
export { NumberFlip };
// usage
// App.ts
import * as React from 'react';
import NumberFlip from './components/NumberFlip';
class App extends React.Component {
private fliper: NumberFlip | null;
public render() {
return (
<div>
<NumberFlip ref={fliper => this.fliper = fliper} />
<button onClick={this.random}>random</button>
</div>
);
}
public random = () => {
const num = Math.floor(Math.random() * 1000);
(this.fliper as NumberFlip).flipTo(num, 1000);
}
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment