react-animated-slider
Advanced tools
Comparing version 0.0.7 to 0.1.0
@@ -127,3 +127,5 @@ module.exports = | ||
_this$props$className = _this$props.classNames, | ||
classNames = _this$props$className === undefined ? {} : _this$props$className; | ||
classNames = _this$props$className === undefined ? {} : _this$props$className, | ||
_this$props$duration = _this$props.duration, | ||
duration = _this$props$duration === undefined ? 2000 : _this$props$duration; | ||
@@ -133,3 +135,4 @@ _this.state = { | ||
classNames: _extends({}, DEFAULT_CLASSNAMES, classNames), | ||
animating: false | ||
animating: false, | ||
duration: duration | ||
}; | ||
@@ -152,3 +155,5 @@ _this.animatedSlideCount = 0; | ||
nextButton = _props$nextButton === undefined ? 'next' : _props$nextButton; | ||
var classNames = this.state.classNames; | ||
var _state = this.state, | ||
classNames = _state.classNames, | ||
animating = _state.animating; | ||
@@ -162,3 +167,4 @@ return _react2.default.createElement( | ||
onClick: this.previous, | ||
className: classNames.previousButton | ||
className: classNames.previousButton, | ||
disabled: animating | ||
}, | ||
@@ -171,3 +177,4 @@ previousButton | ||
onClick: this.next, | ||
className: classNames.nextButton | ||
className: classNames.nextButton, | ||
disabled: animating | ||
}, | ||
@@ -182,3 +189,4 @@ nextButton | ||
key: index, | ||
onAnimationEnd: _this2.onAnimationEnd, | ||
onTouchStart: _this2.handleTouchStart, | ||
onTouchEnd: _this2.handleTouchEnd, | ||
className: classNames.slide + ' ' + _this2.getSlideClass(index) + addClassname(item.props.className) | ||
@@ -198,11 +206,8 @@ }); | ||
this.onAnimationEnd = function (event) { | ||
_this3.animatedSlideCount = _this3.animatedSlideCount + 1; | ||
if (_this3.animatedSlideCount === 2) { | ||
_this3.setState({ | ||
currentSlideIndex: _this3.nextSlideIndex, | ||
animating: false, | ||
animation: undefined | ||
}); | ||
} | ||
this.onAnimationEnd = function () { | ||
_this3.setState({ | ||
currentSlideIndex: _this3.nextSlideIndex, | ||
animating: false, | ||
animation: undefined | ||
}); | ||
}; | ||
@@ -212,5 +217,5 @@ | ||
if (_this3.state.animating) return; | ||
_this3.nextSlideIndex = index; // todo simplify logic into prev/next functions | ||
_this3.animatedSlideCount = 0; | ||
_this3.nextSlideIndex = index; | ||
_this3.setState({ animating: true, animation: animation }); | ||
setTimeout(_this3.onAnimationEnd, _this3.state.duration); | ||
}; | ||
@@ -230,7 +235,7 @@ | ||
this.getSlideClass = function (index) { | ||
var _state = _this3.state, | ||
currentSlideIndex = _state.currentSlideIndex, | ||
classNames = _state.classNames, | ||
animating = _state.animating, | ||
animation = _state.animation; | ||
var _state2 = _this3.state, | ||
currentSlideIndex = _state2.currentSlideIndex, | ||
classNames = _state2.classNames, | ||
animating = _state2.animating, | ||
animation = _state2.animation; | ||
@@ -252,2 +257,62 @@ var lastSlideIndex = _this3.props.children.length - 1; | ||
}; | ||
this.left = 0; | ||
this.handleTouchStart = function (e) { | ||
var _state$classNames = _this3.state.classNames, | ||
previous = _state$classNames.previous, | ||
next = _state$classNames.next; | ||
var touch = e.touches[0]; | ||
_this3.startPageX = touch.pageX; | ||
_this3.startLeft = e.target.getBoundingClientRect().left; | ||
_this3.previousElement = document.getElementsByClassName(previous)[0]; | ||
_this3.nextElement = document.getElementsByClassName(next)[0]; | ||
_this3.previousElementStartLeft = _this3.previousElement.getBoundingClientRect().left; | ||
_this3.nextElementStartLeft = _this3.nextElement.getBoundingClientRect().left; | ||
e.currentTarget.addEventListener('touchmove', _this3.handleTouchMove, { | ||
passive: false | ||
}); | ||
e.target.style.transition = 'none'; | ||
_this3.previousElement.style.transition = 'none'; | ||
_this3.nextElement.style.transition = 'none'; | ||
_this3.previousElement.style.visibility = 'visible'; | ||
_this3.nextElement.style.visibility = 'visible'; | ||
}; | ||
this.animating = false; | ||
this.handleTouchMove = function (e) { | ||
e.preventDefault(); | ||
_this3.animating = _this3.animating || requestAnimationFrame(function () { | ||
var touch = e.touches[0]; | ||
_this3.left = _this3.startLeft + touch.pageX - _this3.startPageX; | ||
_this3.previousElementLeft = _this3.previousElementStartLeft + touch.pageX - _this3.startPageX; | ||
_this3.nextElementLeft = _this3.nextElementStartLeft + touch.pageX - _this3.startPageX; | ||
e.target.style.left = _this3.left + 'px'; | ||
_this3.previousElement.style.left = _this3.previousElementLeft + 'px'; | ||
_this3.nextElement.style.left = _this3.nextElementLeft + 'px'; | ||
_this3.animating = false; | ||
}); | ||
}; | ||
this.handleTouchEnd = function (e) { | ||
e.currentTarget.removeEventListener('touchmove', _this3.handleTouchMove); | ||
console.log('this.startLeft < this.left', _this3.startLeft, _this3.left); | ||
e.target.style.removeProperty('left'); | ||
e.target.style.removeProperty('transition'); | ||
_this3.previousElement.style.removeProperty('visibility'); | ||
_this3.nextElement.style.removeProperty('visibility'); | ||
_this3.previousElement.style.removeProperty('transition'); | ||
_this3.nextElement.style.removeProperty('transition'); | ||
_this3.previousElement.style.removeProperty('left'); | ||
_this3.nextElement.style.removeProperty('left'); | ||
if (_this3.startLeft < _this3.left) { | ||
_this3.previous(); | ||
} else { | ||
_this3.next(); | ||
} | ||
_this3.startLeft = undefined; | ||
_this3.startPageX = undefined; | ||
}; | ||
}; | ||
@@ -254,0 +319,0 @@ |
{ | ||
"name": "react-animated-slider", | ||
"version": "0.0.7", | ||
"version": "0.1.0", | ||
"description": "Animated slider component for react", | ||
@@ -5,0 +5,0 @@ "main": "build/index.js", |
@@ -33,2 +33,6 @@ # react-animated-slider | ||
**duration** - number, default 2000 | ||
Number of milliseconds before removing the `animateIn` and `animateOut` classes and adding `current` | ||
**previousButton** - ReactElement, default "previous" | ||
@@ -35,0 +39,0 @@ |
191
src/index.js
@@ -15,3 +15,3 @@ import React from 'react'; | ||
animateIn: 'animateIn', | ||
animateOut: 'animateOut', | ||
animateOut: 'animateOut' | ||
}; | ||
@@ -26,6 +26,3 @@ | ||
super(props); | ||
const { | ||
slideIndex = 0, | ||
classNames = {}, | ||
} = this.props; | ||
const { slideIndex = 0, classNames = {}, duration = 2000 } = this.props; | ||
this.state = { | ||
@@ -35,2 +32,3 @@ currentSlideIndex: slideIndex, | ||
animating: false, | ||
duration, | ||
}; | ||
@@ -40,30 +38,29 @@ this.animatedSlideCount = 0; | ||
onAnimationEnd = event => { | ||
this.animatedSlideCount = this.animatedSlideCount + 1; | ||
if (this.animatedSlideCount === 2) { | ||
this.setState({ | ||
currentSlideIndex: this.nextSlideIndex, | ||
animating: false, | ||
animation: undefined, | ||
}); | ||
} | ||
} | ||
onAnimationEnd = () => { | ||
this.setState({ | ||
currentSlideIndex: this.nextSlideIndex, | ||
animating: false, | ||
animation: undefined | ||
}); | ||
}; | ||
goTo = (index, animation) => { | ||
if (this.state.animating) return; | ||
this.nextSlideIndex = index; // todo simplify logic into prev/next functions | ||
this.animatedSlideCount = 0; | ||
this.nextSlideIndex = index; | ||
this.setState({ animating: true, animation }); | ||
} | ||
setTimeout(this.onAnimationEnd, this.state.duration); | ||
}; | ||
previous = () => { | ||
const nextSlideIndex = this.state.currentSlideIndex - 1; | ||
const actualNextSlide = nextSlideIndex >= 0 ? nextSlideIndex : this.props.children.length - 1; | ||
const actualNextSlide = | ||
nextSlideIndex >= 0 ? nextSlideIndex : this.props.children.length - 1; | ||
this.goTo(actualNextSlide, PREVIOUS); | ||
} | ||
}; | ||
next = () => { | ||
const nextSlideIndex = (this.state.currentSlideIndex + 1) % this.props.children.length; | ||
const nextSlideIndex = | ||
(this.state.currentSlideIndex + 1) % this.props.children.length; | ||
this.goTo(nextSlideIndex, NEXT); | ||
} | ||
}; | ||
@@ -76,8 +73,16 @@ getSlideClass = index => { | ||
return classNames.current; | ||
} else if (index === currentSlideIndex - 1 || (currentSlideIndex === 0 && index === lastSlideIndex)) { | ||
if (animation === PREVIOUS) return `${classNames.animateIn} ${classNames.previous}`; | ||
} else if ( | ||
index === currentSlideIndex - 1 || | ||
(currentSlideIndex === 0 && index === lastSlideIndex) | ||
) { | ||
if (animation === PREVIOUS) | ||
return `${classNames.animateIn} ${classNames.previous}`; | ||
if (animation === NEXT) return classNames.hidden; | ||
return classNames.previous; | ||
} else if (index === currentSlideIndex + 1 || (index === 0 && currentSlideIndex === lastSlideIndex)) { | ||
if (animation === NEXT) return `${classNames.animateIn} ${classNames.next}`; | ||
} else if ( | ||
index === currentSlideIndex + 1 || | ||
(index === 0 && currentSlideIndex === lastSlideIndex) | ||
) { | ||
if (animation === NEXT) | ||
return `${classNames.animateIn} ${classNames.next}`; | ||
if (animation === PREVIOUS) return classNames.hidden; | ||
@@ -87,31 +92,115 @@ return classNames.next; | ||
return classNames.hidden; | ||
} | ||
}; | ||
startPageX; | ||
startLeft; | ||
left = 0; | ||
previousElement; | ||
nextElement; | ||
previousElementStartLeft; | ||
nextElementStartLeft; | ||
previousElementLeft; | ||
nextElementLeft; | ||
handleTouchStart = e => { | ||
const { previous, next } = this.state.classNames; | ||
const touch = e.touches[0]; | ||
this.startPageX = touch.pageX; | ||
this.startLeft = e.target.getBoundingClientRect().left; | ||
this.previousElement = document.getElementsByClassName(previous)[0]; | ||
this.nextElement = document.getElementsByClassName(next)[0]; | ||
this.previousElementStartLeft = this.previousElement.getBoundingClientRect().left; | ||
this.nextElementStartLeft = this.nextElement.getBoundingClientRect().left; | ||
e.currentTarget.addEventListener('touchmove', this.handleTouchMove, { | ||
passive: false | ||
}); | ||
e.target.style.transition = `none`; | ||
this.previousElement.style.transition = `none`; | ||
this.nextElement.style.transition = `none`; | ||
this.previousElement.style.visibility = `visible`; | ||
this.nextElement.style.visibility = `visible`; | ||
}; | ||
animating = false; | ||
handleTouchMove = e => { | ||
e.preventDefault(); | ||
this.animating = | ||
this.animating || | ||
requestAnimationFrame(() => { | ||
const touch = e.touches[0]; | ||
this.left = this.startLeft + touch.pageX - this.startPageX; | ||
this.previousElementLeft = | ||
this.previousElementStartLeft + touch.pageX - this.startPageX; | ||
this.nextElementLeft = | ||
this.nextElementStartLeft + touch.pageX - this.startPageX; | ||
e.target.style.left = `${this.left}px`; | ||
this.previousElement.style.left = `${this.previousElementLeft}px`; | ||
this.nextElement.style.left = `${this.nextElementLeft}px`; | ||
this.animating = false; | ||
}); | ||
}; | ||
handleTouchEnd = e => { | ||
e.currentTarget.removeEventListener('touchmove', this.handleTouchMove); | ||
console.log('this.startLeft < this.left', this.startLeft, this.left); | ||
e.target.style.removeProperty('left'); | ||
e.target.style.removeProperty('transition'); | ||
this.previousElement.style.removeProperty('visibility'); | ||
this.nextElement.style.removeProperty('visibility'); | ||
this.previousElement.style.removeProperty('transition'); | ||
this.nextElement.style.removeProperty('transition'); | ||
this.previousElement.style.removeProperty('left'); | ||
this.nextElement.style.removeProperty('left'); | ||
if (this.startLeft < this.left) { | ||
this.previous(); | ||
} else { | ||
this.next(); | ||
} | ||
this.startLeft = undefined; | ||
this.startPageX = undefined; | ||
}; | ||
render() { | ||
const { children, className, previousButton = 'previous', nextButton = 'next' } = this.props; | ||
const { classNames } = this.state; | ||
return <div className={className}> | ||
<button | ||
onClick={this.previous} | ||
className={classNames.previousButton} | ||
> | ||
{previousButton} | ||
</button> | ||
<button | ||
onClick={this.next} | ||
className={classNames.nextButton} | ||
> | ||
{nextButton} | ||
</button> | ||
<div className={classNames.track}> | ||
{React.Children.map(children, (item, index) => React.cloneElement( | ||
item, { | ||
key: index, | ||
onAnimationEnd: this.onAnimationEnd, | ||
className: `${classNames.slide} ${this.getSlideClass(index)}${addClassname(item.props.className)}`, | ||
}))} | ||
const { | ||
children, | ||
className, | ||
previousButton = 'previous', | ||
nextButton = 'next' | ||
} = this.props; | ||
const { classNames, animating } = this.state; | ||
return ( | ||
<div className={className}> | ||
<button | ||
onClick={this.previous} | ||
className={classNames.previousButton} | ||
disabled={animating} | ||
> | ||
{previousButton} | ||
</button> | ||
<button | ||
onClick={this.next} | ||
className={classNames.nextButton} | ||
disabled={animating} | ||
> | ||
{nextButton} | ||
</button> | ||
<div className={classNames.track}> | ||
{React.Children.map(children, (item, index) => | ||
React.cloneElement(item, { | ||
key: index, | ||
onTouchStart: this.handleTouchStart, | ||
onTouchEnd: this.handleTouchEnd, | ||
className: | ||
classNames.slide + | ||
' ' + | ||
this.getSlideClass(index) + | ||
addClassname(item.props.className) | ||
}) | ||
)} | ||
</div> | ||
</div> | ||
</div>; | ||
); | ||
} | ||
} | ||
export default Slider; | ||
export default Slider; |
212871
888
83