React 轮播图

1、框架搭建

  在该轮播图中,将使用到三个组件:

  • ImgSlides // 轮播图的顶层组件,用于状态控制
  • ImgFigure // 图片组件,用于接收顶层传来的状态,并显示相应的图片
  • ControllerUnit // 控制组件,用于控制图片的显示

首先,将这三个组件简单实现,并编写样式:
ImgSlides 组件

import React, { Component } from 'react';
import '../style/component/imgSlides.css';
class ImgSlides extends Component {

  render() {
    return (
      <div className="slides">
        <ControllerUnit />
        <ImgFigure />
      </div>
    );
  }

}
export default ImgSlides;

ImgSlides 样式

.slides{
  width: 100%;
  height: 40vw;
  position: relative;
  overflow: hidden;

}

ImgFigure 组件

import React, { Component } from 'react';
import '../style/component/imgFigure.css';
class ImgFigure extends Component {
  componentDidMount(){

  }
  render() {
    let arr = [];
    for(let i = 0; i < 3; i++){
      let imgContent =
      <img key={i.toString()} src=`${i.jpg}` alt=`${图片i}`/>
      arr.push(imgContent);
    }
    return (
      <div className="imgs">{arr}</div>
    );
  }
}

export default ImgFigure;

ImgFigure 样式

img{
  border: none;
  width: 100%;
  height: 40vw;
  transition: opacity 1s;
}
.imgs img{
  position: absolute;
  top: 0;
}

ControllerUnit 组件

import React, { Component } from 'react';
import '../style/component/controllerUnit.css';
class ControllerUnit extends Component {
  render() {
    let arr = [];
    for(let i = 0; i < 3; i++){
      let btnContent = 
          <span key={i.toString()} ></span>

        arr.push(btnContent);
    }
    return(
      <nav className="btns">{arr}</nav>
    );
  }
}
export default ControllerUnit;

ControllerUnit 样式

.btns{
  display: flex;
  position: absolute;
  bottom: 1rem;
  z-index: 9;
  left: 50%;
  margin-left: -3rem;
}
.btns span{
  display: block;
  width: 1rem;
  height: 1rem;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  border: 2px solid rgba(0, 0, 0, 0.5);
  transition: background .5s;
  margin: 0.5rem;
}

2、图片处理

  考虑到组件的灵活性,我们在组件中不将图片信息写死,而是从外部传入,组件内部通过 props 获得图片信息。
  首先编写图片数据集:src/data/imageDatas.json

[
  {
    "filename":"home1.jpg",
    "title":"1",
    "desc":"it is 1.jpg"
  },
  {
    "filename":"home2.jpg",
    "title":"2",
    "desc":"it is 2.jpg"
  },
  {
    "filename":"home3.jpg",
    "title":"3",
    "desc":"it is 3.jpg"
  }
]

  接着,编写图片URL处理工具函数:src/util.js(其中图片存放在src/images/x.jpg下)

export function getImageUrl(imageDatasArr){
  for(var i = 0; i < imageDatasArr.length; i++){
    var singleImageData = imageDatasArr[i];
    singleImageData.imageURL = require('./images/' + singleImageData.filename); 
    imageDatasArr[i] = singleImageData;
  }
  return imageDatasArr;
}

其中,通过 require 来请求图片。
  最后在 App.js 中将图片数据传给 ImgSlides 组件。

import ImgSlides from './component/ImgSlides'
import {getImageUrl} from './util';
// 获得图片数据
var imageDatas = require('./data/imageDatas.json');
// 拼装图片URL
imageDatas = getImageUrl(imageDatas);

class App extends Component {
  render() {
    return <ImgSlides imageDatas={imageDatas}/>
  }
}

3、图片轮播

  (1)图片轮播中需要当前照片显示状态,即该那张图片显示,将该状态定义在 ImgSlides 组件的 state 中,通过改变 state 来渲染组件。(ImgSlides 组件代码片段)

class ImgSlides extends Component {
  constructor(props){
    super(props);
    this.state = {
      current: 0, // 当前图片
      imgsArrangeArr: [ // 图片样式
        // { // 由于要是用动画,所以不能使用 display: none
             // 注意样式的值为字符串
        //   visibility:'hidden', // 是否显示,
        //   opacity: '0', // 透明度
        // }
      ]
  }
}

  (2)图片状态的改变,也放在 ImgSlides 组件中,这样可以使 ImgFigure 组件只用来显示,不进行图片处理。(ImgSlides 组件代码片段)

setImgArrange(current){
    let imgsArrangeArr = [];
    for (var i = 0; i < this.props.imageDatas.length; i++) {
      if(i === current){ // 如果是当前要显示的图片,
        imgsArrangeArr[i] = {
          visibility: 'visible',
          opacity: '100'
        }
      } else{
        imgsArrangeArr[i] = {visibility:'hidden', opacity: '0'}
      }
    }
    return imgsArrangeArr;
  }

  (3)设定定时器,来改变 this.state.current 的值。(ImgSlides 组件代码片段)

setCurrent(){
    let _this = this;
    setInterval(function(){ 
       _this.setState(function(prev){
// 使用循环队列的思想来设置 current 的值
         let current = (prev.current + 1) % this.props.imageDatas.length;
         let imgsArrangeArr = this.setImgArrange(current);
         return {current: current,
            imgsArrangeArr: imgsArrangeArr};
        });
    },5000);
  }

  (5)图片数据、图片状态传给 ImgFigure 组件(ImgSlides 组件代码片段)

render() {
    return (
      <div className="slides" >
        <ControllerUnit />
        <ImgFigure data = {this.props.imageDatas} current={this.state.current} arrange={this.state.imgsArrangeArr}/>
      </div>
    );
  }

  (6)ImgFigure 组件中进行图片显示:(ImgFigure 组件代码片段)

import React, { Component } from 'react';
import '../style/component/imgFigure.css';
class ImgFigure extends Component {

  render() {
    let arr = [];
    let img = this.props.data;
    for(let i = 0; i < img.length; i++){
      let imgContent =
      <img key={i.toString()} style={this.props.arrange[i]} src={img[i].imageURL} alt={img[i].desc}/>
      arr.push(imgContent);
    }
    return (
      <div className="imgs">{arr}</div>
    );
  }
}

export default ImgFigure;

4、控制按钮实现

  控制按钮实现的功能是:鼠标悬停在哪个按钮上就显示该按钮对应的图片。
  (1)由于图片状态是在 ImgSlides 组件中改变的,所以应该在 ImgSlides 组件中定义方法,在 ControllerUnit 组件中调用,来改变 ImgSlides 中图片的状态。(ImgSlides 组件代码片段)

changeCurrent(index){ // index 表示,鼠标悬停在第 index 个按钮上
    this.setState(function(prev){
      let imgsArrangeArr = this.setImgArrange(index); // 改变图片显示状态
      return {current: index, // 改变状态
      imgsArrangeArr: imgsArrangeArr}
    });
  }

  (2)将图片信息,悬停改变图片状态方法传给 ControllerUnit 组件。(ControllerUnit 组件代码片段)

render() {

    return (
      <div className="slides" onMouseOver={this.hoverHandle} onMouseOut={this.hoverHandle}>
        <ControllerUnit current={this.state.current} changeCurrent={this.changeCurrent}  count={this.props.imageDatas.length} />
        <ImgFigure data = {this.props.imageDatas} current={this.state.current} arrange={this.state.imgsArrangeArr}/>
      </div>
    );
  }

  (3)在 ControllerUnit 组件中,实现鼠标悬停显示图片功能。由于在鼠标悬停事件发生时,要确定是鼠标悬停在哪个按钮上,因此要将按钮的 index 以参数的形式传递给方法。(ControllerUnit 组件代码片段)

<span key={i.toString()} onMouseOver={this.changeCurrent(i)}></span>

由于事件绑定需要传入的是函数,故 changeCurrent 函数应该返回一个闭包函数。(ControllerUnit 组件代码片段)

changeCurrent(index){
    return function(){ 
// 在闭包函数中调用父组件的方法进行图片状态改变
      this.props.changeCurrent(index);
    }.bind(this);
  }

  (4) ControllerUnit 组件完整代码

import React, { Component } from 'react';
import '../style/component/controllerUnit.css';
class ControllerUnit extends Component {
  constructor(props) {
    super(props);
    this.changeCurrent = this.changeCurrent.bind(this);
  }
  changeCurrent(index){
    return function(){
      this.props.changeCurrent(index);
    }.bind(this);
  }
  render() {
    let arr = [];
    for(let i = 0; i < this.props.count; i++){
      let btnContent = null;
      if(i === this.props.current){
        btnContent =
          <span key={i.toString()} style={{background: 'rgba(255,255,255,0.5)'}} onMouseOver={this.changeCurrent(i)}></span>
      } else{
        btnContent =
          <span key={i.toString()} onMouseOver={this.changeCurrent(i)}></span>
      }
        arr.push(btnContent);
    }
    return(
      <nav className="btns">{arr}</nav>
    );
  }
}
export default ControllerUnit;

5、鼠标悬停在图片上停止轮播

  该功能可以看做是一个状态的改变,当鼠标悬停在图片上,关闭定时器,当鼠标移除,启动定时器。但是,将定时器开启关闭比较麻烦。我们需要的是将鼠标悬停在图片上,轮播停止,只要我们不去更改 state.current 就可以将轮播停止。为此,在 ImgSlides 定义状态 (ImgSlides 组件代码片段)

constructor(props){
    super(props);
    this.state = {
      current: 0, // 当前图片
      isHover: false, // 鼠标是否悬停到组件上
      imgsArrangeArr: []
    }
}

  鼠标悬停事件处理(ImgSlides 组件代码片段)
hoverHandle(){
this.setState(function(prev){
return {
isHover: !prev.isHover,
}
})
}
  事件绑定(ImgSlides 组件代码片段)

render() {
    return (
      <div className="slides" onMouseOver={this.hoverHandle} onMouseOut={this.hoverHandle}>
        <ControllerUnit current={this.state.current} changeCurrent={this.changeCurrent}  count={this.props.imageDatas.length} />
        <ImgFigure data = {this.props.imageDatas} current={this.state.current} arrange={this.state.imgsArrangeArr}/>
      </div>
    );
  }

  停止更新 state.current 值(ImgSlides 组件代码片段)

setCurrent(){
    let _this = this;
    setInterval(function(){
      if(!_this.state.isHover){
        // 当鼠标没有悬停在组件上时,更新状态
        _this.setState(function(prev){
          let current = (prev.current + 1) % this.props.imageDatas.length;
          let imgsArrangeArr = this.setImgArrange(current);
          return {current: current,
            imgsArrangeArr: imgsArrangeArr};
        });
      } else{
        return null;
      }
    },5000);
  }

6、完整代码:https://github.com/lujinming1/react-slides

7、Demo:https://lujinming1.github.io/react-slides/

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值