|
@@ -83,11 +83,15 @@ export interface RountangleEditorProps {
|
|
|
}
|
|
|
|
|
|
interface RountangleEditorState {
|
|
|
- translateX: number;
|
|
|
- translateY: number;
|
|
|
- zoom: number;
|
|
|
- dragging: boolean;
|
|
|
- moved: boolean;
|
|
|
+ baseWidth: number;
|
|
|
+ currentWidth: number;
|
|
|
+ baseHeight: number;
|
|
|
+ currentHeight: number;
|
|
|
+ translateX: number;
|
|
|
+ translateY: number;
|
|
|
+ zoom: number;
|
|
|
+ dragging: boolean;
|
|
|
+ moved: boolean;
|
|
|
}
|
|
|
|
|
|
export class RountangleEditor extends React.Component<RountangleEditorProps, RountangleEditorState> {
|
|
@@ -99,6 +103,10 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
this.canvasRef = React.createRef<SVGSVGElement>();
|
|
|
this.onDispatchListeners = new Set();
|
|
|
this.state = {
|
|
|
+ baseWidth: 350,
|
|
|
+ baseHeight: 350,
|
|
|
+ currentHeight: 350,
|
|
|
+ currentWidth: 350,
|
|
|
translateX: 0,
|
|
|
translateY: 0,
|
|
|
zoom: 1.0,
|
|
@@ -214,8 +222,8 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
|
|
|
if (event.movementY !== 0 ||event.movementX !== 0) {
|
|
|
this.setState({
|
|
|
- translateX: this.state.translateX - event.movementX,
|
|
|
- translateY: this.state.translateY - event.movementY,
|
|
|
+ translateX: this.state.translateX - event.movementX * this.state.zoom,
|
|
|
+ translateY: this.state.translateY - event.movementY * this.state.zoom,
|
|
|
moved: true
|
|
|
});
|
|
|
}
|
|
@@ -224,27 +232,32 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
event.preventDefault();
|
|
|
}
|
|
|
|
|
|
+ private clickToSVGPos = (x:number, y: number): DOMPoint | undefined => {
|
|
|
+ // point transformation adapted from https://stackoverflow.com/a/70595400
|
|
|
+ if (!this.canvasRef.current) return undefined;
|
|
|
+
|
|
|
+ const screenCTM = this.canvasRef.current.getScreenCTM();
|
|
|
+ if (screenCTM === null) return undefined;
|
|
|
+
|
|
|
+ const refPoint = new DOMPoint(x, y);
|
|
|
+ return refPoint.matrixTransform(screenCTM.inverse());
|
|
|
+ }
|
|
|
+
|
|
|
onPointerUp = (event: React.PointerEvent<SVGSVGElement>) => {
|
|
|
event.stopPropagation();
|
|
|
event.preventDefault();
|
|
|
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
|
|
|
|
- console.log('hier');
|
|
|
-
|
|
|
this.setState({
|
|
|
dragging: false,
|
|
|
moved: false
|
|
|
});
|
|
|
|
|
|
// add new state on left mouse button and ALT-Key pressed
|
|
|
- if (event.button === 0 && event.altKey && this.canvasRef.current) {
|
|
|
- // point transformation adapted from https://stackoverflow.com/a/70595400
|
|
|
- const refPoint = new DOMPoint(event.clientX, event.clientY);
|
|
|
- const screenCTM = this.canvasRef.current.getScreenCTM();
|
|
|
-
|
|
|
- if (screenCTM !== null) {
|
|
|
- const cursorPoint = refPoint.matrixTransform(screenCTM.inverse())
|
|
|
+ if (event.button === 0 && event.altKey) {
|
|
|
+ const cursorPoint = this.clickToSVGPos(event.clientX, event.clientY);
|
|
|
|
|
|
+ if (cursorPoint) {
|
|
|
const newRountangleName = prompt('Name', 'New Rountangle');
|
|
|
if (newRountangleName) {
|
|
|
this.dispatch({
|
|
@@ -258,20 +271,23 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
name: newRountangleName});
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
|
onWheel = (event: WheelEvent) => {
|
|
|
event.preventDefault();
|
|
|
event.stopPropagation();
|
|
|
- return;
|
|
|
- if (event.deltaY > 0) {
|
|
|
- this.setState({zoom: Math.min(this.state.zoom * 1.1, 5)})
|
|
|
- }
|
|
|
- else {
|
|
|
- this.setState({zoom: Math.min(this.state.zoom * 0.9, 5)})
|
|
|
- }
|
|
|
+ if (event.deltaY === 0) return;
|
|
|
+ if(!this.canvasRef.current) return;
|
|
|
+
|
|
|
+ const newZoom = event.deltaY > 0 ? Math.min(this.state.zoom * 1.1, 3.0) : Math.max(this.state.zoom * 0.9, 0.1);
|
|
|
+ this.setState({
|
|
|
+ zoom: newZoom,
|
|
|
+ translateX: this.state.translateX + (this.state.baseWidth * this.state.zoom - this.state.baseWidth * newZoom)/2,
|
|
|
+ translateY: this.state.translateY + (this.state.baseHeight * this.state.zoom - this.state.baseHeight * newZoom)/2,
|
|
|
+ currentWidth: this.state.baseWidth * newZoom,
|
|
|
+ currentHeight: this.state.currentHeight * newZoom
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
render() {
|
|
@@ -283,7 +299,7 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
onPointerUp={this.onPointerUp}
|
|
|
width='350px'
|
|
|
height='100%'
|
|
|
- viewBox={`${this.state.translateX} ${this.state.translateY} 350 ${this.canvasRef.current?.viewBox.baseVal.width ?? 100}`}
|
|
|
+ viewBox={`${this.state.translateX} ${this.state.translateY} ${this.state.currentWidth} ${this.state.currentHeight}`}
|
|
|
ref={this.canvasRef}
|
|
|
>
|
|
|
{
|
|
@@ -301,6 +317,7 @@ export class RountangleEditor extends React.Component<RountangleEditorProps, Rou
|
|
|
posZ={rountangle.posZ}
|
|
|
width={rountangle.width}
|
|
|
height={rountangle.height}
|
|
|
+ zoom={this.state.zoom}
|
|
|
dispatch={this.dispatch}
|
|
|
/>
|
|
|
})
|