【问题标题】:Continuous looping scroll连续循环滚动
【发布时间】:2019-10-23 05:25:52
【问题描述】:

我在 react 中使用 https://github.com/locomotivemtl/locomotive-scroll 插件来启用平滑滚动。我试图让它做一个连续滚动,所以无论你向哪个方向滚动,它都会循环,通过在状态数组中添加和删除项目来改变顺序。

这可行,但会导致一些超级闪烁。

几个演示是

https://codesandbox.io/s/heuristic-resonance-0ybkl

https://codesandbox.io/s/young-wind-ozeeq

https://codesandbox.io/s/patient-darkness-6gxj1

任何帮助将不胜感激

代码如下

import React from "react";
import ReactDOM from "react-dom";
import LocomotiveScroll from "locomotive-scroll";
import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      limit: null,
      items: [
        "https://www.fillmurray.com/640/460",
        "https://www.fillmurray.com/g/640/560",
        "https://www.fillmurray.com/640/760",
        "https://www.fillmurray.com/g/640/860",
        "https://www.fillmurray.com/640/160",
        "https://www.fillmurray.com/g/640/260",
        "https://www.fillmurray.com/g/640/360",
        "https://www.fillmurray.com/g/640/460"
      ]
    };
  }
  componentDidMount() {
    const target = document.querySelector("#view");
    const scroll = new LocomotiveScroll({
      el: target,
      smooth: true,
      smoothMobile: true,
      getDirection: true
    });

    scroll.on("scroll", obj => {
      console.log(obj.scroll.y);
      if (this.state.limit !== null) {
        if (obj.direction === "up") {
          var current = this.state.items;

          var first = current.shift();
          current.push(first);
          this.setState(
            {
              items: current
            },
            () => {
              scroll.update();
            }
          );
        }

        if (obj.direction === "down") {
          current = this.state.items;
          var last = current.pop();
          current.unshift(last);
          this.setState(
            {
              items: current
            },
            () => {
              scroll.update();
            }
          );
        }
      } else {
        var halfway = obj.limit / 2;
        scroll.scrollTo(target, halfway);
        this.setState({
          limit: obj.limit
        });
      }
    });

    scroll.scrollTo(target, 1);
  }
  render() {
    return (
      <div className="App">
        <div id="view">
          <div className="left">
            {this.state.items.map(item => {
              return <img src={item} alt="" />;
            })}
          </div>
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

【问题讨论】:

  • 你能把你的代码也放在问题本身吗?这将使它对未来的访问者更有价值。

标签: javascript reactjs scroll


【解决方案1】:

闪烁的原因是整个组件在滚动事件上重新渲染,而您的元素没有键。

this.setState(
    {
        items: current
    },
    () => {
        scroll.update();
    }
);

在上面的代码中,您设置了滚动事件的状态,这将导致列表的完全重新呈现。您需要在 map 函数中的元素上设置 key

Key docs

Code Sandbox

import React from "react";
import ReactDOM from "react-dom";
import LocomotiveScroll from "locomotive-scroll";
import "./styles.css";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      limit: null,
      items: [
        "https://www.fillmurray.com/640/460",
        "https://www.fillmurray.com/g/640/560",
        "https://www.fillmurray.com/640/760",
        "https://www.fillmurray.com/g/640/860",
        "https://www.fillmurray.com/640/160",
        "https://www.fillmurray.com/g/640/260",
        "https://www.fillmurray.com/g/640/360",
        "https://www.fillmurray.com/g/640/460"
      ]
    };
  }
  componentDidMount() {
    const target = document.querySelector("#view");
    const scroll = new LocomotiveScroll({
      el: target,
      smooth: true,
      smoothMobile: true,
      getDirection: true
    });

    scroll.on("scroll", ({ limit, direction }) => {
      if (this.state.limit !== null) {
        if (direction === "up") {
          console.log("up");
          var current = this.state.items;
          var last = current.pop();
          current.unshift(last);
          this.setState(
            {
              items: current
            },
            () => {
              scroll.update();
            }
          );
        }

        if (direction === "down") {
          current = this.state.items;
          var first = current.shift();
          current.push(first);
          this.setState(
            {
              items: current
            },
            () => {
              scroll.update();
            }
          );
        }
      } else {
        var halfway = limit / 2;
        scroll.scrollTo(target, halfway);
        this.setState({
          limit
        });
      }
    });

    scroll.scrollTo(target, 1);
  }
  render() {
    return (
      <div className="App">
        <div id="view">
          <div className="left">
            {this.state.items.map((item, idx) => {
              return <img key={`${item}${idx}`} src={item} alt="" />;
            })}
          </div>
        </div>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

【讨论】:

  • 好像还在闪烁,是不是应该不设置状态?
  • 我没有在我链接的代码框中看到闪烁。我想知道浏览器是否有差异?滚动似乎正在疯狂地快速移动,我认为这只是滚动逻辑。
  • 我在 chrome 中。怎么解决?
猜你喜欢
  • 2011-10-07
  • 2018-07-09
  • 2015-07-17
  • 2016-08-30
  • 2013-06-04
  • 2021-04-30
  • 1970-01-01
  • 1970-01-01
  • 2016-09-18
相关资源
最近更新 更多