slider
一组轮播的区域
何时使用
- 主要是针对于移动端
- 常用于一组图片或卡片轮播
demo演示
[ 暂无]
基本使用方法
js:
import PuiSlider from './pui-slider'
render(){
return <div className="wrap" id="wrap">
<PuiSlider currentIndex="2" smallDot={true} autoSpeed="2000" autoSlide={true} wrapHeight="600">
<div>1</div>
<div>2</div>
</PuiSlider>
</div>
}
cs:
.pansliderBox{
position: relative;
.puiSlider{
@include flex-box;
flex-wrap: nowrap;
-webkit-flex-wrap: nowrap;
.sliderItem{
width: 100%;
height: 200px;
img{
width: 100%;
height: 100%;
}
}
}
.sliderDot{
position: absolute;
bottom: 20px;
left: 0;
z-index: 20;
width: 100%;
height: 10px;
display: block;
font-size: 0;
text-align: center;
li{
width: 12px;
height: 12px;
border-radius: 50%;
background: #fff;
display: inline-block;
margin: 6px;
transition: .25s;
-webkit-transition: .25s;
position: relative;
overflow: hidden;
}
li.active{
width: 15px;
background: #fef339;
height: 6px;
border-radius: 6px;
transition: .25s;
-webkit-transition: .25s;
position: relative;
}
}
}
API
参数 | 说明 | 类型 | 默认值 | 是否比传 | 其他 |
---|---|---|---|---|---|
currentIndex | 当前从第几张开始轮播 | string | 1 | 否 | 无 |
autoSlide | 是否自动轮播 | boolean | true | 否 | 无 |
smallDot | 是否有轮播点点跟随 | boolean | true | 否 | 无 |
autoSpeed | 轮播速度 | string | 2000 | 否 | 无 |
wrapHeight | 轮播内容高度 | string | 750 | 否 | 传入的是设计稿的实际高度 |
方法
[ 暂无]
源码
import React, { Component } from 'react';
export default class puiSlider extends Component {
constructor(props) {
super(props);
const {currentIndex=1,swiper=30,smallDot=true,autoSlide=true,autoSpeed=2000,wrapHeight=750}=this.props;
const itemWidth=((wrapHeight-0)/37.5)*(document.getElementsByTagName('html')[0].style.fontSize.replace(/[px]/g,'')-0);
this.state={
currentIndex: currentIndex-0, //当前展示第几张图片
swiper:swiper-0, //最小移动距离,才能切换下一页
smallDot, //是否有小按钮
autoSlide,//是否自动轮播
autoSpeed:autoSpeed-0, //自动轮播定时器间隔
itemWidth, //item的宽度
speed:0, //tanslate移动速度
startX:"", //水平滑动其实位置
curX: "", //水平实时移动位置
moveX: "", //水平移动位置
distance:-((currentIndex-0)*itemWidth), //水平移动距离
}
}
componentDidMount(){
let _this=this;
const {wrapHeight}=_this.props;
window.addEventListener('resize', function () {
_this.setState({
itemWidth:((wrapHeight-0)/37.5)*(document.getElementsByTagName('html')[0].style.fontSize.replace(/[px]/g,'')-0)
})
});
if(this.props.children && this.props.children.length>1){
this.play()
}
}
//开启定时器,自动播放
play=()=>{
if(this.state.autoSlide){
let _this=this;
_this.timer=setInterval(()=>{
let currentIndex=_this.state.currentIndex;
_this.setIndex(currentIndex+1);
},_this.state.autoSpeed);
}
}
//关闭定时器
pause=()=>{
if(this.state.autoSlide){
clearInterval(this.timer)
}
}
//子组头尾克隆渲染件渲染
renderChildren=(children)=>{
const appendedChildren = [
children[children.length - 1],
...children,
children[0]
];
return React.Children.map(appendedChildren,(child,index)=>{
const childClone = React.cloneElement(child, { }); //克隆子组件,并返回一个新的组件,arg(要克隆的组件,新组建增加的属性)
return (
<div className="sliderItem" key={index}>
{childClone}
</div>
)
})
}
translate=(_this,time,distance)=>{
_this.setState({
distance,
speed:time
})
}
//上下切换下一页
setIndex=(index)=>{
const len=this.props.children.length;
if(len>1){
let nextIndex=index;
this.translate(this,300,-(this.state.itemWidth*(nextIndex)))
const _this=this
function translateFunc() {
if (nextIndex == 0) {
nextIndex = len;
_this.translate(_this,0,-(_this.state.itemWidth*(nextIndex)))
_this.setState({
currentIndex:nextIndex,
})
} else if (nextIndex == len + 1) {
nextIndex = 1;
_this.translate(_this,0,-(_this.state.itemWidth*(nextIndex)))
_this.setState({
currentIndex:nextIndex,
})
}else{
_this.setState({
currentIndex:nextIndex,
})
}
_this.refs.puiSlider.removeEventListener('webkitTransitionEnd',translateFunc,false)
_this.refs.puiSlider.removeEventListener('transitionend',translateFunc,false)
}
this.refs.puiSlider.addEventListener('webkitTransitionEnd',translateFunc,false)
this.refs.puiSlider.addEventListener('transitionend',translateFunc,false)
}
}
touchStart=(e)=>{
this.pause()
this.setState({
startX: e.touches[0].pageX
})
}
touchMove=(e)=>{
this.pause()
e.preventDefault();
let curX = e.touches[0].pageX;
let moveX = curX - this.state.startX;
let distance = -(this.state.currentIndex * this.state.itemWidth - moveX);
this.setState({
curX,
moveX,
distance
})
}
touchEnd=()=>{
this.play()
if(Math.abs(this.state.moveX)>this.state.swiper){
if(this.state.moveX>0){
this.setIndex(this.state.currentIndex-1)
}else{
this.setIndex(this.state.currentIndex+1)
}
}else{
this.setIndex(this.state.currentIndex)
}
}
render() {
const {children}=this.props;
let unionStyle={
WebkitTransform: 'translate3d(' + this.state.distance + 'px,'+0+'px,'+0+'px)',
transform: 'translate3d(' + this.state.distance + 'px,'+0+'px,'+0+'px)',
WebkitTransition: 'all ' + this.state.speed+ 'ms ' + 'ease',
transition: 'all ' + this.state.speed + 'ms ' + 'ease',
}
return (
<div className="pansliderBox">
{
(children && children.length>1) ?
<div ref="puiSlider" className="puiSlider" style={unionStyle} onTouchStart={e=>this.touchStart(e)} onTouchMove={e=>this.touchMove(e)} onTouchEnd={e=>this.touchEnd(e)}>{this.renderChildren(children)}</div>
:
<div ref="puiSlider" className="puiSlider">
<div className="sliderItem">{children}</div>
</div>
}
{
(this.state.smallDot && children && children.length>1) ?
<ol className="sliderDot">
{children.length>1 && children.map((item,index)=>(
<li className={this.state.currentIndex==(index+1) ? 'active' : ''} key={index}>{index}</li>
))}
</ol>
:
<ol className="sliderDot">
<li className='active' key={1}>1</li>
</ol>
}
</div>
);
}
}