zoukankan      html  css  js  c++  java
  • react多张图片切换组件,仿优酷图片切换(附图)

    前言:之前写过图片切换组件,例如通过改变state,读取图片数组下标来实现切换,感觉效果不是很好,太过生硬,并且因为每次切换时候读取到的下标时候会去重新请求图片的url,重复浪费资源。

     重新整理功能:

    1、点击右侧icon时候切换下面4张图片,并附带有平移动画效果

    2、点击左侧icon切换前张图片,并附带有平移动画效果

    思路整理:

    1、使用css的transform,可以将元素旋转,缩放,移动,倾斜

    2、使用object-fit:cover需要设置图片填充效果,(每张图片大小不一致)

    3、保证每张图片在同一行

    4、切换时候设置transform的translateX偏移宽度

    按照上面的思路我们贴下代码和初步的实现:

    初步less文件----------------

    .wrap_scrollImg {
      width: 100%;
      height: 300px;
      background-color: #2C9806;
      overflow: hidden;
      position: relative;
    
      span {
        z-index: 11;
        position: absolute;
        display: inline-block;
        height: 50px;
        width: 50px;
        background-color: red;
        top: 0;
        bottom: 0;
        margin: auto;
      }
    
      .left_icon {
        left: 0;
      }
    
      .right_icon {
        right: 0;
      }
    
      ul {
        z-index: 10;
        height: 300px;
        white-space: nowrap;
        position: absolute;
    
        li {
          height: 100%;
          display: inline-block;
          width: 24%;
          margin-left: 1%;
    
          img {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }
      }
    }

    初步jsx文件---------------

    import React, { Component, useState, memo } from 'react';
    import styles from './index.less';
    
    function Index(props) {
    
      const { imgData } = props;
      const [translateX, setTranslateX] = useState(0); //设置偏移数值
    
      const clickRightIcon = () => {
        setTranslateX(translateX + 400); //随便写个偏移值测试
      };
      const clickLeftIcon = () => {
        if (translateX === 0) return;
        setTranslateX(translateX - 400);
      };
      console.log('translateX', translateX);
      return (
        <div className={styles.wrap_scrollImg}>
          <span className={styles.left_icon} onClick={clickLeftIcon}></span>
          <span className={styles.right_icon} onClick={clickRightIcon}></span>
          <ul style={{ transform: `translateX(${translateX}px)` }}>
            {imgData.map(item => {
              return <li>
                <img src={item.imgUrl} alt={item.name}/>
              </li>;
            })}
    
          </ul>
        </div>
      );
    }
    
    export default memo(Index);

    以上代码初步效果-------------

    可以看到点击左右方块图片‘切换了’,分析下有什么不足:每次点击切换时候需要偏移的宽度不准确、左侧边缘有缝隙(margin-left导致的)、切换时候偏移效果生硬、左右切换方向错了、偏移到最后一张图片位置时候需要停止,

    经过改造效果:

     最终代码:

    less文件-----------------

    
    .wrap_scrollImg {
      width: 100%;
      height: 220px;
      //background-color: #2C9806;
      overflow: hidden;
      position: relative;
    
      &:hover {
        span {
          display: inline-block;
        }
      }
    
      span {
        cursor: pointer;
        z-index: 11;
        position: absolute;
        display: none;
        background-color: rgba(0, 0, 0, 0.3);
        top: 0;
        bottom: 0;
        margin: auto;
        height: 35px;
        line-height: 35px;
        width: 24px;
        text-align: center;
        color: white;
        font-size: 20px;
        transition: 0.2s;
    
        &:hover {
          font-size: 22px;
        }
      }
    
      .left_icon {
        left: 0;
      }
    
      .right_icon {
        right: 0;
      }
    
      ul {
        z-index: 10;
        height: inherit;
        white-space: nowrap;
        position: absolute;
        transition: all 0.5s ease-in 0s;  //偏移的过度效果
        margin-right: -1%; //设置ul偏右-用来抵消li元素右边距1%导致的缺口
    
        li {
          height: 100%;
          display: inline-block;
          min-width: calc(24%);
          width: calc(24%);
          margin-right: 1%;  //图片右边距
          overflow: hidden;
          border-radius: 6px;
          cursor: pointer;
    
          img {
            transition: all 0.3s;
            width: 100%;
            height: 100%;
            object-fit: cover;
    
            &:hover {
              transform: scale(1.1);
            }
          }
        }
      }
    }

    js文件---------------

    import React, { Component, useState, memo, createRef } from 'react';
    import styles from './index.less';
    import { Icon } from 'antd';
    
    function Index(props) {
      const ref = createRef();
      const { imgData } = props;
      const [translateX, setTranslateX] = useState(0); //每次偏移数值
    
      /**
       * 点击右侧按钮
       */
      const clickRightIcon = () => {
        if (ref.current.scrollWidth < Math.abs(translateX) + Math.abs(ref.current.offsetWidth)) {//到最后一页时候需要停止点击按钮
          return;
        }
        setTranslateX(translateX - ref.current.offsetWidth); //每次滚动可见区域宽度
      };
    
      /**
       * 点击左侧按钮
       */
      const clickLeftIcon = () => {
        if (translateX === 0) return;
        setTranslateX(translateX + ref.current.offsetWidth);
      };
      console.log('translateX', translateX);
      console.log('ref', ref);
      return (
        <div className={styles.wrap_scrollImg}>
          <span className={styles.left_icon} onClick={clickLeftIcon}><Icon type="left"/></span>
          <span className={styles.right_icon} onClick={clickRightIcon}><Icon type="right"/></span>
          <ul style={{ transform: `translateX(${translateX}px)` }} ref={ref}>
            {imgData.map(item => {
              return <li>
                <img src={item.imgUrl} alt={item.name}/>
              </li>;
            })}
    
          </ul>
        </div>
      );
    }
    
    export default memo(Index);

    以上因为没有其他特定业务需求,所以就只封装成这个样子,有业务需求其实再在基础上增加几个参数就可以,例如每次图片显示多少张、或者切换过度时间为多少。思路对了就很简单。需要比较注意的点我已经再上面给出注释了

    不要说我不会,要说我可以学
  • 相关阅读:
    【Educational Codeforces Round 101 (Rated for Div. 2) C】Building a Fence
    【Codeforces Round #698 (Div. 2) C】Nezzar and Symmetric Array
    【Codeforces Round #696 (Div. 2) D】Cleaning
    【Codeforces Round #696 (Div. 2) C】Array Destruction
    【Educational Codeforces Round 102 D】Program
    【Educational Codeforces Round 102 C】No More Inversions
    【Good Bye 2020 G】Song of the Sirens
    【Good Bye 2020 F】Euclid's nightmare
    使用mobx入门
    requestAnimationFrame 控制速度模拟setinterval
  • 原文地址:https://www.cnblogs.com/seemoon/p/14482229.html
Copyright © 2011-2022 走看看