admin管理员组文章数量:1418306
I want to build a Flow Builder for my clients to give them an entirely way to construct data inside my dashboard editor, inspired with manychat flow builder
I have a simple app which has UI editor I have a need to build a workflow tool, allowing people to drag nodes onto a canvas, connect outlets of nodes to inputs of other nodes... Zoom.etc.
I am inspired with a manychat editor which u can see it here /
More how it look in manychat
Looking for suggestions on how to get started... Curious if there are frameworks/libraries anyone would remend making this easier or just confirmation that I should just start whipping out Javascript to handle the drags/drops/line drawing/etc.
I have found this library named rete.js
So far this is what I have.
js
var numSocket = new Rete.Socket('Number value');
var VueNumControl = {
props: ['readonly', 'emitter', 'ikey', 'getData', 'putData'],
template: '<input type="number" :readonly="readonly" :value="value" @input="change($event)" @dblclick.stop="" @pointermove.stop=""/>',
data() {
return {
value: 0,
}
},
methods: {
change(e){
this.value = +e.target.value;
this.update();
},
update() {
if (this.ikey)
this.putData(this.ikey, this.value)
this.emitter.trigger('process');
}
},
mounted() {
this.value = this.getData(this.ikey);
}
}
class NumControl extends Rete.Control {
constructor(emitter, key, readonly) {
super(key);
thisponent = VueNumControl;
this.props = { emitter, ikey: key, readonly };
}
setValue(val) {
this.vueContext.value = val;
}
}
class NumComponent extends Rete.Component {
constructor(){
super("Number");
}
builder(node) {
var out1 = new Rete.Output('num', "Number", numSocket);
return node.addControl(new NumControl(this.editor, 'num')).addOutput(out1);
}
worker(node, inputs, outputs) {
outputs['num'] = node.data.num;
}
}
class AddComponent extends Rete.Component {
constructor(){
super("Add");
}
builder(node) {
var inp1 = new Rete.Input('num1',"Number", numSocket);
var inp2 = new Rete.Input('num2', "Number2", numSocket);
var out = new Rete.Output('num', "Number", numSocket);
inp1.addControl(new NumControl(this.editor, 'num1'))
inp2.addControl(new NumControl(this.editor, 'num2'))
return node
.addInput(inp1)
.addInput(inp2)
.addControl(new NumControl(this.editor, 'preview', true))
.addOutput(out);
}
worker(node, inputs, outputs) {
var n1 = inputs['num1'].length?inputs['num1'][0]:node.data.num1;
var n2 = inputs['num2'].length?inputs['num2'][0]:node.data.num2;
var sum = n1 + n2;
this.editor.nodes.find(n => n.id == node.id).controls.get('preview').setValue(sum);
outputs['num'] = sum;
}
}
(async () => {
var container = document.querySelector('#rete');
var ponents = [new NumComponent(), new AddComponent()];
var editor = new Rete.NodeEditor('[email protected]', container);
editor.use(ConnectionPlugin.default);
editor.use(VueRenderPlugin.default);
editor.use(ContextMenuPlugin.default);
editor.use(AreaPlugin);
editor.use(CommentPlugin.default);
editor.use(HistoryPlugin);
editor.use(ConnectionMasteryPlugin.default);
var engine = new Rete.Engine('[email protected]');
ponents.map(c => {
editor.register(c);
engine.register(c);
});
var n1 = await ponents[0].createNode({num: 2});
var n2 = await ponents[0].createNode({num: 0});
var add = await ponents[1].createNode();
n1.position = [80, 200];
n2.position = [80, 400];
add.position = [500, 240];
editor.addNode(n1);
editor.addNode(n2);
editor.addNode(add);
editor.connect(n1.outputs.get('num'), add.inputs.get('num1'));
editor.connect(n2.outputs.get('num'), add.inputs.get('num2'));
editor.on('process nodecreated noderemoved connectioncreated connectionremoved', async () => {
console.log('process');
await engine.abort();
await engine.process(editor.toJSON());
});
editor.view.resize();
AreaPlugin.zoomAt(editor);
editor.trigger('process');
})();
Here is HTML
<div id="rete"></div>
<a target="_blank" href=""><img style="position: absolute; top: 0; right: 0; border: 0;" src="" alt="Fork me on GitHub" data-canonical-src=".png"></a>
Here is codepen code pen demo
Unfortunately, this does not give what I want,
What do I need to do to get what I need? or is there any library which I can try?
I want to build a Flow Builder for my clients to give them an entirely way to construct data inside my dashboard editor, inspired with manychat flow builder
I have a simple app which has UI editor I have a need to build a workflow tool, allowing people to drag nodes onto a canvas, connect outlets of nodes to inputs of other nodes... Zoom.etc.
I am inspired with a manychat editor which u can see it here https://manychat./
More how it look in manychat
Looking for suggestions on how to get started... Curious if there are frameworks/libraries anyone would remend making this easier or just confirmation that I should just start whipping out Javascript to handle the drags/drops/line drawing/etc.
I have found this library named rete.js
So far this is what I have.
js
var numSocket = new Rete.Socket('Number value');
var VueNumControl = {
props: ['readonly', 'emitter', 'ikey', 'getData', 'putData'],
template: '<input type="number" :readonly="readonly" :value="value" @input="change($event)" @dblclick.stop="" @pointermove.stop=""/>',
data() {
return {
value: 0,
}
},
methods: {
change(e){
this.value = +e.target.value;
this.update();
},
update() {
if (this.ikey)
this.putData(this.ikey, this.value)
this.emitter.trigger('process');
}
},
mounted() {
this.value = this.getData(this.ikey);
}
}
class NumControl extends Rete.Control {
constructor(emitter, key, readonly) {
super(key);
this.ponent = VueNumControl;
this.props = { emitter, ikey: key, readonly };
}
setValue(val) {
this.vueContext.value = val;
}
}
class NumComponent extends Rete.Component {
constructor(){
super("Number");
}
builder(node) {
var out1 = new Rete.Output('num', "Number", numSocket);
return node.addControl(new NumControl(this.editor, 'num')).addOutput(out1);
}
worker(node, inputs, outputs) {
outputs['num'] = node.data.num;
}
}
class AddComponent extends Rete.Component {
constructor(){
super("Add");
}
builder(node) {
var inp1 = new Rete.Input('num1',"Number", numSocket);
var inp2 = new Rete.Input('num2', "Number2", numSocket);
var out = new Rete.Output('num', "Number", numSocket);
inp1.addControl(new NumControl(this.editor, 'num1'))
inp2.addControl(new NumControl(this.editor, 'num2'))
return node
.addInput(inp1)
.addInput(inp2)
.addControl(new NumControl(this.editor, 'preview', true))
.addOutput(out);
}
worker(node, inputs, outputs) {
var n1 = inputs['num1'].length?inputs['num1'][0]:node.data.num1;
var n2 = inputs['num2'].length?inputs['num2'][0]:node.data.num2;
var sum = n1 + n2;
this.editor.nodes.find(n => n.id == node.id).controls.get('preview').setValue(sum);
outputs['num'] = sum;
}
}
(async () => {
var container = document.querySelector('#rete');
var ponents = [new NumComponent(), new AddComponent()];
var editor = new Rete.NodeEditor('[email protected]', container);
editor.use(ConnectionPlugin.default);
editor.use(VueRenderPlugin.default);
editor.use(ContextMenuPlugin.default);
editor.use(AreaPlugin);
editor.use(CommentPlugin.default);
editor.use(HistoryPlugin);
editor.use(ConnectionMasteryPlugin.default);
var engine = new Rete.Engine('[email protected]');
ponents.map(c => {
editor.register(c);
engine.register(c);
});
var n1 = await ponents[0].createNode({num: 2});
var n2 = await ponents[0].createNode({num: 0});
var add = await ponents[1].createNode();
n1.position = [80, 200];
n2.position = [80, 400];
add.position = [500, 240];
editor.addNode(n1);
editor.addNode(n2);
editor.addNode(add);
editor.connect(n1.outputs.get('num'), add.inputs.get('num1'));
editor.connect(n2.outputs.get('num'), add.inputs.get('num2'));
editor.on('process nodecreated noderemoved connectioncreated connectionremoved', async () => {
console.log('process');
await engine.abort();
await engine.process(editor.toJSON());
});
editor.view.resize();
AreaPlugin.zoomAt(editor);
editor.trigger('process');
})();
Here is HTML
<div id="rete"></div>
<a target="_blank" href="https://github./retejs/rete"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent./652c5b9acfaddf3a9c326fa6bde407b87f7be0f4/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws./github/ribbons/forkme_right_orange_ff7600.png"></a>
Here is codepen code pen demo
Unfortunately, this does not give what I want,
What do I need to do to get what I need? or is there any library which I can try?
Share Improve this question asked Jun 12, 2019 at 11:45 The Dead ManThe Dead Man 5,57633 gold badges125 silver badges226 bronze badges 7- Please describe in detail what you need. Rete.js provides a visual editor and engine, and you can create programming data-flow schemes for different processing methods – Ni55aN Commented Jun 12, 2019 at 17:48
- Hi, I want the same as the manychat builder does when connecting elements – The Dead Man Commented Jun 12, 2019 at 17:59
- what exactly? I haven't see any playground for manychat – Ni55aN Commented Jun 13, 2019 at 9:57
- Hi @user9964622, have you some cool resources for this? I'm looking for a similar thing – Cordo van Saviour Commented Sep 23, 2019 at 10:57
- 1 @CordovanSaviour I manage using plumb js github./jsplumb/jsplumb for connectivity – The Dead Man Commented Sep 23, 2019 at 11:05
1 Answer
Reset to default 2ManyChat uses PIXI.js to build the flow builder. I found out myself when reading through their bundle codes (who the hell read piled codes, yes I did :))
Seems like they use React-PIXI - a react wrapper of PIXI.js (I'm not sure about this)
From that observation I can build my own one using VueJS (in a project of my previous pany)
You should take a look at PIXI. Some important notices for you (all I collect from Manychat's idea and during my implementation):
- Remember to double your canvas width and height property, then use CSS to style your canvas with half size of the width and height. Doing this will make your canvas has high quality. Example:
<canvas width="400" height="600" style="width: 200px; height: 300px;"></canvas>
- One of the hard part is making the arrow to connect between 2 blocks, I read piled code of Manychat and found out, not remember exactly what it is but basically they split the arrow to 2 symmetric parts and start drawing them to their center, you can read it and find out yourself (if you lucky, LOL), it's in
main.js
- Another hard part is reflecting Vue data into canvas, canvas is not DOM, any change you'll have to re-draw the whole canvas, so do this carefully
- don't render multiple images, it's cost
- for Object snapping, you can learn from idea of KonvaJS (they have an example for that)
- For pin, pan and Zoom you can search on Google examples using PIXI.
- When clicking an block, the camera will smoothly focus that block with some animations (zoom in then out, centralize the block with the camera,...), seem Many chat uses
tween.js
- Beware of puting data in event listeners (mousemove, mousedrag,...), it can easily destroy performance
本文标签: javascriptFlow Builder (visual editor)Stack Overflow
版权声明:本文标题:javascript - Flow Builder (visual editor) - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745278313a2651304.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论