接到項目, 用react和material-ui實現輪播圖. 搜索了一些方法參考, 不論語言/框架的使用,大致上分爲兩種思路react
在原生JS或者JQuery中,輪播圖的實現通常是這樣子的數組
設置一個ul, 把全部圖片橫向展開,複製第一張圖到最後,設置顯示的界面 正好爲一張圖的大小和寬度,而後不斷向後移動. 到最後一張圖時無變化的切換到第一張, 數據結構
橙色框爲顯示穿體,能夠想象成在後面抽動圖片條, 抽到後一個的時候瞬間無動畫的回到初始狀態.框架
這個能夠類比數據結構中的循環數組,首尾相連,從一個元素開始能夠遍歷完整個隊列而後回到初始元素,相似項鍊的一個圈.ide
而咱們觀察到,影響整個動畫的只有3個元素,當前圖像和先後兩個圖像,所以能夠類比數據結構中的循環隊列,每次只記錄當前元素和當前元素先後的狀態,用index指向當前元素便可動畫
那麼就有三種狀態ui
center 顯示在屏幕中間的圖片this
left 即將從屏幕中移除的圖片,動畫效果直到徹底出屏幕spa
right 即將進入屏幕的圖片,動畫效果從右側貼緊屏幕到正中3d
圖片被包裹在一個div中 如下爲代碼
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { withStyles } from '@material-ui/core/styles'; const styles = ({ root: { position: "relative", padding: 0, margin: 0, overflow: "hidden", width: "100%", }, center: { position: "relative", //顯示在中間的要撐開div width: "100%", left: 0, //用於transition動畫,必須設定left值 transition :"all 1s ease-in-out", }, right: { position :"absolute", left: "100%", width: "100%", top: 0, }, left: { position :"absolute", left: "-100%", width: "100%", top: 0, transition :"all 1s ease-in-out", } }); class Slideshow extends Component { state = { index: 0, images: [], }; turn = step => { let index = this.state.index + step; if (index >= this.state.images.length) { index = 0; } if (index < 0) { index = this.props.images.length - 1; } this.setState({ index: index }) }; go = () => { this.timer = setInterval( () => this.turn(1), this.props.delay * 1000, ) }; clear = () => { clearInterval(this.timer) }; componentDidMount() { const images = [ require('../image/1.jpg'), require('../image/2.jpg'), require('../image/3.png'), ]; this.setState({ images: images, }); this.go() }; componentWillUnmount() { this.clear(); } render() { const { classes } = this.props; return ( <div className={classes.root} onMouseOver={this.clear} //鼠標懸停時中止計時 onMouseLeave={this.go} > { this.state.images.map((item, index) => ( <img src={ item } alt="" key={index} className={ classNames( { [classes.center]: index === this.state.index }, { [classes.right]: index === this.state.index + 1 || (index === 0 && this.state.index === this.state.images.length - 1) }, { [classes.left]: index === this.state.index - 1 || (index === this.state.images.length - 1 && this.state.index === 0) }, ) }/> )) } </div> ) } } Slideshow.propTypes = { classes: PropTypes.object.isRequired, }; export default withStyles(styles)(Slideshow);
有了基本框架以後,向左向右翻動的按鈕和顯示頁數的按鈕也能夠直接作出來了. 只須要改變當前頁面的index便可生效
在作按鈕的時候發現一個問題,這個方法在只有3張圖片的時候 會有奇怪的狀況出現.緣由是由於 只有3張圖片 每一張都是本體 前驅 後繼 每次轉換的時候都會進行一次transform
解決辦法 用4張圖片 或者設置left和right 的opacity:0