mathsvgslidercoordinateszooming# Calculating svg transform values for zooming-in and dragging an image

### Calculus

### Scheming

### Crunching

### Mopping Up

We have available svg area of 1300x620px, wanting to vertically and horizontally center 300x500px image with ability to zoom in and out, with default zoom level of 3.

We start by calculating the image size by dividing the available area size by the default zoom level, ending with 433x207px image, which we wrap in a `<g>`

tag with `transform="translate(0,0) scale(3)"`

and the result looks like that:

The question is, how to calculate the proper x and y here `translate(x, y) scale(3.5)`

so that the image is still centered.

The second question is, how to calculate minimum and maximum x,y coordinates of the image.

The idea is to implement sliders for the x and y axis and 2 buttons to zoom-in / zoom-out which will modify the `transform()`

values for the slider functionality, but we need to know the min-max values on each axis as well as to properly transform the image so that it keeps to be centered no matter of the current transform applied.

Solution

I'll list the principal calculation in pseudocode first, and than demonstrate its functioning graphically. Finally we'll sum up things.

So according to your description we start with:

```
// SVG viewport size
set viewWidth = 1300px;
set viewHeight = 620px;
// initial scale factor and according image size
set initScale = 3;
set imgWidth = viewWidth / initScale;
set imgHeight = viewHeight / initScale;
```

To adjust the position of your image we have to apply a factor to the image size:

```
set newScale = 3.5;
set adjustFactor = 0.5 * (1 - newScale / initScale);
scale(newScale);
translate(adjustFactor * imgWidth, adjustFactor * imgHeight);
```

When zooming in, e.g. with `newScale = 3.5`

, we get (rounded):

```
scale(3.5);
translate(-36, -17);
```

Now lets zoom out (rounded again):

```
scale(2.5);
translate(36, 17);
```

That behavior is to be expected. To center we have to left-/up-shift when zooming in, and right-/down-shift when zooming out.

**Fig.1** illustrates what is done here. We have a grayisch square within a `10 x 6 px`

"canvas". We have a frame of the same size, which remains unchanged and shall always show the square centered, no matter how we scale the canvas (together with the square). Now, when scaling up the canvas without an adjusting translation, the canvas slips out of the frame, and we see only the top-left corner of the square. Using the above formula and the resulting adjustment factor of `0.5`

we push the canvas back by `-5px`

along the x-axis and `-3px`

along the y-axis till the square is centered within the frame again.

**Fig.1** Adjusting the position of an image slippen out of the frame by scaling, to be shown centered in that frame.

The coordinates are correspondingly:

```
minX = adjustFactor * imgWidth;
maxX = minX + imgWidth * (newScale / initScale);
minY = adjustFactor * imgHeight;
maxY = minY + imgHeight * (newScale / initScale);
```

The max-Values are basically min-Value plus newly scaled width resp. height.

Note that

```
maxX = minX + imgWidth * (newScale / initScale)
= adjustFactor * imgWidth + imgWidth * (newScale / initScale)
= imgWidth * (adjustFactor + newScale / initScale)
= imgWidth * (0.5 * (1 - newScale / initScale) + newScale / initScale)
= imgWidth * (0.5 - 0.5 * newScale / initScale + newScale / initScale)
= imgWidth * (0.5 + 0.5 * newScale / initScale)
= imgWidth * 0.5 * (1 + newScale / initScale)
```

Remembers of something, doesn't it?

```
adjustFactor = 0.5 * (1 - newScale / initScale);
```

It's just a plus instead of a minus. The difference between `0.5 * (1 + newScale / initScale)`

and `0.5 * (1 - newScale / initScale)`

is `newScale / initScale`

. We may want to consider this, as divisions are costly concerning performance. The less the better.

So in total we get:

```
set a = 0.5 * (1 - newScale / initScale); // our former "adjustFactor"
set b = a + newScale / initScale;
set minX = a * imgWidth;
set maxX = b * imgWidth;
set minY = a * imgHeight;
set maxY = b * imgHeight;
scale(newScale);
translate(minX, minY); // looks sane, right?
```

You can use the min/max-values for scrolling checks. It might make sense to turn off scrolling for an axis when the respective min-value is `>= 0`

.

- How to find the interception coordinates of a moving target in 3D space?
- Decompose a vector in rotational components
- How is the starting point chosen in GNU Scientific Library multiroot finder?
- PYTORCH - TENSORS issue - Mat1 and mat2 shapes cannot be multiplied (8x10 and 8x8)
- Float number division with 3 decimal places
- Calculate lowest common indivisible number in JavaScript
- MATLAB: Using ODE solvers?
- Runge-Kutta (RK4) integration for game physics
- Fast algorithm for multiple line integrals over 2D discrete function
- how to display math equations (integration, algebraic, etc) in UILabel
- Integrating a Bayes probability distribution
- Evaluate limit of integral in Mathematica
- JavaScript % (modulo) gives a negative result for negative numbers
- Truncate a floating point number without rounding up
- Resize div with drag handle when rotated
- Calculation of intersections between line segments
- Identity in sympy
- solution for basic integration of mathematical functions
- Why does my Runge-Kutta implementation oscillate to 0?
- Integration via trapezoidal sums in MATLAB
- stieltjes integration in Python
- C++ nan keeps coming up with integration
- integration 3 dimensions by generalizing the method of rectangle
- How to solve integral in Matlab having an upper limit set as the sine function?
- Trouble using Sympy to integrate
- Obtaining the constant that makes the integral equal to zero in Matlab
- Determining the event location on an oscillatory signal
- Code wont produce the value of a definite integral in MATLAB
- Triple Integration: ValueError: negative number cannot be raised to a fractional power
- Scipy tplquad syntax