Skip to content
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

Inquiry about Manual Control of Zoom and Persistent Configuration in Your Open Source Framework #274

Open
LatoAndroid opened this issue Jan 29, 2024 · 3 comments

Comments

@LatoAndroid
Copy link

Hello, and thank you very much for your open-source framework, which is very user-friendly! Currently, I have two questions I would like to ask:

Is it possible to manually control zooming, for example, having zoom in and zoom out buttons on the touchscreen, where clicking the buttons can control zoom similar to a scroll wheel? Are there any relevant APIs for this, or if not, are there other ways to achieve this? I've seen others ask this question in historical issues, but there hasn't been a resolution.

After zooming and panning, is it possible to persist the configuration? For example, saving the configuration of this zoom locally and automatically applying this zoom and pan the next time it opens.

@mauriciopoppe
Copy link
Owner

hi there, answering inline:

Is it possible to manually control zooming, for example, having zoom in and zoom out buttons on the touchscreen, where clicking the buttons can control zoom similar to a scroll wheel? Are there any relevant APIs for this, or if not, are there other ways to achieve this? I've seen others ask this question in historical issues, but there hasn't been a resolution.

I do believe it's possible, given instance = functionPlot({ }) you have access to a d3.zoom instance through instance.meta.zoomBehavior, you can do something like this:

    instance.canvas.merge(window.instance.canvas.enter)
      .call(
        instance.meta.zoomBehavior.transform,
        d3.zoomIdentity.translate(1000, 1000)
      )

That would move the graph as expected but it you zoom or pan it goes back to its original location, I'm not sure why that's happening, I think there might be a bug in this codebase.

After zooming and panning, is it possible to persist the configuration? For example, saving the configuration of this zoom locally and automatically applying this zoom and pan the next time it opens.

Yes, I believe the current zoom should be stored in instance.meta.zoomBehavior.transform (it's an instance of https://d3js.org/d3-zoom#ZoomTransform), you'd need to serialize it and apply it to the graph with the d3 API.

@LatoAndroid
Copy link
Author

LatoAndroid commented Feb 4, 2024

Thank you for your response. I have tried the methods you provided, and indeed, I can translate and scale, but whenever I use the mouse to move or scale the graph again, it resets the state.

I attempted to simulate button clicks for manual zoom events, simulate reset events, and persistently store zoom and pan events by recalculating xDomain and yDomain settings. Persistent storage of zoom and pan is effective and achieves the desired results. However, the first two conflict with mouse zoom and pan. I wonder if I should destroy the original function-plot before the operation and then redraw it with the new domain? Would this solve the problem? I noticed you added a destroy method two months ago, but I couldn't find this method in the latest npm version 1.24.0.

I am a developer from China, using ChatGPT to translate my question. If there are any translation issues, please forgive me!

reset() {
this.options.xAxis = { domain: [-10, 10] }
this.options.yAxis = { domain: [-10, 10] }
this.draw()
},

zoomIn() {
const [xStart, xEnd] = this.options.xAxis.domain;
const [yStart, yEnd] = this.options.yAxis.domain;
const xMid = (xStart + xEnd) / 2;
const yMid = (yStart + yEnd) / 2;
const xDomain = [(xStart - xMid) * 0.9 + xMid, (xEnd - xMid) * 0.9 + xMid];
const yDomain = [(yStart - yMid) * 0.9 + yMid, (yEnd - yMid) * 0.9 + yMid];
this.options.xAxis.domain = xDomain;
this.options.yAxis.domain = yDomain;
this.draw();
},

this.instance?.on('all:zoom', (event) => {
console.log('xy',this.instance?.options.xAxis.domain,this.instance?.options.yAxis.domain)
})

@mauriciopoppe
Copy link
Owner

I have tried the methods you provided, and indeed, I can translate and scale, but whenever I use the mouse to move or scale the graph again, it resets the state.

Yes this is what I saw too, what I remember doing is overriding the default zoom behavior so that zoom works across multiple instances of function plot (done with these lines) so it's unfortunately not implemented the same way as the zoom example from the d3 docs.

I wonder if I should destroy the original function-plot before the operation and then redraw it with the new domain?

Interesting idea, calling destroy removes the SVG node from the page and all listener associated with it, however I believe for every pan/zoom you'd redraw from scratch and that's a little bit expensive. It's also true that it's in the master branch and not released yet and hopefully destroy comes in 1.25 soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants