2022-06-28 工作记录--React-swiper + react-intersection-observer 实现图片在可视范围内时加上其对应动图

React-swiper + react-intersection-observer 实现图片在可视范围内时加上其对应动图

一、前言 ⭐️

最近项目里遇到一个需求⚽️:在一个页面里需同时展示5张动图😎。那么。。。为了提高性能,防止卡顿,前端就需要进行单页面多动效优化处理啦🤔,处理方式如下:🌸

  • 页面一来先展示5张静态图片,只有当某张静态图片进入可视范围内时,才给其加上其对应的动图;未在可视范围内的,就不加上其对应的动图。
    在这里插入图片描述

二、实现效果 ⭐️

请添加图片描述

三、实现步骤 ⭐️

1、安装react-intersection-observer

react-intersection-observer判断是否在可视范围内。

yarn add react-intersection-observer

或者

npm install react-intersection-observer --save
2、安装swiper

实现图片轮播,我安装的是swiper3版本,版本根据需求选择即可。

React-swiper的运用 可查看我的另外一篇博客
在这里插入图片描述

npm i swiper@3 

或者

 yarn add swiper@3
3、到package.json里去判断是否安装成功

在这里插入图片描述

4、对应代码 ⭐️

我分为了三大点:「小萝卜儿们🥕依据这三个点查看对应代码哟」

  • 一、【判断是否在可视范围内】
  • 二、【图片匀速轮播】
    • 「项目需要」让5张图片实现匀速向下滚动的效果。
  • 三、【是否展示动图】
    • 对应索引值的图片出现在可视范围内了,就给其加上对应动图。
      在这里插入图片描述

scenesPage.jsx

import React, { useEffect, useState } from "react";
import { InView } from 'react-intersection-observer'; // 【判断是否在可视范围内】
import Swiper from "swiper"; // 【图片匀速轮播】—— 引入swiper,实现轮播
import { SvgaPlayer } from '@spark/animation'; // 公司内部的组件【动图】
import {RES_PATH} from '../../sparkrc.js';

import "./scenesPage.less"; // 引入样式【根据自己需求编写】

function ScenesPage() {
    // 【是否展示动图】—— 在state里设置变量currentIndex,初始值为0,改变变量的方法名为setCurrentIndex
    const [currentIndex, setCurrentIndex] = useState(0);

    useEffect(() => {
        // 【图片匀速轮播】—— 初始化swiper
        new Swiper('.swiper-container1', {
            direction: 'vertical', // 垂直方向
            freeMode: true, // 设置为true则变为free模式
            freeModeMomentum : false, // free模式下,若设置为false则关闭动量,释放slide之后立即停止不会滑动。【详情参考官网,对应位置截图放在最后面啦】
            // speed: 6000, // 匀速时间【在这儿不要加匀速时间,避免在第一页继续往上拉或最后一页继续往下拉出现大片空白区域的情况出现】
            onTouchEnd: function (swiper, event) { // 回调函数,当释放slider时执行。【详情参考官网,对应位置截图也放在最后面啦】
                let t1 = swiper.translate;
                setTimeout(
                    function () {
                        // console.log(swiper);
                        let t2 = swiper.translate;
                        console.log(t1);
                        console.log(t2);

                        // 判断slide「上滑」、「下拉」、「点击」
                        // if (t1 < t2) {
                        //     console.log('上滑');
                        // } else if (t1 > t2) {
                        //     console.log('下拉');
                        // } else {
                        //     console.log('点击');
                        // }
                        if (t1 > t2 && swiper.isBeginning) { // 在第一页继续向前拖动则toast提示
                            // console.log('下拉');
                            Toast('精彩内容已为你呈现咯,请往下滑动选择喔~', 1000);
                        }
                        if (t1 < t2 && swiper.isEnd) { // 在最后一页继续向后拖动则toast提示
                            // console.log('上滑');
                            Toast('您已浏览全部场景,快选择场景生成你的专属标签吧~', 1000);
                        }
                    }, 30);
            }
        });
    }, []);

    // 场景静图和动图-最好写在utils/constans.js里封装成公共的,避免代码冗余
    const scenes = [{
        imgSrc:`${RES_PATH}场景/场景一.png`,
        motionGraph: `${RES_PATH}svga/场景1.svga`,
    },{
        imgSrc:`${RES_PATH}场景/场景二.png`,
        motionGraph: `${RES_PATH}svga/场景2.svga`,
    },{
        imgSrc:`${RES_PATH}场景/场景三.png`,
        motionGraph: `${RES_PATH}svga/场景3.svga`,
    },{
        imgSrc:`${RES_PATH}场景/场景四.png`,
        motionGraph: `${RES_PATH}svga/场景4.svga`,
    },{
        imgSrc:`${RES_PATH}场景/场景五.png`,
        motionGraph: `${RES_PATH}svga/场景5.svga`,
    }]    

    return (
        <div className="scenesPage">
            {/* 【图片匀速轮播】—— Swiper */}
            <div className="swiper-container swiper-container1">
                <div className="swiper-wrapper swiper-wrapper1">
                    {
                        scenes.map((item, index) => {
                            return (
                                <div className="swiper-slide swiper-slide1"} key={index}>
                                    {/* 【判断是否在可视范围内】—— 需要判断哪些内容是否在可视范围内,就把这些内容写在InView里面 */}
                                    <InView as="div" onChange={(inView, entry) => {
                                        console.log(`${index + 1}张图 出现:`, inView);
                                        if (inView) { // inView:true-在可视范围内;false-不在可视范围内
                                            setTimeout(() => { // 定时器可加可不加,根据实际需求来
                                                // 【是否展示动图】—— 改变变量currentIndex的值为index,相当于:currentIndex = index(赋值)
                                                setCurrentIndex(index);
                                            }, 500)
                                        }
                                    }}>
                                        {/* 静图 */}
                                        <img src={item.imgSrc} alt="" />
                                    </InView>
                                    {
                                        // 【是否展示动图】动图 —— currentIndex等于index,就展示对应静图的动图;否则,不展示
                                        currentIndex == index && <SvgaPlayer
                                            className="motionGraph"
                                            src={item.motionGraph}
                                        />
                                    }
                                </div>
                            )
                        })
                    }
                </div>
            </div>
        </div>
    );
}

export default ScenesPage;

scenesPage.less

@import "../../../node_modules/swiper/dist/css/swiper.css"; /* 【图片匀速轮播】*/

/* 公共方法 【图片匀速轮播】 */
.swiper-container {
    width: 100%;
    height: 100vh;
}
.swiper-slide {
    text-align: center;
    font-size: 18px;
    background: #fff;
  
    /* Center slide text vertically */
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
}
/* 非公共方法 */
.scenesPage {
    position: relative;
    .swiper-slide1 {
      width: 750px;
      height: 1334px;
      position: relative;
      img,.motionGraph {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%,-50%);
          width: 100%;
          height: 100%;
          object-fit: cover;
      }
  	}
  	/*【图片匀速轮播】*/
  	.swiper-container1>.swiper-wrapper1 {
		-webkit-transition-timing-function: linear;    /*之前是ease-out*/
  		-moz-transition-timing-function: linear;
  		-ms-transition-timing-function: linear;
  		-o-transition-timing-function: linear;
  		transition-timing-function: linear;
  		margin: 0 auto;
  	}
}

sparkrc.js

module.exports ={
  "RES_PATH": "/src/assets/",
}

当当当当~大功告成🌶

在这里插入图片描述

【补充1】swiper3-freeModeMomentum属性

在这里插入图片描述
【补充2】swiper3-onTouchEnd属性

官网:https://3.swiper.com.cn/api/callbacks/2014/1217/89.html

在这里插入图片描述
在这里插入图片描述

  • 10
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小呀小萝卜儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值