因此,我最初创建了一个程序,该程序允许交互式工作区,允许用户在页面上拖动并使用纯 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;
经过几次尝试和错误之后。事实证明,用代码通过
.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;
我希望这可以帮助解决同样问题的人。我也感谢该帖子的单次否决。感谢您实际访问我的页面并按下投票。我希望你一切都好,我表示感谢。