-
-
Notifications
You must be signed in to change notification settings - Fork 969
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Zoom in/out #22
Comments
That could definitely be a good idea, I'll look into it. |
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. |
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. |
I see what you mean, can it work the same way with the import to make things consistent?
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? |
Hello, |
I assume you mean using 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. |
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? |
Yes that would be the best I think, |
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 : Then in flowy, I am updating the height and witdth of every block :
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). |
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 + "%" |
@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. |
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. |
Sure:
Also in moveBlock (but refactored into another function:
Then in my UX I have this wired up with the plus/minus keys and the UX in screen shot above. Hope that helps! |
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. |
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. |
Hi Ravi,
You need to add the UX to handle this. For example:
<div id="zoom">Zoom <span>100</span>% <a href="#" id="zoom_out"><i
class="far fa-search-minus" aria-hidden="true"></i></a> | <a href="#"
id="zoom_in"><i class="far fa-search-plus" aria-hidden="true"></i></a></div>
Along with the appropriate event handlers:
//
┌────────────────────────────────────────────────────────────────────
// │ Updates the percentage of zoom we're at
//
└────────────────────────────────────────────────────────────────────
function updateZoomDisplay() {
let zoom = flowy.getZoom();
document.querySelector("#zoom span").innerText = zoom;
}
//
┌────────────────────────────────────────────────────────────────────
// │ Zoom out
//
└────────────────────────────────────────────────────────────────────
document.getElementById("zoom_out").addEventListener("click",
function (e) {
flowy.zoomOut();
updateZoomDisplay();
});
//
┌────────────────────────────────────────────────────────────────────
// │ Zoom in
//
└────────────────────────────────────────────────────────────────────
document.getElementById("zoom_in").addEventListener("click",
function (e) {
flowy.zoomIn();
updateZoomDisplay();
});
…On Mon, Apr 5, 2021 at 3:30 AM Ravi Koppula ***@***.***> wrote:
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.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#22 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHHFGC7Q7Q5ZNSGB32KURTTHFYJLANCNFSM4J3DNMRA>
.
|
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
@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
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 :) |
Hi Ravi,
Sorry, I'm not sure what to tell you. You've got all the pieces, but it's
not trivial. Most of what I've done (as well as others) isn't really tied
in with the flowy library any longer. They are additions. I can only
provide you the pieces I used.
Rob
…On Mon, Apr 5, 2021 at 9:54 PM Ravi Koppula ***@***.***> wrote:
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
<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.
Zoom 100% <#m_1333813811625634984_> | <#m_1333813811625634984_>
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 :)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#22 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHHFGG5V4L46PABHP2EW5LTHJZVZANCNFSM4J3DNMRA>
.
|
Rob has its own You should be able to make cdebattista's code work fairly easily though. |
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. |
@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! |
Hey Drew we’ve since modified it to the point that it’s super customized to
our use case. I can probably provide some snippets that show what we’re
doing but it’s gotten crazy complicated.
On Tue, Feb 28, 2023 at 12:09 PM Drew Wetherington ***@***.***> wrote:
@robhoward <https://github.com/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!
—
Reply to this email directly, view it on GitHub
<#22 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAHHFGCIYGM3WNFDV4HZF4LWZZLRNANCNFSM4J3DNMRA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Founder
*DailyStory Marketing Automation | *Superhero powers for your marketing
team*
learn more at dailystory.com <http://dailystory.com> | +1-833-914-1105
* cape not included
|
Would be nice to see a PR of a zoom done tbh |
It would be great and very useful if for larger diagrams we could zoom in/out. This would make it easier to visualize larger flows.
The text was updated successfully, but these errors were encountered: