reactjs - 单击按钮时如何禁用 Edhehandles?
问题描述
我有用于添加节点和添加边的单独按钮。当我单击添加边缘按钮(名称:流)时,边缘手柄变为活动状态。使用 eh.enable() 函数。当我使用 eh.disable();eh.hide() 函数开始箭头绘制过程时,我在侧句柄选项中添加了 stop 函数,或者当箭头绘制完成时,它会关闭。
当我单击添加节点按钮时,我还想停止边缘句柄。我包含在 stopAddEdge() 函数中的 eh.disable();eh.hide() 函数没有提供此功能。按下按钮时如何禁用边缘手柄。我应该在哪里以及如何使用 eh.disable() 函数?
我的项目由两个组件组成,
MyParentComponent.jsx ;
import React, { useState, useEffect } from 'react';
import { DownCircleOutlined, SyncOutlined, MinusCircleOutlined, ArrowRightOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import 'antd/dist/antd.css';
import NewComponent from './NewComponent';
const MyParentComponent = () => {
const [nodeType, setNodeType] = useState("");
const [flowModeOn, setFlowModeOn] = useState(false);
useEffect(() => {
}, []);
const handleEvent = (e) => {
console.log(e.currentTarget);
console.log(e.currentTarget.value);
const btnValue = e.currentTarget.value;
setNodeType(btnValue);
setFlowModeOn(false);
};
const stopAddNode = (params) => {
setNodeType(params);
}
const flowModeEvent = () => {
setFlowModeOn(true);
setNodeType("");
};
const ChangeFlowMode = (params) => {
setFlowModeOn(params);
};
return (
<div>
<div style={{ textAlign: "center" }}>
<h1> My Cytoscape App </h1>
<div>
<Button value="startNode" shape="round" icon={<DownCircleOutlined />} size='large' onClick={handleEvent}>Start</Button>
<Button value="activity" shape="round" icon={<SyncOutlined />} size='large' onClick={handleEvent}>Activity</Button>
<Button value="endNode" shape="round" icon={<MinusCircleOutlined />} size='large' onClick={handleEvent}>End</Button>
<Button value="edge" shape="round" icon={<ArrowRightOutlined />} size='large' onClick={() => flowModeEvent()}>Flow</Button>
</div>
<h3>Selected Items: {nodeType}</h3>
</div>
<NewComponent nodeType={nodeType} stopAddNode={stopAddNode} flowModeOn={flowModeOn} ChangeFlowMode={ChangeFlowMode} />
</div>
);
};
export default MyParentComponent;
新组件.jsx;
import React, { useEffect, useState, useRef } from 'react';
import CytoscapeComponent from 'react-cytoscapejs';
import Cytoscape from 'cytoscape';
import edgehandles from 'cytoscape-edgehandles';
import contextMenus from 'cytoscape-context-menus';
import 'cytoscape-context-menus/cytoscape-context-menus.css';
Cytoscape.use(edgehandles);
Cytoscape.use(contextMenus);
const NewComponent = (props) => {
const cyRef = useRef();
const [controlStartState, setControlStartState] = useState(-1);
const [controlEndState, setControlEndState] = useState(-1);
const [nodeArray, setNodeArray] = useState([]);
const [currentNodeArray, setCurrentNodeArray] = useState([]);
const [ehStoped, setEhStoped] = useState(true)
let eh;
useEffect(() => {
eh = cyRef.current.edgehandles(edgehandlesOptions);
eh.disable();
});
useEffect(() => {
cyRef.current.contextMenus(contextMenuOptions);
}, []);
useEffect(() => {
console.log("props.flowModeOn: " + props.flowModeOn);
console.log("ehStoped: " + ehStoped);
if (props.flowModeOn === true && ehStoped ===true) {
if (cyRef.current) {
console.log("add edgein hemen üstü");
addEdge();
}
}
else if (props.flowModeOn === false) {
if (cyRef.current) {
console.log("stopAddEdgein hemen üstü");
stopAddEdge();
}
}
}, [props.flowModeOn]);
const edgehandlesOptions = {
preview: true, // whether to show added edges preview before releasing selection
hoverDelay: 150, // time spent hovering over a target node before it is considered selected
handleNodes: 'node', // selector/filter function for whether edges can be made from a given node
snap: false, // when enabled, the edge can be drawn by just moving close to a target node
snapThreshold: 50, // the target node must be less than or equal to this many pixels away from the cursor/finger
snapFrequency: 15, // the number of times per second (Hz) that snap checks done (lower is less expensive)
noEdgeEventsInDraw: false, // set events:no to edges during draws, prevents mouseouts on compounds
disableBrowserGestures: true, // during an edge drawing gesture, disable browser gestures such as two-finger trackpad swipe and pinch-to-zoom
handlePosition: function (node) {
return 'middle top'; // sets the position of the handle in the format of "X-AXIS Y-AXIS" such as "left top", "middle top"
},
handleInDrawMode: false, // whether to show the handle in draw mode
edgeType: function (sourceNode, targetNode) {
// can return 'flat' for flat edges between nodes or 'node' for intermediate node between them
// returning null/undefined means an edge can't be added between the two nodes
return 'flat';
},
loopAllowed: function (node) {
// for the specified node, return whether edges from itself to itself are allowed
return false;
},
nodeLoopOffset: -50, // offset for edgeType: 'node' loops
nodeParams: function (sourceNode, targetNode) {
// for edges between the specified source and target
// return element object to be passed to cy.add() for intermediary node
return {};
},
edgeParams: function (sourceNode, targetNode, i) {
// for edges between the specified source and target
// return element object to be passed to cy.add() for edge
// NB: i indicates edge index in case of edgeType: 'node'
return {};
},
ghostEdgeParams: function () {
// return element object to be passed to cy.add() for the ghost edge
// (default classes are always added for you)
return {};
},
show: function (sourceNode) {
// fired when handle is shown
},
hide: function (sourceNode) {
// fired when the handle is hidden
console.log("options içindeki HİDE fonksiyonu");
},
start: function (sourceNode) {
// fired when edgehandles interaction starts (drag on handle)
},
complete: function (sourceNode, targetNode, addedEles) {
// fired when edgehandles is done and elements are added
// console.log("addedEles: ");
// console.log(addedEles);
// cyRef.current.remove(addedEles);
},
stop: function (sourceNode) {
// fired when edgehandles interaction is stopped (either complete with added edges or incomplete)
eh.disable();
eh.hide();
console.log("options içindeki stop fonksiyonu");
props.ChangeFlowMode(false);
setEhStoped(true);
console.log("ehStoped: " + ehStoped);
},
cancel: function (sourceNode, cancelledTargets) {
// fired when edgehandles are cancelled (incomplete gesture)
console.log("options içindeki cancel fonksiyonu");
},
hoverover: function (sourceNode, targetNode) {
// fired when a target is hovered
},
hoverout: function (sourceNode, targetNode) {
// fired when a target isn't hovered anymore
},
previewon: function (sourceNode, targetNode, previewEles) {
console.log("previewon qqqqq");
// fired when preview is shown
},
previewoff: function (sourceNode, targetNode, previewEles) {
// fired when preview is hidden
console.log("previewoff");
},
drawon: function () {
// fired when draw mode enabled
console.log("drawon");
},
drawoff: function () {
// fired when draw mode disabled
console.log("options içindeki drawoff fonksiyonu");
}
};
const addEdge = () => {
console.log("1 addEdge ehStoped: " + ehStoped);
console.log("add adge enable");
// @ts-ignore
eh.enable();
setEhStoped(false);
console.log("2 addEdge ehStoped: " + ehStoped);
}
const stopAddEdge = () => {
console.log("stop Add edge fonksiyonu");
// eh.destroy();
// eh.stop();
// eh.disableDrawMode()
eh.disable();
eh.hide();
// props.ChangeFlowMode(false);
}
const elements = [
{ data: { id: "one", label: "Comp1", type: 'comp' }, position: { x: 20, y: 200 } },
// { data: { id: "two", label: "Node 2" }, position: { x: 120, y: 200 } },
// { data: { id: "three", label: "Node 3" }, position: { x: 220, y: 200 } },
// { data: { id: "four", label: "Node 4" }, position: { x: 320, y: 200 } },
// { data: { source: "one", target: "two", label: "Edge from Node1 to Node2" } }
];
const styleSheet = [
{
selector: 'node',
style: {
// 'background-color': '#000',
'color': '#1e2829',
'label': 'data(label)',
//opacity: 0.3
'width': '80',
'height': '80',
'text-wrap': 'wrap',
'text-valign': 'center',
'text-halign': 'center',
'border-width': '1px',
'border-color': 'black'
}
},
{
selector: 'node[type="comp"]',
style: {
'background-color': '#822',
}
},
{
selector: ".startNode",
style: {
backgroundColor: "green",
'border-width': '1px',
'border-color': 'black'
}
},
{
selector: ".rectangleNode",
style: {
'shape': 'rectangle',
'width': 250,
'height': 150,
'content': 'data(label)',
'text-wrap': 'wrap',
'text-valign': 'center',
'text-halign': 'center',
'border-width': '1px',
'border-color': 'black'
}
},
{
selector: ".endNode",
style: {
backgroundColor: "#aa0000",
'border-width': '1px',
'border-color': 'black'
}
},
{
selector: 'edge',
style: {
'width': 2,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier',
}
},
// some style for the Edge Handles !!!
{
selector: '.eh-handle',
style: {
// 'background-color': '#1abc9c',
'background-color': 'red',
'width': 12,
'height': 12,
'shape': 'barrel',
'overlay-opacity': 0,
'border-width': 12, // makes the handle easier to hit
'border-opacity': 0
}
},
{
selector: '.eh-hover',
css: {
'background-color': 'red'
}
},
{
selector: '.eh-source', //ok tamamlanmadan önceki kaynak görüntüsü
css: {
'border-width': 2,
'border-color': 'red'
}
},
{
selector: '.eh-target', //ok tamamlanmadan önceki hedef görüntüsü
css: {
'border-width': 2,
'background-color': 'red',
'border-color': 'red'
}
},
{
selector: '.eh-preview, .eh-ghost-edge',
css: {
'line-color': 'red',
'target-arrow-color': 'red',
'source-arrow-color': 'red'
}
},
{
selector: 'node:selected',
style:
{
'background-color': '#ffc90e',
'border-color': '#ffc90e', /*#f1c40f'*/
}
},
{
selector: 'edge:selected',
style:
{
'width': 3,
'line-color': '#ffc90e',
'target-arrow-color': '#ffc90e'
}
},
];
const contextMenuOptions = {
evtType: 'cxttap',
menuItems: [
{
id: 'add edge',
content: 'add edge',
tooltipText: 'add edge',
selector: 'node',
onClickFunction: function (event) {
console.log("label: " + event.target.data().label);
console.log("id: " + event.target.data().id);
// eh.start(cyRef.current.$('node:selected'));
},
hasTrailingDivider: true
},
{
id: 'edit',
content: 'edit',
tooltipText: 'edit with text area content',
selector: 'node, edge',
onClickFunction: function (event) {
console.log("ID: " + event.target.data().label);
},
hasTrailingDivider: true
},
{
id: 'remove',
content: 'remove',
tooltipText: 'remove',
// image: { src: "assets/remove.svg", width: 12, height: 12, x: 6, y: 4 },
selector: 'node, edge',
onClickFunction: function (event) {
console.log("ID: " + event.target.data().id);
var target = event.target || event.cyTarget;
var removed = target.remove();
console.log(removed);
},
hasTrailingDivider: true
}
],
submenuIndicator: { src: 'assets/submenu-indicator-default.svg', width: 12, height: 12 }
};
var tempCurrentNodeArray = [];
var controlStart, controlEnd = null;
const mousedownEvent = () => {
cyRef.current.nodes().unlock();
var typeIds = cyRef.current.elements('node');
for (var i = 0; i < typeIds.length; i++) {
tempCurrentNodeArray.push(typeIds[i].data().label);
}
setCurrentNodeArray(tempCurrentNodeArray);
controlStart = tempCurrentNodeArray.indexOf("startNode");
setControlStartState(controlStart);
controlEnd = tempCurrentNodeArray.indexOf("endNode");
setControlEndState(controlEnd);
}
const addNode = (evt) => {
var evtTarget = evt.target;
if (evtTarget === cyRef.current) {
if (props.nodeType == "startNode") {
if (controlStartState == -1) {
// console.log('tap on background');
cyRef.current.add({
group: 'nodes',
data: {
weight: 175,
label: props.nodeType,
},
locked: false,
classes: 'startNode',
position: {
x: evt.position.x,
y: evt.position.y
},
style: { 'shape': 'ellipse' }
});
setNodeArray([...nodeArray, props.nodeType])
props.stopAddNode("");
} else {
alert("Start Node exist");
}
} else if (props.nodeType == "endNode") {
if (controlEndState == -1) {
var evtTarget = evt.target;
if (evtTarget === cyRef.current) {
// console.log('tap on background');
cyRef.current.add({
group: 'nodes',
data: {
weight: 5,
label: props.nodeType,
},
classes: 'endNode',
position: {
x: evt.position.x,
y: evt.position.y
},
style: { 'shape': 'ellipse' }
});
setNodeArray([...nodeArray, props.nodeType])
}
props.stopAddNode("");
} else {
alert("End Node exist");
}
} else if (props.nodeType == "activity") {
var evtTarget = evt.target;
if (evtTarget === cyRef.current) {
// console.log('tap on background');
cyRef.current.add({
group: 'nodes',
data: {
weight: 5,
label: props.nodeType,
},
classes: 'rectangleNode',
position: {
x: evt.position.x,
y: evt.position.y
},
style: {
// 'shape': 'barrel',
// "width": "80",
}
});
setNodeArray([...nodeArray, props.nodeType])
}
props.stopAddNode("");
}
} else {
// console.log('tap on some element');
}
}
return (
<div>
<CytoscapeComponent
elements={elements}
// layout={layout}
cy={cy => {
cyRef.current = cy;
cyRef.current.unbind("tap"); // unbind event to prevent possible mishaps with firing too many events
cyRef.current.unbind('mousedown'); // unbind event to prevent the event to fire
cyRef.current.bind("tap", addNode);
cyRef.current.bind('mousedown', mousedownEvent);
}}
stylesheet={styleSheet}
style={{
width: "100%",
height: "83vh",
border: '1px solid black'
}}
/>
</div>
);
};
export default NewComponent;
解决方案
推荐阅读
- logstash - logstash - 如何将表示为字符串的日期转换为另一种格式作为日期数据类型
- ms-access - 我可以在子程序运行时单击 MS Access 表单上的按钮吗?
- regex - 递归正则表达式
- python - 每次循环运行时都需要生成不同的随机数
- sql - 在多对一临时表查询中选择名称与值相似且名称与其他值相似的值
- swift - 在抛出扩展错误时,如何正确识别 Swift 中使用的基本错误?
- go - 如何使用 gocenter 远程 Artifactory repo 进行本地依赖解析?
- visual-studio - 无法加载解决方案属性
- python - 从数据框中删除一些行后如何遍历数据框?
- javascript - 如何修复 $(this).val 在 jquery 的 ajax 调用中返回错误