64 lines
1.4 KiB
TypeScript
64 lines
1.4 KiB
TypeScript
import react from 'react';
|
|
|
|
interface ViewportProperties {
|
|
boardSize: number;
|
|
shift: { x: number; y: number };
|
|
zoom: number;
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Let's call:
|
|
* - x and y the SVG coordinates
|
|
* - X and Y the screen coordinates (pixels on screen)
|
|
*
|
|
* X0 = (x + shift.x * zoom) * zoom
|
|
* or
|
|
* x = X0 * zoom - shift.x
|
|
* id for Y
|
|
*
|
|
* To add a new shift of S screen pixels, we need to apply a zoom of S/zoom
|
|
*
|
|
* How can we zoom so that X and x stay constant ?
|
|
*
|
|
* Knowing X0, x0, zoom0, zoom1 and shift.x0,
|
|
*
|
|
*
|
|
* X0 = (x0 + shift.x0 *zoom0) * zoom0
|
|
* X1 = (x1 + shift.x1 *zoom1) * zoom1
|
|
* X0 = X1 (=X)
|
|
* x0 = x1 (=x)
|
|
* =>
|
|
* (x + shift.x1*zoom1) * zoom1 = (x + shift.x0 * zoom0) * zoom0
|
|
* =>
|
|
* (x + shift.x1*zoom1) = (x + shift.x0*zoom0) * zoom0 / zoom1
|
|
* shift.x1 = ((x + shift.x0) * zoom0 / zoom1 - x) / zoom1
|
|
*
|
|
* x = 333
|
|
* 282 => -25,5
|
|
*
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* viewBox={`${-props.shift.x} ${-props.shift.y} ${
|
|
props.boardSize / props.zoom
|
|
} ${props.boardSize / props.zoom}`}
|
|
|
|
*
|
|
*/
|
|
|
|
const Viewport: react.FC<ViewportProperties> = (props: ViewportProperties) => {
|
|
return (
|
|
<svg height={props.boardSize} width={props.boardSize}>
|
|
<g
|
|
transform={`translate(${props.shift.x}, ${props.shift.y}) scale(${props.zoom})`}
|
|
>
|
|
<circle cx='50' cy='50' r='50' />
|
|
</g>
|
|
</svg>
|
|
);
|
|
};
|
|
|
|
export default Viewport;
|