无法使 cytoscape 撤消-重做正常工作
Unable to get cytoscape undo-redo to work correctly
我正在使用 cytoscape 并尝试启动它并 运行 像这样 demo. I've converted most of the code 来进行 React,它大部分都在工作。
我遇到的问题是让 CTRL+Z 像在演示中一样工作(或任何其他键盘为此事输入)。我知道我已经正确注册了插件,因为我可以通过 undo()
和 redo()
操作以编程方式撤消和重做。
我不确定这里发生了什么,也许是 React 的问题?
在沙盒中,您可以看到按钮 undo
和 redo
工作正常,但键盘 CTRL+ Z 和 CTRL+Y 没有。为什么键盘绑定在他们的 demo 而不是我的沙盒中工作?
这是我的,
import React from "react";
import cytoscape, { Core as CSCore } from "cytoscape";
import CytoscapeComponent from "react-cytoscapejs";
import stylesheet from "./stylesheet";
import layout from "./layout";
import { initialNodes, initialEdges } from "./elements";
import { TEdge } from "./elements/edges";
import { TNode } from "./elements/nodes";
import undoRedo from "cytoscape-undo-redo";
cytoscape.use(undoRedo);
export default React.memo(() => {
// Nodes and edges are handles separately
const [nodes] = React.useState<TNode[]>(initialNodes);
const [edges] = React.useState<TEdge[]>(initialEdges);
// Cytoscape instance
const cyRef = React.useRef<CSCore | null>(null);
// UndoRedo instance
const urRef = React.useRef<any>(null);
const init = React.useCallback((cy: CSCore) => {
if (!cyRef.current) {
cyRef.current = cy;
}
urRef.current = cyRef.current.undoRedo({
isDebug: false, // Debug mode for console messages
actions: {}, // actions to be added
undoableDrag: true, // Whether dragging nodes are undoable can be a function as well
stackSizeLimit: undefined, // Size limit of undo stack, note that the size of redo stack cannot exceed size of undo stack
ready: function () {
// callback when undo-redo is ready
}
}); // Can also be set whenever wanted.
cyRef.current.on("afterUndo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkred; font-weight: bold'>Undo: </span> " +
name +
"</br>";
});
cyRef.current.on("afterRedo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkblue; font-weight: bold'>Redo: </span>" +
name +
"</br>";
});
cyRef.current.on("afterDo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkmagenta; font-weight: bold'>Do: </span>" +
name +
"</br>";
});
}, []);
return (
<div>
<div id="undoRedoList">
<span style={{ color: "darkslateblue", fontWeight: "bold" }}>Log</span>
<div
id="undos"
style={{ paddingBottom: 20, position: "absolute", left: 40, top: 40 }}
/>
</div>
<div
style={{ zIndex: 99999999, position: "absolute", right: 20, top: 20 }}
>
<button onClick={() => urRef.current.undo()}>undo</button>
<button onClick={() => urRef.current.redo()}>redo</button>
</div>
<CytoscapeComponent
elements={CytoscapeComponent.normalizeElements({
nodes: nodes,
edges: edges
})}
layout={layout}
cy={(cy) => init(cy)}
stylesheet={stylesheet}
style={{
width: "100vw",
height: "100vh"
}}
/>
</div>
);
});
您的代码唯一的错误是遗漏了实际的关键侦听器。在撤消重做演示中,crtl+z
和 crtl+y
功能实际上就是这样:
document.addEventListener("keydown", function(e) {
if (e.which === 46) {
var selecteds = cy.$(":selected");
if (selecteds.length > 0)
ur.do("remove", selecteds);
} else if (e.ctrlKey && e.target.nodeName === 'BODY')
if (e.which === 90)
ur.undo();
else if (e.which === 89)
ur.redo();
});
如果您将此粘贴到您的代码中(我在“index.tsx”中的“afterDo”事件侦听器之后尝试过它,那么您的撤消重做应该可以正常工作。我遇到了一个问题,您的代码抱怨undo-redo 被定义了两次,但在重新加载你的沙箱后自行解决。
我正在使用 cytoscape 并尝试启动它并 运行 像这样 demo. I've converted most of the code 来进行 React,它大部分都在工作。
我遇到的问题是让 CTRL+Z 像在演示中一样工作(或任何其他键盘为此事输入)。我知道我已经正确注册了插件,因为我可以通过 undo()
和 redo()
操作以编程方式撤消和重做。
我不确定这里发生了什么,也许是 React 的问题?
在沙盒中,您可以看到按钮 undo
和 redo
工作正常,但键盘 CTRL+ Z 和 CTRL+Y 没有。为什么键盘绑定在他们的 demo 而不是我的沙盒中工作?
这是我的,
import React from "react";
import cytoscape, { Core as CSCore } from "cytoscape";
import CytoscapeComponent from "react-cytoscapejs";
import stylesheet from "./stylesheet";
import layout from "./layout";
import { initialNodes, initialEdges } from "./elements";
import { TEdge } from "./elements/edges";
import { TNode } from "./elements/nodes";
import undoRedo from "cytoscape-undo-redo";
cytoscape.use(undoRedo);
export default React.memo(() => {
// Nodes and edges are handles separately
const [nodes] = React.useState<TNode[]>(initialNodes);
const [edges] = React.useState<TEdge[]>(initialEdges);
// Cytoscape instance
const cyRef = React.useRef<CSCore | null>(null);
// UndoRedo instance
const urRef = React.useRef<any>(null);
const init = React.useCallback((cy: CSCore) => {
if (!cyRef.current) {
cyRef.current = cy;
}
urRef.current = cyRef.current.undoRedo({
isDebug: false, // Debug mode for console messages
actions: {}, // actions to be added
undoableDrag: true, // Whether dragging nodes are undoable can be a function as well
stackSizeLimit: undefined, // Size limit of undo stack, note that the size of redo stack cannot exceed size of undo stack
ready: function () {
// callback when undo-redo is ready
}
}); // Can also be set whenever wanted.
cyRef.current.on("afterUndo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkred; font-weight: bold'>Undo: </span> " +
name +
"</br>";
});
cyRef.current.on("afterRedo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkblue; font-weight: bold'>Redo: </span>" +
name +
"</br>";
});
cyRef.current.on("afterDo", function (e, name) {
// @ts-ignore
document.getElementById("undos").innerHTML +=
"<span style='color: darkmagenta; font-weight: bold'>Do: </span>" +
name +
"</br>";
});
}, []);
return (
<div>
<div id="undoRedoList">
<span style={{ color: "darkslateblue", fontWeight: "bold" }}>Log</span>
<div
id="undos"
style={{ paddingBottom: 20, position: "absolute", left: 40, top: 40 }}
/>
</div>
<div
style={{ zIndex: 99999999, position: "absolute", right: 20, top: 20 }}
>
<button onClick={() => urRef.current.undo()}>undo</button>
<button onClick={() => urRef.current.redo()}>redo</button>
</div>
<CytoscapeComponent
elements={CytoscapeComponent.normalizeElements({
nodes: nodes,
edges: edges
})}
layout={layout}
cy={(cy) => init(cy)}
stylesheet={stylesheet}
style={{
width: "100vw",
height: "100vh"
}}
/>
</div>
);
});
您的代码唯一的错误是遗漏了实际的关键侦听器。在撤消重做演示中,crtl+z
和 crtl+y
功能实际上就是这样:
document.addEventListener("keydown", function(e) {
if (e.which === 46) {
var selecteds = cy.$(":selected");
if (selecteds.length > 0)
ur.do("remove", selecteds);
} else if (e.ctrlKey && e.target.nodeName === 'BODY')
if (e.which === 90)
ur.undo();
else if (e.which === 89)
ur.redo();
});
如果您将此粘贴到您的代码中(我在“index.tsx”中的“afterDo”事件侦听器之后尝试过它,那么您的撤消重做应该可以正常工作。我遇到了一个问题,您的代码抱怨undo-redo 被定义了两次,但在重新加载你的沙箱后自行解决。