无法使 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 的问题?

在沙盒中,您可以看到按钮 undoredo 工作正常,但键盘 CTRL+ ZCTRL+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+zcrtl+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 被定义了两次,但在重新加载你的沙箱后自行解决。