Skip to content

Commit 4ab1776

Browse files
committed
add beforeHook afterHook callbacks to animate prop
1 parent 27c2504 commit 4ab1776

File tree

3 files changed

+63
-47
lines changed

3 files changed

+63
-47
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-scrollchor",
3-
"version": "2.1.4",
3+
"version": "2.2.0",
44
"description": "A React component for scroll to #hash links with smooth animations",
55
"files": [
66
"lib"

src/animatescroll.js

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/scrollchor.jsx

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,79 @@
11
import React, { PropTypes } from 'react';
2-
import animateScroll from './animatescroll';
2+
import warning from 'fbjs/lib/warning';
3+
import { getScrollTop, setScrollTop, getOffsetTop } from './utils';
34

45
export default class Scrollchor extends React.Component {
6+
constructor(props) {
7+
super(props);
8+
this._to = props.to && props.to.replace(/^#/, '') || '';
9+
const {
10+
offset = 0, duration = 400, easing = easeOutQuad,
11+
beforeHook = () => {},
12+
afterHook = () => {}
13+
} = props.animate || {};
14+
this._beforeHook = beforeHook;
15+
this._afterHook = afterHook;
16+
this._animate = { offset, duration, easing };
17+
}
18+
519
static propTypes = {
620
to: PropTypes.string.isRequired,
7-
animate: PropTypes.object
21+
animate: PropTypes.shape({
22+
offset: PropTypes.number,
23+
duration: PropTypes.number,
24+
easing: PropTypes.func,
25+
beforeHook: PropTypes.func,
26+
afterHook: PropTypes.func
27+
})
828
};
929

1030
handleClick = (event) => {
11-
event.preventDefault();
31+
this._beforeHook(event);
1232

13-
const { animate } = this.props;
14-
animateScroll(this._to, animate);
15-
};
33+
event.preventDefault();
34+
animateScroll(this._to, this._animate);
1635

17-
componentWillMount() {
18-
const { to = '' } = this.props;
19-
this._to = to.replace(/^#/, '');
36+
this._afterHook(event);
2037
}
2138

2239
render() {
2340
const { to, animate, ...props } = this.props; // eslint-disable-line no-unused-vars
2441
return <a {...props} href={'#' + this._to} onClick={this.handleClick} />;
2542
}
2643
}
44+
45+
function animateScroll(id, animate) {
46+
const element = id ? document.getElementById(id) : document.body;
47+
48+
warning(element, `Cannot find element: #${id}`);
49+
50+
scrollTo(element, animate);
51+
}
52+
53+
function scrollTo(element, { offset, duration, easing }) {
54+
const start = getScrollTop();
55+
const to = getOffsetTop(element) + offset;
56+
const change = to - start;
57+
const increment = 20;
58+
59+
function animate(elapsedTime) {
60+
const elapsed = elapsedTime + increment;
61+
const position = easing(null, elapsed, start, change, duration);
62+
63+
setScrollTop(position);
64+
65+
if (elapsed < duration) {
66+
setTimeout(function() {
67+
animate(elapsed);
68+
}, increment);
69+
}
70+
}
71+
72+
animate(0);
73+
}
74+
75+
// Default easing function
76+
// jQuery easing 'swing'
77+
function easeOutQuad(x, t, b, c, d) {
78+
return -c * (t /= d) * (t - 2) + b;
79+
}

0 commit comments

Comments
 (0)