@6thquake/react-material
Version:
React components that implement Google's Material Design.
292 lines (256 loc) • 7.26 kB
JavaScript
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import withStyles from '../styles/withStyles';
import CarouselItem from './CarouselItem';
import CarouselDots from './CarouselDots';
import CarouselArrow from './CarouselArrow';
const styles = {
root: {
height: '100%',
width: '100%',
overflow: 'hidden',
position: 'relative'
},
scrollwrap: {
overflow: 'hidden',
transition: 'all .5s',
WebkitTransition: 'all .5s',
width: '100%',
height: '100%'
},
mask: {
position: 'absolute',
width: '100%',
height: '100%',
top: '0',
left: '0',
background: 'rgba(0,0,0,0)'
}
};
class Carousel extends React.Component {
constructor(props) {
super(props);
this.vedioLeadToClearIntervalFunc = () => {
this.isVedioPlaying = true;
this.clearIntervalFunc();
};
this.vedioEndLeadToResumeIntervalFunc = () => {
this.isVedioPlaying = false;
this.resumeIntervalFunc();
};
this.clearIntervalFunc = () => {
if (this.props.pause) {
clearInterval(this.interval);
}
};
this.resumeIntervalFunc = () => {
if (this.isVedioPlaying) {
return;
}
if (!this.props.autoplay) {
return;
}
if (this.props.pause) {
this.start();
}
};
this.start = () => {
clearInterval(this.interval); // this.next();
if (this.justInit) {
this.initPic();
}
this.justInit = false;
this.interval = setInterval(() => {
this.next();
}, this.props.delay * 1000);
};
this.initPic = () => {
this.setActive(this.activeIndex, false);
};
this.next = () => {
const len = this.count;
const activeIndex = this.activeIndex;
const nextActiveIndex = activeIndex < len ? activeIndex + 1 : 0;
const self = this;
this.setActive(nextActiveIndex, true);
if (activeIndex === len - 1) {
setTimeout(() => {
self.setActive(0, false);
}, (self.props.speed || '0.5') * 1000);
}
};
this.previous = () => {
const len = this.count;
const activeIndex = this.activeIndex;
const preActiveIndex = activeIndex >= 0 ? activeIndex - 1 : len - 1;
const self = this;
this.setActive(preActiveIndex, true);
if (activeIndex === 0) {
setTimeout(() => {
self.setActive(self.count - 1, false);
}, (self.props.speed || '0.5') * 1000);
}
};
this.setActive = (index, withAnimation) => {
const carouselEl = ReactDOM.findDOMNode(this.carouselRef.current);
const carouselWarpEl = ReactDOM.findDOMNode(this.carouselWarpRef.current);
const width = carouselEl.offsetWidth;
if (!withAnimation) {
carouselWarpEl.style.transition = 'none';
carouselWarpEl.style.WebkitTransition = 'none';
} else {
carouselWarpEl.style.transition = `all ${this.props.speed || '0.5'}s`;
carouselWarpEl.style.WebkitTransition = `all ${this.props.speed || '0.5'}s`;
}
carouselWarpEl.style.marginLeft = `${-1 * (index + 1) * width}px`;
this.activeIndex = index;
this.setState({
temp: new Date().getTime()
});
};
this.chengeActivedByDot = (index, withAnimation) => {
this.isVedioPlaying = false;
this.setActive(index, withAnimation);
};
if (props.speed) {
styles.scrollwrap.transition = `all ${props.speed}s`;
styles.scrollwrap.WebkitTransition = `all ${props.speed}s`;
}
this.count = props.items.length;
this.activeIndex = 0;
this.carouselRef = React.createRef();
this.carouselWarpRef = React.createRef();
this.mainSize = {
width: 0,
height: 0
};
this.isVedioPlaying = false; // 有视频正在播放
this.justInit = true; // 刚刚进来时候
}
componentDidMount() {
const carouselEl = ReactDOM.findDOMNode(this.carouselRef.current);
const carouselWarpEl = ReactDOM.findDOMNode(this.carouselWarpRef.current);
const width = carouselEl.offsetWidth;
this.mainSize = {
width: carouselEl.offsetWidth,
height: carouselEl.offsetHeight
};
carouselWarpEl.style.transition = 'none';
carouselWarpEl.style.WebkitTransition = 'none';
carouselWarpEl.style.minWidth = `${(this.count + 2) * width}px`;
carouselWarpEl.style.marginLeft = `${-1 * width}px`;
/* if (!!this.props.speed) {
carouselWarpEl.style.transition = 'all ' + this.props.speed + 's';
carouselWarpEl.style.WebkitTransition = 'all ' + this.props.speed + 's';
} */
if (this.props.autoplay) {
this.start();
}
}
componentWillUnmount() {
clearInterval(this.interval);
}
render() {
const {
items,
speed,
delay,
pause,
autoplay,
dots,
arrows,
classes
} = this.props;
const self = this;
const _items = items.map((_, index) => {
return React.createElement(CarouselItem, {
isCurrent: index === self.activeIndex,
onCleanInterval: this.vedioLeadToClearIntervalFunc,
onResumeInterval: this.vedioEndLeadToResumeIntervalFunc,
data: _,
size: self.mainSize,
key: `item${index}`,
index: index
});
});
return React.createElement("div", {
ref: this.carouselRef,
className: classes.root
}, React.createElement("div", {
onMouseOver: this.clearIntervalFunc,
onMouseOut: this.resumeIntervalFunc
}, React.createElement("div", {
ref: this.carouselWarpRef,
className: classes.scrollwrap
}, React.createElement(CarouselItem, {
data: items[items.length - 1],
size: self.mainSize,
index: -1
}), _items, React.createElement(CarouselItem, {
data: items[0],
size: self.mainSize,
index: items.length
})), arrows ? React.createElement(CarouselArrow, {
next: () => {
this.isVedioPlaying = false;
this.next();
},
pre: () => {
this.isVedioPlaying = false;
this.previous();
}
}) : null, dots ? React.createElement(CarouselDots, {
count: items.length,
speed: speed,
activeIndex: this.activeIndex,
onChange: this.chengeActivedByDot.bind(this)
}) : null));
}
}
process.env.NODE_ENV !== "production" ? Carousel.propTypes = {
/**
* is arrows showed
*/
arrows: PropTypes.bool,
/**
* autoplay
*/
autoplay: PropTypes.bool,
/**
* delay of pictrue slide,unit second
*/
delay: PropTypes.number,
/**
* is dots showed
*/
dots: PropTypes.bool,
/**
* item list
* eg.
* [{
* src: '/static/images/grid-list/bike.jpg',
* alt: 'images-1',
* },
* {
* src: '/static/images/grid-list/mushroom.jpg',
* alt: 'images-2',
* },
* {
* src: '/static/images/grid-list/burgers.jpg',
* alt: 'images-3',
* }]
*/
items: PropTypes.array.isRequired,
/**
* pause when mouseover
*/
pause: PropTypes.bool,
/**
* speed of pictrue slide,unit second
*/
speed: PropTypes.number
} : void 0;
export default withStyles(styles, {
name: 'RMCarousel'
})(Carousel);