在 React 中重新创建交互式工作区。如何迁移?

问题描述 投票:0回答:1

因此,我最初创建了一个程序,该程序允许交互式工作区,允许用户在页面上拖动并使用纯 JavaScript 移动容器内的所有内容。代码如下。

jsFiddle:https://jsfiddle.net/L05zorc7/2/

正如您在示例中看到的,如果拖动空白区域,您可以移动其中的子项。

但是我想把这个程序迁移到react组件中。我尝试这样做,但它不起作用。

import React, { useState, useEffect, useRef  } from 'react';
import './workspace.css'

const Workspace = () => {
  const workspaceRef = useRef<HTMLDivElement>(null);
  const workspaceContainerRef = useRef<HTMLDivElement>(null);


  // while the conf change, modify workspace accordingly
  const workspaceConf = new Proxy({ movementX: 0, movementY: 0, scale: 1 }, {
    set: (target, key, value) => {
      target[key as keyof typeof target]  = value;
      if (["movementX", "movementY"].includes(key as string) ) { // i.e., if movement changed
        if(workspaceRef.current){
          workspaceRef.current.style["translate"] = `${target.movementX}px ${target.movementY}px`;
        }
      }

      return true; // set handler should return true if success.
    }
  });

  // init workspace
  Object.keys(workspaceConf).forEach((key) => {
    workspaceConf[key as keyof typeof workspaceConf] = workspaceConf[key as keyof typeof workspaceConf];
  });

  // move the workspace while mouse dragging
  if(workspaceContainerRef.current){
    workspaceContainerRef.current.addEventListener("mousedown", e => {
    if (e.target !== workspaceContainerRef.current) return;
    // prevent unexpected workspace movement (e.g. while blocks being dragged)

    const move = (e:any) => { // mousemove event
      workspaceConf.movementX += e.movementX;
      workspaceConf.movementY += e.movementY;
    }

    document.body.addEventListener("mousemove", move);
    document.body.addEventListener(
      "mouseup",
      e => document.body.removeEventListener("mousemove", move), { once: true }
    );
    });}

  

  return (
    <div
    id="workspaceContainer"
      ref={workspaceContainerRef}
      style={{ width: "100vw", height: "100vh", margin: 0, padding: 0, overflow: "hidden" }}
    >
      <main
        id="workspace"
        ref={workspaceRef}
      >
        <div className="block">
          <div className="header">Sample</div>
          <div className="content">Yes</div>
        </div>
      </main>
    </div>
  );
};

export default Workspace;

在主应用程序根组件中:

import React from 'react';
import WorkspaceComponent from './components/workspace';
//import Menu from './components/menu';

function App() {
  return (
    <>
      <WorkspaceComponent/>
    </>
    
  );
}
export default App;

似乎不起作用,有人可以帮忙吗?

有人可以给我一些关于 dom 操作时组件与纯 js 的工作方式不同的课程吗?

我尝试使用 useState 来跟踪运动,并在运动状态改变时使用 useEffect 或修改 css 翻译,但失败了。所以我求助于使用与我原来的纯 CSS 代码几乎完全相同的代码。

我使用 useState 和 useEffect Hooks 的方法

import React, { useState, useEffect, useRef  } from 'react';
import './workspace.css'

const Workspace = () => {

  const workspaceRef = useRef<HTMLDivElement>(null);
  const workspaceContainerRef = useRef<HTMLDivElement>(null);
  
  const [workspaceConfState, setWorkspaceConfState] = useState({
    movementX: 0,
    movementY: 0,
  });


  useEffect(() =>{
    if(workspaceRef.current !== null ){
      workspaceRef.current.style["translate"] = `${workspaceConfState.movementX}px ${workspaceConfState.movementY}px`;
    } 
  },[workspaceConfState])

  if(workspaceContainerRef.current){
    workspaceContainerRef.current.addEventListener("mousedown", (e: any) =>{
      if(e.target !== workspaceContainerRef.current) return;
      
      const move = (event:any) => {
        setWorkspaceConfState((prevConf) => ({
          ...prevConf,
          movementX: prevConf.movementX + event.movementX,
          movementY: prevConf.movementY + event.movementY,
        }));
      };
  
      document.body.addEventListener('mousemove', move);
      document.body.addEventListener(
        "mouseup",
        e => document.body.removeEventListener("mousemove", move), { once: true }
      );
      
    })
  }
  return (
    <div
    id="workspaceContainer"
      ref={workspaceContainerRef}
      style={{ width: "100vw", height: "100vh", margin: 0, padding: 0, overflow: "hidden" }}
    >
      <main
        id="workspace"
        ref={workspaceRef}
      >
        <div className="block">
          <div className="header">Sample</div>
          <div className="content">Yes</div>
        </div>
      </main>
    </div>
  );
};

export default Workspace;


javascript reactjs css-transforms dom-manipulation
1个回答
0
投票

经过几次尝试和错误之后。事实证明,用代码通过

.style
改变变换并不是一个好主意,而是将样式状态传递到渲染函数中的
style
变量中才是答案

import React, { useState, MouseEvent } from 'react';
import './workspace.css'

interface WorkspaceConf {
    movementX: number;
    movementY: number;
}

const Workspace: React.FC = () => {
    const [workspaceConf, setWorkspaceConf] = useState<WorkspaceConf>({
        movementX: 0,
        movementY: 0
    });

    const handleMouseDown = (e: any) => {
        if (e.target !== document.getElementById('workspaceContainer')) return;

        const move = (moveEvent: any) => {
            setWorkspaceConf(workspaceConf => ({
                movementX: workspaceConf.movementX + moveEvent.movementX,
                movementY: workspaceConf.movementY + moveEvent.movementY
            }));
        };

        const handleMouseUp = () => {
            document.body.removeEventListener('mousemove', move);
        };

        document.body.addEventListener('mousemove', move);
        document.body.addEventListener('mouseup', handleMouseUp, { once: true });
    };

    return (
        <div id="workspaceContainer" onMouseDown={handleMouseDown} style={{height: '100vh'}}>
            <main
                id="workspace"
                style={{ transform: `translate(${workspaceConf.movementX}px, ${workspaceConf.movementY}px)` }}>

                <div className="block">
                    <div className="header">Sample</div>
                    <div className="content">Yes</div>
                </div>

            </main>
        </div>
    );
};

export default Workspace;

我希望这可以帮助解决同样问题的人。我也感谢该帖子的单次否决。感谢您实际访问我的页面并按下投票。我希望你一切都好,我表示感谢。

© www.soinside.com 2019 - 2024. All rights reserved.