visx
visx copied to clipboard
Applying visx-zoom to a XYChart - issue moving graph outside grid and on top of axises
Discussed in https://github.com/airbnb/visx/discussions/1243
Originally posted by nilsgoksor June 18, 2021 I'm struggling to find examples of visx-zoom other than the official one: https://airbnb.io/visx/zoom-i and right now I'm totally stuck on one issue.
When I apply it to my XYChart it's not behaving the desired way. I obviously don't want to be able to move the graph on top of the axises or even outside the graph (as in the picture) but no matter what I try I can't seem to get both the XYChart-axises and a movable graph at the same time.
Do you guys have any example I can follow or any idea what might cause the issue?
@nilsgoksor Do you have a gist of your xychart component that I can take a look? 👀
Sure, here you go https://codesandbox.io/embed/charming-cookies-ik7ps?fontsize=14&hidenavigation=1&theme=dark 🤙
@nilsgoksor sorry for the late reply. Interesting problem.
I believe this is normal if you directly apply transform={zoom.toString()}
here:
<Group>
<LineSeries
transform={zoom.toString()} // <-- here
data={reScaledData}
{...otherProps}
{...accessors}
/>
</Group>
Because that just takes whichever how much x and y movements you dragged and apply to the path svg (chart) with transform: matrix(...variables)
or transform: translate(x, y)
attributes.
This is a viz from Mike Bostock himself, same issue. https://observablehq.com/@d3/zoomable-bar-chart
So transform={zoom.toString()}
is causing the problem for what you want to achieve with charts and axis. If you want to keep it simple with zoom.toString(), I would expand and axis and grid to cover the full svg space:
<Group>
<Axis left hideZero orientation="right" />
<Axis top hideZero orientation="bottom" />
<Grid top left width={width + margin} height={height + margin} />
</Group>
If what you want to achieve is something like this: Line chart with zoom
Then you need to remove transform={zoom.toString()}
, and do more math in getScaledData() function, calculate the new extent with x and y movement after dragging and remap your values onto the chart with new extent, something like this:
let extent = [[0, width], [0, height]];
function getScaledData(transformMatrix) {
// ... get xMovement and yMovement after multiplying scaleX, scaleY
// set extent
extent = [[extent[0][0] + xMovement, extent[0][1] + xMovement], [extent[1][0] + yMovement, extent[1][1] + yMovement]];
//
const xScale = scaleLinear({
domain: [Math.min(...XVals), Math.max(...XVals)],
range: [extent[0][0], extent[0][1]]
});
const yScale = scaleLinear({
domain: [Math.min(...YVals), Math.max(...YVals)],
range: [extent[1][0], extent[1][1]]
});