Comments (30)
That could definitely be a good idea, I'll look into it.
from flowy.
I see what you mean, can it work the same way with the import to make things consistent?
{
"html": "",
"blockarr": [],
"blocks": [
{
"id": 1,
"parent": 0,
"data": [
{
"name": "blockid",
"value": "1"
}
],
"attr": [
{
"id": "block-id",
"class": "block-class"
}
]
}
]
}
Regarding the HTML, I think we should avoid touching any HTML if possible and only deal with json data. There could be a render callback that accept a block data then return a rendered HTML string perhaps?
from flowy.
Finally got it ! next step panning.
var zoom = 1;
...
...
flowy.zoom = function(value = 0, restore = false){
zoom += value;
if(zoom > 1 || zoom < 0.1 || restore){
zoom = 1;
}
canvas_div.style.zoom = zoom;
canvas_div.childNodes.forEach(function(node){
if (node.className.indexOf("arrowblock") < 0) {
let id = parseInt(node.querySelector(".blockid").value);
let block = blocks.filter(a => a.id == id)[0];
block.x = ((node.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(node).width) / 2) + canvas.scrollLeft);
block.y = ((node.getBoundingClientRect().top + window.scrollY) + (parseInt(window.getComputedStyle(node).height) / 2) + canvas.scrollTop);
}
});
}
...
...
var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2) + canvas_div.scrollLeft) / zoom;
var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / zoom
zoom: function(){
document.querySelector('.zoom-in').addEventListener('click', () => {
flowy.zoom(+0.1);
});
document.querySelector('.zoom-out').addEventListener('click', () => {
flowy.zoom(-0.1);
});
document.querySelector('.zoom-restore').addEventListener('click', () => {
flowy.zoom(null, true);
});
},
from flowy.
I think right now all the "actions" require interaction from the user (drag and drop). There is an import method but it would affect the whole tree. Perhaps we could extend the import and allow specifying the root of the import, would that work?
from flowy.
In addition to zooming in and out, perhaps this is more useful: module. I find this concept really useful on Botstar.com which has a comprehensive UI to build bot flows. The module allow you to group multiple steps and hide them by default.
from flowy.
NVM, I found #29 which proposes the idea of a wrapper outside of flowy to keep things simple. I think that's quite amazing to be honest. It would be nice if we do have the api to addBlock and removeBlock exposed, that would help alot.
from flowy.
NVM, I found #29 which proposes the idea of a wrapper outside of flowy to keep things simple. I think that's quite amazing to be honest. It would be nice if we do have the api to addBlock and removeBlock exposed, that would help alot.
What would "addBlock" being exposed look like? There is currently onSnap which gets triggered when a block is able to be attached to another block, which lets you to either prevent or allow the attachment. Just added a method for the block removal.
from flowy.
I think right now all the "actions" require interaction from the user (drag and drop). There is an import method but it would affect the whole tree. Perhaps we could extend the import and allow specifying the root of the import, would that work?
I see, so you suggest a way to import blocks under a certain parent? I can definitely make it so that blocks can be added programmatically (and not just individual blocks, also trees), but the problem is, how would that work? Blocks can be 100% custom - so would it be a method that accepts some HTML, an array of blocks, and the ID of the desired parent? Not sure what would be the most intuitive here.
from flowy.
Hello,
I was thinking about implementing this feature as well,
Do you think using the scale property on all dom element on the canvas, and updating the blocks array would be enough?
I mean scaling with the same ratio the blocks? As it did not succeed so far.
If you have a direction, that would be great ;)
from flowy.
Hello,
I was thinking about implementing this feature as well,
Do you think using the scale property on all dom element on the canvas, and updating the blocks array would be enough?
I mean scaling with the same ratio the blocks? As it did not succeed so far.
If you have a direction, that would be great ;)
I assume you mean using transform: scale()
? It's certainly possible, I would just need to make sure this doesn't cause any conflicts with the block positioning/dimensions.
I haven't been prioritizing this feature simply because I see a potential problem - if the canvas area is scaled up/down, how would it look/feel like dragging and dropping a differently sized block there (e.g. in the demo, from the left panel)? I'm just not sure if it would feel smooth or intuitive.
Here's an image of what I mean. It might just feel weird, but I'm open to hearing your thoughts.
from flowy.
Sure I thought about this too, maybe, I would have forced the user then to reset the zoom before dropping a new element on the canvas, but that would be out of Flowy charge I mean.
Its just that after adding a few blocks, it seems to me that it becomes quite hard to see properly the canvas and maybe rearrange the blocks if needed.
But one can also just use the browser zoom feature if needed. Anyway that feature would be awesome I think ;)
from flowy.
Sure I thought about this too, maybe, I would have forced the user then to reset the zoom before dropping a new element on the canvas, but that would be out of Flowy charge I mean.
Its just that after adding a few blocks, it seems to me that it becomes quite hard to see properly the canvas and maybe rearrange the blocks if needed.
But one can also just use the browser zoom feature if needed. Anyway that feature would be awesome I think ;)
Hmm in that case the developer could simply use transform: scale() on the canvas themselves, since either way the block snapping / dragging functionality would be off when resizing. So I don't see it being useful as a method, in that sense. Like I said, unless someone thinks of a better way to go about it - maybe it could work when resized, just that when the block is dropped into the flowchart it would resize to match automatically?
from flowy.
Yes that would be the best I think,
Once dropped the block should resize automaticlly to the new scale.
from flowy.
Hello @alyssaxuu,
I tried to implement it myself doing the following :
on zoom in I am changing the scale of every childNode of the canvas except the arrows :
document.getElementById("canvas").childNodes.forEach((node) => { if (node.className.indexOf("arrowblock") < 0) { node.style.transform = "scale(" + this.currentScale + ")"; } });
Then in flowy, I am updating the height and witdth of every block :
flowy.scale = function (scale) { blocks.forEach(function (block) { block.width = block.width * scale; block.height = block.height * scale; }); if (blocks.length > 1) { rearrangeMe(); } };
I thought that the rearrangeMe function would update then the childWidth properties, and redraw the arrows to fit the new size of the element, however it does not seem to work properly.
Do you have any hint on how to do that in a better way?
from flowy.
Hello @alyssaxuu,
I tried to implement it myself doing the following :
on zoom in I am changing the scale of every childNode of the canvas except the arrows :
document.getElementById("canvas").childNodes.forEach((node) => { if (node.className.indexOf("arrowblock") < 0) { node.style.transform = "scale(" + this.currentScale + ")"; } });
Then in flowy, I am updating the height and witdth of every block :
flowy.scale = function (scale) { blocks.forEach(function (block) { block.width = block.width * scale; block.height = block.height * scale; }); if (blocks.length > 1) { rearrangeMe(); } };
I thought that the rearrangeMe function would update then the childWidth properties, and redraw the arrows to fit the new size of the element, however it does not seem to work properly.
Do you have any hint on how to do that in a better way?
I believe the best way to go about it would be to use transform scale to resize the canvas' contents, and then immediately after replace all the array properties of the blocks (I see you updated height and width, but there's also the X and Y properties that are important which you're missing. Childwidth is used to store how much space all the children elements one next to the other (including spacing in between) takes in order to then calculate how much offset a new block being dragged in should have. I suppose if you changed all those properties and ran the rearrangeMe function it should work (haven't tested it though).
from flowy.
One solution works but arrows are !@{"#
let _this = this;
let ratio = this.scale / this.previousScale;
let canvas = document.getElementById("canvas");
//console.log(ratio);
canvas.childNodes.forEach(function(node){
let nodeX = parseFloat(window.getComputedStyle(node).left);
let nodeY = parseFloat(window.getComputedStyle(node).top);
let style = window.getComputedStyle(node);
let matrix = new WebKitCSSMatrix(style.transform);
let previousTx = (- matrix.m41 * _this.previousScale);
let previousTy = (- matrix.m42 * _this.previousScale);
let previousDx = (nodeX * _this.previousScale);
let previousDy = (nodeY * _this.previousScale);
let newTx = ((previousTx * ratio + previousDx * (ratio - 1)) / _this.scale);
let newTy = ((previousTy * ratio + previousDy * (ratio - 1)) / _this.scale);
let newX = nodeX - newTx;
let newY = nodeY - newTy;
//node.style.transform = "scale(" + _this.scale + ")";
//node.style.transform = "scale(" + _this.scale + ") translate(" + newTx + "px, " + newTy + "px)";
//node.style.transformOrigin = "0 0";
if (node.className.indexOf("arrowblock") < 0) {
let blockProperties = {
id: parseInt(node.querySelector(".blockid").value),
x: ((node.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(node).width) / 2) + canvas.scrollLeft) * _this.scale,
y: ((node.getBoundingClientRect().top + window.scrollY) + (parseInt(window.getComputedStyle(node).height) / 2) + canvas.scrollTop) * _this.scale,
width: (parseInt(window.getComputedStyle(node).width)) * _this.scale,
height: (parseInt(window.getComputedStyle(node).height)) * _this.scale
}
let blocStyles = {
top : ((node.getBoundingClientRect().top + window.scrollY) - (canvas.getBoundingClientRect().top + window.scrollY) + canvas.scrollTop) * _this.scale,
left : ((node.getBoundingClientRect().left + window.scrollX) - (canvas.getBoundingClientRect().left + window.scrollX) + canvas.scrollLeft) * _this.scale
}
console.log(blockProperties, blocStyles);
node.style.left = blocStyles.left + 'px';
node.style.top = blocStyles.top + 'px';
//node.style.transform = "scale(" + _this.scale + ")";
node.style.transform = "scale(" + _this.scale + ") translate(" + newTx + "px, " + newTy + "px)";
//node.style.transformOrigin = "0 0";
//node.style.left = newX + 'px';
//node.style.top = newY + 'px';
flowy.transformBlocks(blockProperties.id, 'x', blockProperties.x);
flowy.transformBlocks(blockProperties.id, 'y', blockProperties.y);
flowy.transformBlocks(blockProperties.id, 'width', blockProperties.width);
flowy.transformBlocks(blockProperties.id, 'height', blockProperties.height);
}else{
node.style.transform = "scale(" + _this.scale + ")";
}
/*console.log(nodeX, nodeY);
console.log(previousTx, previousTy);
console.log(previousDx, previousDy);
console.log(newTx, newTy);
console.log(newX, newY);*/
});
//flowy.scale(this.scale);
console.log(flowy.output());
I tried a CSS trick and it works but now have to changes the x,y,width,height,childwitdh and the code above don't work
canvas.style.transform = "scale(" + this.scale + ")";
canvas.style.width = "calc(" + 100 / this.scale + "% - 0px)"
canvas.style.height = "calc(" + 100 / this.scale + "% - 0px)"
canvas.style.top = (100 - (100 / this.scale)) / 2 + "%"
canvas.style.left = (100 - (100 / this.scale)) / 2 + "%"
from flowy.
@cdebattista in the approach you mentioned, when the tree becomes big and wide the indicator will not attach to the target node and will distance far away from the node you want. As zoom increases the distance will be increased more. Do you have any idea about that?
In my opinion, the indicator's left property should be tied to the canvas left property as well as so.
from flowy.
So I had planned to implement this as well, we came almost to the same implementation. My UX is a little different. I've also been going through and refactoring the code into more functions.
Still a few issues with scroll position for large workflows.
from flowy.
Hi Rob Howard
I am using flowy.js script and at the moment I failed to implement the ZOOM IN & OUT feature.
I really don't have idea how to implement. I gone through the Git comments but it does help me out any luck.
Can any one please share the piece of logic with.
Thank you so much in advance.
from flowy.
Sure:
-
I have a global var:
var zoom = 100; -
Some Zoom functions:
// ┌──────────────────────────────────────────────────────────────────── // │ Zooms the display out making the blocks smaller // └──────────────────────────────────────────────────────────────────── flowy.zoomOut = function () { let scale_factor = 5; zoom = zoom - scale_factor; flowy.setZoom(); flowy.draw(); } // ┌──────────────────────────────────────────────────────────────────── // │ Zooms the display in making the blocks larger // └──────────────────────────────────────────────────────────────────── flowy.zoomIn = function () { let scale_factor = 5; zoom = zoom + scale_factor; flowy.setZoom(); flowy.draw(); } // ┌──────────────────────────────────────────────────────────────────── // │ Sets the current zoom // └──────────────────────────────────────────────────────────────────── flowy.setZoom = function () { flowy.getZoom(); canvas_div.style.zoom = `${zoom}%`; } // ┌──────────────────────────────────────────────────────────────────── // │ Gets the current zoom // └──────────────────────────────────────────────────────────────────── flowy.getZoom = function () { if (zoom > 100) { zoom = 100; } if (zoom < 40) { zoom = 40; } return zoom; }
-
In flowy.moveBlock I recalculate the mouse position:
if (zoom < 1) { mouse_x = mouse_x * (zoom / 100); mouse_y = mouse_y * (zoom / 100); }
Also in moveBlock (but refactored into another function:
let z = zoom / 100;
// Get the center point position of the dragged block and offset with zoom
var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2) + canvas_div.scrollLeft) / z;
var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / z;
Then in my UX I have this wired up with the plus/minus keys and the UX in screen shot above. Hope that helps!
from flowy.
You might want to instead look at #105. Scroll to the bottom and @cdebattista posted a solid update. I found it this morning and have been converting my zoom behavior to use his.
from flowy.
Hi Rob Howard
Thank you so much for the response.
Can you please assist me how can I use the user interface part +/- as shown in the above image.
Do you attached the code? I cant see any out come after I apply the code you had attached.
Please assist me.
from flowy.
from flowy.
Thank you for the response.
Let me explain to you the way I added your code in my project.
step 1. Downloaded the code from the Git repo https://github.com/alyssaxuu/flowy
step 2: In the flowy.min.js file I had added the below strip
var zoom = 100; Global variable.
// ┌────────────────────────────────────────────────────────────────────
// │ Zooms the display out making the blocks smaller
// └────────────────────────────────────────────────────────────────────
flowy.zoomOut = function () {
let scale_factor = 5;
zoom = zoom - scale_factor;
flowy.setZoom();
flowy.draw();
}
// ┌────────────────────────────────────────────────────────────────────
// │ Zooms the display in making the blocks larger
// └────────────────────────────────────────────────────────────────────
flowy.zoomIn = function () {
let scale_factor = 5;
zoom = zoom + scale_factor;
flowy.setZoom();
flowy.draw();
}
// ┌────────────────────────────────────────────────────────────────────
// │ Sets the current zoom
// └────────────────────────────────────────────────────────────────────
flowy.setZoom = function () {
flowy.getZoom();
canvas_div.style.zoom = `${zoom}%`;
}
// ┌────────────────────────────────────────────────────────────────────
// │ Gets the current zoom
// └────────────────────────────────────────────────────────────────────
flowy.getZoom = function () {
if (zoom > 100) {
zoom = 100;
}
if (zoom < 40) {
zoom = 40;
}
return zoom;
}
In the **flowy.moveBlock**
if (zoom < 1) {
mouse_x = mouse_x * (zoom / 100);
mouse_y = mouse_y * (zoom / 100);
}
@NOTE: I have No Idea about the below code ( getBoundingClientRect() is returning an error method name not found ) but I have used the same method name many times in the flowy.min.js file. Indeed I added this code in the flowy.moveBlock
let z = zoom / 100;
// Get the center point position of the dragged block and offset with zoom
var xpos = ((drag.getBoundingClientRect().left + window.scrollX) + (parseInt(window.getComputedStyle(drag).width) / 2)
- canvas_div.scrollLeft) / z;
var ypos = ((drag.getBoundingClientRect().top + window.scrollY) + canvas_div.scrollTop) / z;
Step 3: In the index.html page inside the canvas div, I added the below code.
Step4: Based on Id triggered the Zoom IN/ Out functions from the main.js.
These are the steps I followed to implement but still not working.
Can you please advice on this. I really want to implement this feature and release in the production.
If possible can you please hang-up on the skype call or any alternative channel for this fix to be done.
I really apricated your time for replying me back.
Have a great day :)
from flowy.
from flowy.
Rob has its own flowy.draw()
function so you'd have to build an equivalent to make it work.
You should be able to make cdebattista's code work fairly easily though.
from flowy.
Yes, that's correct. I ended up doing a massive merge over the last few months of my changes with @cdebattista's code. I just finished it last month.
from flowy.
@robhoward I know it's a year later, but if you have it working could you link an example repo or fork? I would love to use this and it seems non-trivial from above!
from flowy.
from flowy.
Would be nice to see a PR of a zoom done tbh
from flowy.
Related Issues (20)
- Output is Not define
- Block name change
- More advanced demo? HOT 7
- Prevent junctions
- Is it possible to implement for nodes to have more than 1 parent? HOT 4
- How to use it in Vuejs ? HOT 3
- Output not getting imported HOT 2
- Can you give me a solution to use it in React js ? HOT 3
- Conditional Snapping Issue HOT 1
- Please invite me in your project. HOT 1
- Drag block item when scrolled
- Hey
- Unable to add text box in the flowchart
- Demo Site link working HOT 1
- Live demo link broken HOT 2
- [Feature request] Dark theme
- Create zoom canva preview
- Support? HOT 2
- How to split branches manually
- How to support cyclic relations between blocks in flowy
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flowy.