【问题标题】:Autoscroll when dragging react拖动时自动滚动反应
【发布时间】:2022-07-30 01:22:46
【问题描述】:

我有一个可以拖放的嵌套列表项目。但是,当我到达页面底部时,我希望它自动向下滚动。例如:

正如您从该图像中看到的那样,那里有更多项目,但它只是拒绝向下滚动。

附上我的代码

import React, { useState, useEffect, useRef } from "react";
import "../list3.css";

const List5 = () => {
  const [categories, setCategories] = useState([
    {
      value: "62bac6eddfe90a7c09873d92",
      title: "A",
      parent: null,
      level: 1,
      children: [
        {
          value: "62bac35ba30786989841809b",
          title: "B",
          parent: "62bac6eddfe90a7c09873d92",
          level: 2,
          children: [
            {
              value: "62bac5af6b6581786cb192e4",
              title: "C",
              parent: "62bac35ba30786989841809b",
              level: 3,
              children: [
                {
                  value: "62bac5af6b6581786cb1999g",
                  title: "F",
                  parent: "62bac5af6b6581786cb192e4",
                  level: 4,
                  children: [
                    {
                      value: "62bac5af6b6581786cc2000h",
                      title: "G",
                      parent: "62bac5af6b6581786cb1999g",
                      level: 5,
                    },
                    {
                      value: "62bac5af6b6581786cc2777j",
                      title: "I",
                      parent: "62bac5af6b6581786cb1999g",
                      level: 5,
                    },
                  ],
                },
              ],
            },
            {
              value: "62bac6696b6581786cb192e7",
              title: "D",
              parent: "62bac35ba30786989841809b",
              level: 3,
              children: [
                {
                  value: "62bac6696b6581786c2003A",
                  title: "H",
                  parent: "62bac6696b6581786cb192e7",
                  level: 4,
                },
              ],
            },
          ],
        },
        {
          value: "62bac6696b6581786cb1945P",
          title: "E",
          parent: "62bac6eddfe90a7c09873d92",
          level: 2,
        },
      ],
    },
  ]);
  const sortList = useRef(null);
  const currentItem = useRef(null);
  const targetItem = useRef(null);
  const isSwap = useRef(false); //to handle swapping of nodes only if they are siblings


  const handleDragStart = (e) => {
    currentItem.current = e.target;
    currentItem.current.classList.add("current");
    if (sortList.current) {
      const sortListElem = sortList.current;
      let items = sortListElem.getElementsByTagName("li");
      for (const item of items) {
        if (item !== currentItem.current) {
          item.classList.add("hint");
        }
      }
    }
  };

  const handleDragEnter = (e) => {
    targetItem.current = e.target;
    if (targetItem.current.tagName === "LI") {
      targetItem.current.classList.add("targetLi");
    }
    if (targetItem.current.className === "droppable") {
      targetItem.current.classList.add("activeChild");
    }
  };

  const handleDragLeave = (e) => {
    if (e.target !== targetItem.current) {
      e.target.classList.remove("activeChild");
      e.target.classList.remove("targetLi");
    }
  };

  // DRAG END - REMOVE ALL HIGHLIGHTS
  const handleDragEnd = (e) => {
    const sortListElem = sortList.current;
    let items = sortListElem.getElementsByTagName("li");
    for (const it of items) {
      it.classList.remove("hint");
      it.classList.remove("active");
    }
    currentItem.current.classList.remove("current");
    targetItem.current.classList.remove("activeChild");
    targetItem.current.classList.remove("targetLi");
  };

  const handleDragOver = (e) => {
    e.preventDefault();
  };

  const handleDrop = (e) => {
    e.preventDefault();
    if (!targetItem.current.getAttribute("nodeid")) {
      return;
    }

  };

  useEffect(() => {
    document.addEventListener("dragstart", handleDragStart);
    document.addEventListener("dragenter", handleDragEnter);
    document.addEventListener("dragleave", handleDragLeave);
    document.addEventListener("dragend", handleDragEnd);
    document.addEventListener("dragover", handleDragOver);
    document.addEventListener("dragover", handleDragOver);
    document.addEventListener("drop", handleDrop);

    return () => {
      document.removeEventListener("dragstart", handleDragStart);
      document.removeEventListener("dragenter", handleDragEnter);
      document.removeEventListener("dragleave", handleDragLeave);
      document.removeEventListener("dragend", handleDragEnd);
      document.removeEventListener("dragover", handleDragOver);
      document.addEventListener("drop", handleDrop);
    };
  }, []);

  return (
    <div className="container">
      <ul id="sortList" className="slist" ref={sortList}>
        <ListItems categories={categories}></ListItems>
      </ul>
    </div>
  );
};

function ListItems({ categories }) {
  if (!categories) {
    return <h2>Loading...</h2>;
  }
  return (
    <div className="nested-div">
      {categories &&
        categories.map((category, index) => {
          return (
            <div key={index} className="nested-item">
              <li
                nodeid={category.value}
                draggable={category.parent ? true : false}
              >
                {" "}
                {category.title}
              </li>
              <div className="droppable" nodeid={category.value}></div>
              {category.children && (
                <ListItems categories={category.children} />
              )}
            </div>
          );
        })}
    </div>
  );
}

export default List5;

我尝试的是通过将溢出 css 属性的 css 属性添加到主 div。附上我的css

/* (A) LIST STYLES */
.slist {
  list-style: none;
  padding: 0;
  margin: 0;
}
.slist li {
  margin: 10px;
  padding: 15px;
  border: 1px solid #dfdfdf;
  background: #f5f5f5;
}

/* (B) DRAG-AND-DROP HINT */
.slist li.hint {
  border: 1px solid #ffc49a;
  background: #feffb4;
}
.slist li.active {
  border: 1px solid #ffa5a5;
  background: #ffe7e7;
}
.slist li.targetLi {
  background-color: red;
}
.nested-div {
  margin-top: 1em;
}

.nested-item {
  margin-left: 2em;
}

.slist li.current {
  border: 5px solid aqua;
}

.droppable {
  padding: 5px;
}

.droppable.activeChild {
  border-bottom: 1px solid red;
}

.container {
  overflow: scroll;
}

#sortList {
  overflow: visible;
}

非常感谢所提供的所有帮助。

非常感谢。

【问题讨论】:

    标签: javascript css reactjs drag-and-drop overflow


    【解决方案1】:

    在拖动对象时尝试使用此方法进行底部滚动:

    • 查找您正在拖动的对象的 y 轴值
    • 获取窗口底部 y 轴(您可能需要通过获取窗口顶部 Y + 窗口高度来计算此值)
    • 检查对象的 y 轴是否与窗口底部的 Y 轴相差 200(可以在您希望滚动开始时更改),并按您选择的像素数滚动窗口/父元素。 (这可能会在拖动元素的 useEffect 中,当它被拖动时检查元素是否到达您设置的底部点,如果是,则滚动)

    这只是滚动到底部,这可能是更难的部分。你必须做类似的事情才能向上滚动。

    【讨论】:

      猜你喜欢
      • 2016-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 2023-03-16
      • 1970-01-01
      相关资源
      最近更新 更多