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);

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

    不要说我不会,要说我可以学
  • 相关阅读:
    博客园定制
    【杂文】久 等 了
    【杂文】随心一记
    NOIP2021游寄
    【python】mac+appium+python的环境配置完整流程
    压力测试平台(nGrinder)入门到精通教程
    Gunicorn启动flask项目
    统计代码测试覆盖率Python
    Android开发Google Pixel、Google Nexus系列手机刷机获取root并且设置ro.debuggable=1的方法
    c宏定义#define、#、##、__VA_ARGS__符号的理解
  • 原文地址:https://www.cnblogs.com/seemoon/p/14482229.html
Copyright © 2011-2022 走看看