当用户点击它时,将可拖动的 div 带到 React.js 的前面

lil*_*ing 10 javascript css z-index draggable reactjs

我想在单击或拖动它时将一个可拖动的框带到前面。

我事先不知道此类框的最大数量,因为我有一个按钮,当用户单击该按钮时,该按钮会创建一个新的可拖动框。

无论有多少个框,按钮都应该始终位于顶部,因此它的 z-index 应始终是最大的。

所以这些是我的问题:

  1. 当用户单击某个框时,如何将其置于最前面。
  2. 如何让按钮保持在前面。

我是 ReactJS 的新手。

这是我目前在 MyComponent.js 中拥有的内容

import React, { useState }  from 'react';
import Draggable from 'react-draggable';

function MyComponent() {
    const [currZIndex, setZIndex] = useState(0);

    const bringForward = () => {
        setZIndex(currZIndex + 1);
    }

    return (
        <Draggable onMouseDown={bringForward}>
            <div className="mydiv" style={{zIndex: currZIndex}}></div>
        </Draggable>
    );
}
Run Code Online (Sandbox Code Playgroud)

我当前实现的问题是每个组件只知道自己的 z-index,但不知道当前最高的 z-index 是多少。每当我单击任何 div 时,z 索引就会增加,因此这使得 z 索引不必要地变大。

如果 div1 的 z-index 为 6,div2 的 z-index 为 2,我必须单击 div2 5 次,使其 z-index 变为 7,才能将 div2 置于前面。

我还没有想出如何处理按钮的 z-index 的想法。

Fyr 这就是我在 App.js 中的内容

import React, { useState } from 'react';
import MyComponent from './MyComponent';

function App() {
  const [componentList, setComponentList] = useState([]);

  function addNewComponent() {
    setComponentList(componentList.concat(<MyComponent key={componentList.length} />));
  }

  return (
    <div>
      <button onClick={addNewComponent}>New Component</button>
      {componentList}
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

Sal*_*n A 7

如果您只关心被拖动的项目的“堆栈级别”而不是其他项目,则仅在该项目上设置 z 索引 \xe2\x80\x94 任何 z 索引 \xe2\x80\x94 。没有 z-index(或具有相同 z-index)的项目的堆栈级别由其源顺序 ( specs ) 决定。所以你会:

\n
    \n
  • 在容器上创建堆叠上下文(例如通过添加position: relative; z-index: 1
  • \n
  • 在拖动开始时设置z-index: 1元素并在拖动结束时将其删除
  • \n
  • 设置z-index: 2在按钮上
  • \n
\n

堆栈闪电战

\n
\n

如果您确实关心所有项目的堆栈级别,那么绝对无需担心“不必要的大”值 \xe2\x80\x94 CSS 中没有限制。您只需要跟踪当前最高的 z-index:

\n

堆栈闪电战

\n
\n

如果您确实想限制 z-index 的值,那么您需要:

\n
    \n
  • 识别正在拖动的项目
  • \n
  • 从 z-index 高于该项目的所有项目中减去 1
  • \n
  • 为该项目分配最大值
  • \n
\n

堆栈闪电战

\n


man*_*055 6

让我们一一解决这些问题。首先是简单的:

1. 如何让按钮无论有多少个盒子都保持在顶部,因此它z-index始终应该是最大的?

实现这一要求的一种方法是:

  1. <button>和包装MyComponent在单独的div.
  2. 提供 的z-index高于<button> divMyComponent div
  3. position: relativebuttoncontainer( div)和MyComponentcontainer( )上使用div来建立单独的堆叠上下文。您可以参考这篇文章来了解更多相关信息。

按照上述步骤,button无论您创建多少个可拖动元素, 都将始终位于顶部。

return (
    <div>
      <div style={{ position: "relative", zIndex: 2 }}>
        <button onClick={addNewComponent}>New Component</button>
      </div>
      <div style={{ position: "relative", zIndex: 1 }}>
        {componentList.map((item) => (
          <MyComponent
            key={item.id}
            zIndex={item.zIndex}
            bringToFront={() => bringToFront(item.id)}
          />
        ))}
      </div>
    </div>
  );
Run Code Online (Sandbox Code Playgroud)

button2.当用户单击/拖动可拖动框时,如何将其带到顶部(但在后面)?

现在,要解决这个问题可以有多种方法。我使用的一种方法是使用视图中创建的可拖动组件的数量。让我将其分解为步骤来详细说明。

  1. 在父组件中维护一个状态,该状态将跟踪可拖动组件的总数。

    const [componentList, setComponentList] = useState([]);
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使<MyComponent />(逻辑上每个可拖动的框)接受两个道具;zIndexbringToFront

  3. 单击后,在对象中button添加一个新条目(即 setState):componentList

     {
        id: prevComponentList.length, 
        zIndex: 0,
      }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 现在,当单击或拖动特定组件(mousedown触发事件)时,bringToFront将调用id该框的回调函数。现在,映射componentList并找到id当前拖动/单击元素的 ,并将其值增加到elsez-index中可用元素的最大长度(如果 与元素不匹配)将当前 z-index 减少 1。prevComponentListidid

    const [componentList, setComponentList] = useState([]);
    
    Run Code Online (Sandbox Code Playgroud)

编辑(h/t Salman A):

上述解决方案适用于您当前的情况。然而,正如您所注意到的,z-index 是无条件递减的。为了解决这个问题,我们可以在 zIndex 上设置一个条件,即它应该被限制为 0 或应该介于 0 之间1total number of draggable boxes in view第二个看起来更理想)。为了实现上述目标,您需要编辑bringToFront如下所示的函数:

 {
    id: prevComponentList.length, 
    zIndex: 0,
  }
Run Code Online (Sandbox Code Playgroud)

演示实施

建议和进一步阅读:

  1. z-index 不起作用的 4 个原因
  2. 使用 Styled 组件进行样式设置