Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

列表无限循环滚动(中奖名单滚动) #61

Open
shuangmianxiaoQ opened this issue Feb 20, 2021 · 0 comments
Open

列表无限循环滚动(中奖名单滚动) #61

shuangmianxiaoQ opened this issue Feb 20, 2021 · 0 comments
Labels
工作相关 记录工作中遇到的问题或收获

Comments

@shuangmianxiaoQ
Copy link
Owner

shuangmianxiaoQ commented Feb 20, 2021

看似简单的需求,但也踩了不少坑,一步一步来总能解决问题!

实现原理

  1. 将数组第一项加到数组尾部(push)
  2. 利用css动画将列表容器上移
  3. 将数组第一项删除(shift)
  4. 列表容器恢复初始态

核心代码

import React, { useEffect, useRef, useState } from 'react';
import cx from 'classnames';
import { requestInterval, clearRequestInterval } from '@essentials/request-interval';
import { px2vw } from '@/utils/helper';
import styles from './index.module.scss';

const list = [
  {
    id: 1,
    picUrl: 'https://imagev2.xmcdn.com/group44/M02/69/AB/wKgKkVsRFeHSZ9NvAABqVg24cIc530.jpg',
    desc: '用户xxx获得专辑《德云社》',
  },
  {
    id: 2,
    picUrl: 'https://imagev2.xmcdn.com/group44/M02/69/AB/wKgKkVsRFeHSZ9NvAABqVg24cIc530.jpg',
    desc: '用户xxx获得专辑《三体全集》',
  },
  {
    id: 3,
    picUrl: 'https://imagev2.xmcdn.com/group44/M02/69/AB/wKgKkVsRFeHSZ9NvAABqVg24cIc530.jpg',
    desc: '用户xxx获得专辑《德云社》',
  },
  {
    id: 4,
    picUrl: 'https://imagev2.xmcdn.com/group44/M02/69/AB/wKgKkVsRFeHSZ9NvAABqVg24cIc530.jpg',
    desc: '用户xxx获得专辑《三体全集》',
  },
];

const Footer = () => {
  const [winnerList, setWinnerList] = useState<any[]>([]);
  const [animate, setAnimate] = useState(false);
  const listRef = useRef<any[]>([]);
  const rafInterval = useRef<any>(null);

  useEffect(() => {
    setWinnerList(list);
    listRef.current = list;
    if (list.length >= 3) {
      rafInterval.current = requestInterval(scrollUp, 1500);
    }

    return () => {
      clearRequestInterval(rafInterval.current);
    };
  }, []);

  const scrollUp = () => {
    listRef.current.push(listRef.current[0]);
    setWinnerList(listRef.current);
    setAnimate(true);

    setTimeout(() => {
      listRef.current.shift();
      setWinnerList(listRef.current);
      setAnimate(false);
    }, 1200);
  };

  return (
    <div className={styles.listWrapper}>
      <div
        className={cx(styles.list, { [styles.animate]: animate })}
        style={{ transform: animate ? `translateY(-${px2vw(55)}vw)` : 'none' }}
      >
        {winnerList.map(({ picUrl, desc }, index) => (
          <div className={styles.item} key={index}>
            <img src={picUrl} alt="" className={styles.avatar} />
            <div className={styles.desc}>{desc}</div>
          </div>
        ))}
      </div>
    </div>
  );
};
.listWrapper {
  height: 150px;
  overflow: hidden;
}

.animate {
  transition: all 0.3s linear;
}

遇到的问题及解决方法

  1. 使用transformtranslateY替换marginTop:防止重绘导致动画不流畅
  2. setInterval的时间间隔要稍大于setTimeout,防止还未删除又加入新的数据导致重复
  3. 使用setInterval依然有数据错乱的问题,排查后发现是切换Tab时出现,原来是浏览器离开当前窗口失焦时setInterval并不能如愿的继续定时执行任务,时间误差导致了数据增多而错乱。针对该问题一开始使用setTimeout代替setInterval,但并不能解决问题。然后使用requestAnimationFrame替换setInterval,问题得到了解决
  4. 项目是移动端的,一开始是在onTransitionEnd回调中删除数据,发现在移动端息屏后不滚动了,排查后发现数组中数据没被删除,自然是transition未执行导致的,换回setTimeout则完美解决问题
@shuangmianxiaoQ shuangmianxiaoQ added the 工作相关 记录工作中遇到的问题或收获 label May 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
工作相关 记录工作中遇到的问题或收获
Projects
None yet
Development

No branches or pull requests

1 participant