Skip to content

Instantly share code, notes, and snippets.

@idmontie
Last active April 6, 2018 22:30
Show Gist options
  • Save idmontie/ca6325a0e5d6e93afed331ff682b352d to your computer and use it in GitHub Desktop.
Save idmontie/ca6325a0e5d6e93afed331ff682b352d to your computer and use it in GitHub Desktop.
Mouse Move Example
const centerX = Math.floor(window.innerWidth / 2);
const centerY = Math.floor(window.innerHeight / 2);
class App extends Component {
render() {
return (
<MousePosition>
{({ x, y }) => (
<Tween func={easeOutQuad} defaultStart={centerX} end={x}>
{({ current: cx }) => (
<Tween func={easeOutQuad} defaultStart={centerY} end={y}>
{({ current: cy }) => (
<Rectangle x={cx} y={cy} />
)}
</Tween>
)}
</Tween>
)}
</MousePosition>
);
}
}
var mountNode = document.getElementById('app');
render(<App />, mountNode);
function easeOutQuad(diff, start, change, duration) {
return -change * (diff/=duration) * (diff-2) + start;
}
class MousePosition extends Component {
constructor(props) {
super(props);
this.onMouseMove = this._onMouseMove.bind(this);
this.state = {
x: 0,
y: 0,
};
}
componentDidMount() {
document.addEventListener('mousemove', this.onMouseMove);
}
_onMouseMove(e) {
this.setState(() => ({
x: e.clientX,
y: e.clientY,
}));
}
render() {
const { x, y } = this.state;
const { children } = this.props;
return children({ x, y });
}
}
const Rectangle = ({ x, y }) => (
<div style={{ position: 'fixed', top: `${y}px`, left: `${x}px`, height: '10px', width: '10px', backgroundColor: 'black' }} />
);
class App extends Component {
render() {
return (
<SimpleTween start={0} end={600}>
{({ current }) => (
<Rectangle x={current} y={600} />
)}
</SimpleTween>
);
}
}
class SimpleTween extends Component {
static defaultProps = {
duration: 1000,
}
constructor(props) {
super(props);
this.state = {
timeStart: +new Date(),
current: props.start,
};
this.calculate = this._calculate.bind(this);
}
componentDidMount() {
this.timer = setInterval(this.calculate, 1000 / 60);
}
componentWillUnmount() {
if (this.timer) {
clearInterval(this.timer);
}
}
_calculate() {
const { duration, start, end } = this.props;
const { timeStart } = this.state;
const time = +new Date() - timeStart;
if (time > duration) {
this.setState(() => ({
current: end,
}));
return;
}
const currentPosition = easeOutQuad(time, start, end - start, duration);
this.setState(() => ({
current: currentPosition,
}));
}
render() {
const { children } = this.props;
const { current } = this.state;
return children({ current });
}
}
class Tween extends Component {
static defaultProps = {
duration: 1000,
}
constructor(props) {
super(props);
this.state = {
timeStart: +new Date(),
start: props.defaultStart || 0,
current: props.defaultStart || 0,
};
this.calculate = this._calculate.bind(this);
}
componentDidMount() {
this.timer = setInterval(this.calculate, 1000 / 60);
}
componentWillUnmount() {
if (this.timer) {
clearInterval(this.timer);
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.end !== this.props.end) {
this.setState((state) => ({
timeStart: +new Date(),
start: state.current,
}));
}
}
_calculate() {
const { func, duration, end } = this.props;
const { timeStart, start } = this.state;
const time = +new Date() - timeStart;
if (time > duration) {
this.setState(() => ({
current: end,
}));
return;
}
const currentPosition = func(time, start, end - start, duration);
this.setState(() => ({
current: currentPosition,
}));
}
render() {
const { children } = this.props;
const { current } = this.state;
return children({ current });
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment