Open Granduca opened 2 years ago
Only by javascript https://github.com/jerosoler/Drawflow/issues/112
The UX https://github.com/jerosoler/Drawflow/issues/50 not implemented.
I solved the multiselect/move problem with this little simple but very powerful library Selectables. Watch the DEMO. alt+click and drag for select/deselect double click in an empty space for clear selection
WoW! 👍
@Granduca thank you for pointing me in the direction of the Selectables library. I haven't started playing with it yet, but I did notice in your demo that when I select a few items, including the "Save log file" element, and start moving the elements around, that particular element doesn't move. Is that just me, or is there something in particular I should be keeping in mind when I start working with the Selectables library that perhaps you omitted for your demo?
@Granduca thank you for pointing me in the direction of the Selectables library. I haven't started playing with it yet, but I did notice in your demo that when I select a few items, including the "Save log file" element, and start moving the elements around, that particular element doesn't move. Is that just me, or is there something in particular I should be keeping in mind when I start working with the Selectables library that perhaps you omitted for your demo?
There is no problem with the Selectables library here. I made my demo very quickly and maybe a little carelessly. Because of this, similar problems can be observed. However, in a personal project, everything works fine for me! I'm sure you can easily figure out how to implement this functionality for your project.
Thank you for your help, I have now fully implemented a multi-select, multi-drag feature, that also allows you to hold the ctrl key to add or remove individual nodes. It works very well. There is one problem that I have yet to be able to resolve though, at zoom 1.0, everything works well. As soon as I start zooming in our out, the Selectables library struggles. Your demo suffers from the same. Any ideas on how I can get around it?
To fix this problem you need to override the static method in the Selectables library:
const editor = new Drawflow("...");
//Add `editor.zoom` to that function:
let cross = function (a, b) {
let aTop = offset(a).top, aLeft = offset(a).left, bTop = offset(b).top, bLeft = offset(b).left;
return !(((aTop + a.offsetHeight) < (bTop)) || (aTop > (bTop + b.offsetHeight * editor.zoom)) || ((aLeft + a.offsetWidth) < bLeft) || (aLeft > (bLeft + b.offsetWidth * editor.zoom)));
};
If you want to leave the library itself unchanged, then you can do in your code like this:
var dr = new Selectables({
//your prefs
})
let rb = function () {
return document.getElementById('s-rectBox');
};
let cross = function (a, b) {
let aTop = offset(a).top, aLeft = offset(a).left, bTop = offset(b).top, bLeft = offset(b).left;
return !(((aTop + a.offsetHeight) < (bTop)) || (aTop > (bTop + b.offsetHeight * editor.zoom)) || ((aLeft + a.offsetWidth) < bLeft) || (aLeft > (bLeft + b.offsetWidth * editor.zoom)));
};
let offset = function (el) {
let r = el.getBoundingClientRect();
return {top: r.top + document.body.scrollTop, left: r.left + document.body.scrollLeft}
};
dr.select = function (e) {
let a = rb();
if (!a) {
return;
}
delete(dr.ipos);
document.body.classList.remove('s-noselect');
document.body.removeEventListener('mousemove', dr.rectDraw);
window.removeEventListener('mouseup', dr.select);
let s = dr.options.selectedClass;
dr.foreach(dr.items, function (el) {
if (cross(a, el) === true) {
if (el.classList.contains(s)) {
el.classList.remove(s);
dr.options.onDeselect && dr.options.onDeselect(el);
} else {
el.classList.add(s);
dr.options.onSelect && dr.options.onSelect(el);
}
}
setTimeout(function () {
el.removeEventListener('click', dr.suspend, true);
}, 100);
});
a.parentNode.removeChild(a);
dr.options.stop && dr.options.stop(e);
}
@Granduca this is fantastic. I implemented the first option and it works like a charm. Thanks again for your guidance!
Multiple Select with ShiftKey native.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.css"/>
<script src="https://cdn.jsdelivr.net/gh/jerosoler/Drawflow/dist/drawflow.min.js"></script>
</head>
<div id="drawflow"></div>
<style>
#drawflow {
position: relative;
text-align:initial;
width: 100%;
height: 800px;
border: 1px solid red;
}
.drawflow svg {
z-index: 1;
}
.drawflow .drawflow-node.GROUP {
width: 500px;
height: 500px;
z-index: 0;
}
.drawflow .drawflow-node.GROUP.hover-drop {
background: pink;
}
</style>
<script>
var id = document.getElementById("drawflow");
const editor = new Drawflow(id);
editor.start();
editor.addNode('aaa', 1, 1, 600, 200, 'aaa', {}, `aaa` );
editor.addNode('bbb', 1, 1, 850, 200, 'bbb', {}, `bbb` );
editor.addNode('ccc', 1, 1, 850, 370, 'ccc', {}, `ccc`);
editor.addConnection(1, 2, 'output_1', 'input_1');
editor.addConnection(2, 3, 'output_1', 'input_1');
const nodesSelected = [];
editor.on("clickEnd", (e) => {
const shiftKey = e.shiftKey;
if(shiftKey) {
if(editor.node_selected !== null) {
const nodeId = editor.node_selected.id.slice(5);
const indexSelected = nodesSelected.indexOf(nodeId);
if(indexSelected === -1) {
nodesSelected.push(nodeId);
} else {
nodesSelected.splice(indexSelected,1);
const nodeUnselected = document.getElementById(`node-${nodeId}`);
nodeUnselected.classList.remove("selected");
}
} else {
nodesSelected.forEach(eleN => {
const node = document.getElementById(`node-${eleN}`);
node.classList.remove("selected");
});
nodesSelected.splice(0, nodesSelected.length);
}
nodesSelected.forEach(eleN => {
const node = document.getElementById(`node-${eleN}`);
node.classList.add("selected");
});
} else {
nodesSelected.forEach(eleN => {
const node = document.getElementById(`node-${eleN}`);
node.classList.remove("selected");
});
nodesSelected.splice(0, nodesSelected.length);
}
});
let last_x = 0;
let last_y = 0;
editor.on("mouseMove", ({x,y}) => {
if(editor.node_selected && editor.drag) {
editor.node_selected.classList.add("selected");
const nodeId = editor.node_selected.id.slice(5);
const indexSelected = nodesSelected.indexOf(nodeId);
if(indexSelected === -1) {
nodesSelected.push(nodeId);
}
nodesSelected.forEach(eleN => {
if(eleN != editor.node_selected.id.slice(5)) {
const node = document.getElementById(`node-${eleN}`);
var xnew = (last_x - x) * editor.precanvas.clientWidth / (editor.precanvas.clientWidth * editor.zoom);
var ynew = (last_y - y) * editor.precanvas.clientHeight / (editor.precanvas.clientHeight * editor.zoom);
node.style.top = (node.offsetTop - ynew) + "px";
node.style.left = (node.offsetLeft - xnew) + "px";
editor.drawflow.drawflow[editor.module].data[eleN].pos_x = (node.offsetLeft - xnew);
editor.drawflow.drawflow[editor.module].data[eleN].pos_y = (node.offsetTop - ynew);
editor.updateConnectionNodes(`node-${eleN}`);
}
});
}
last_x = x;
last_y = y;
})
</script>
</body>
</html>
@jerosoler Hello, i'm using your library in my angular project and it's very useful. Isn't the multiselect + drag packaged in the library already? If it's not will it be in the future? Thank you.
Hello, @koufounak It would not be included in this library. I am preparing a new library. But it is still in development.
@jerosoler Wait, what? New library? Tell me more! :-D
Is it possible to move several nodes (with a specific tag or id) at the same time?