mirror of
https://code.lenaisten.de/Lenaisten/advent22.git
synced 2024-11-23 00:03:07 +00:00
coordinate transformation into ThouCanvas
This commit is contained in:
parent
1ca9ca6577
commit
dde8f172dc
2 changed files with 84 additions and 32 deletions
|
@ -1,11 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<svg
|
<ThouCanvas
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 1000 1000"
|
|
||||||
preserveAspectRatio="none"
|
|
||||||
@mousedown.left="draw_start"
|
@mousedown.left="draw_start"
|
||||||
@mouseup.left="draw_finish"
|
@mouseup.left="draw_finish"
|
||||||
@contextmenu.prevent
|
|
||||||
@mousedown.right="drag_start"
|
@mousedown.right="drag_start"
|
||||||
@mouseup.right="drag_finish"
|
@mouseup.right="drag_finish"
|
||||||
@mousemove="on_mousemove"
|
@mousemove="on_mousemove"
|
||||||
|
@ -22,29 +18,18 @@
|
||||||
:focused="true"
|
:focused="true"
|
||||||
:rectangle="preview_rectangle"
|
:rectangle="preview_rectangle"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</ThouCanvas>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Vue, Options } from "vue-class-component";
|
import { Vue, Options } from "vue-class-component";
|
||||||
import { Vector2D, Rectangle } from "./rectangles";
|
import { Vector2D, Rectangle } from "./rectangles";
|
||||||
|
import ThouCanvas from "./ThouCanvas.vue";
|
||||||
import Rect from "./Rect.vue";
|
import Rect from "./Rect.vue";
|
||||||
|
|
||||||
function get_event_thous(event: MouseEvent): Vector2D {
|
|
||||||
if (event.currentTarget === null) {
|
|
||||||
return new Vector2D();
|
|
||||||
}
|
|
||||||
|
|
||||||
const target = event.currentTarget as Element;
|
|
||||||
|
|
||||||
return new Vector2D(
|
|
||||||
Math.round((event.offsetX / target.clientWidth) * 1000),
|
|
||||||
Math.round((event.offsetY / target.clientHeight) * 1000)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Options({
|
@Options({
|
||||||
components: {
|
components: {
|
||||||
|
ThouCanvas,
|
||||||
Rect,
|
Rect,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -76,14 +61,14 @@ export default class RectPad extends Vue {
|
||||||
return this.rectangles.splice(idx, 1)[0];
|
return this.rectangles.splice(idx, 1)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
private draw_start(event: MouseEvent) {
|
private draw_start(event: MouseEvent, point: Vector2D) {
|
||||||
if (this.preview_visible) {
|
if (this.preview_visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.drawing = true;
|
this.drawing = true;
|
||||||
this.preview_corner1 = get_event_thous(event);
|
this.preview_corner1 = point;
|
||||||
this.preview_corner2 = get_event_thous(event);
|
this.preview_corner2 = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
private draw_finish() {
|
private draw_finish() {
|
||||||
|
@ -100,12 +85,11 @@ export default class RectPad extends Vue {
|
||||||
this.rectangles.push(this.preview_rectangle);
|
this.rectangles.push(this.preview_rectangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private drag_start(event: MouseEvent) {
|
private drag_start(event: MouseEvent, point: Vector2D) {
|
||||||
if (this.preview_visible) {
|
if (this.preview_visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const point = get_event_thous(event);
|
|
||||||
this.drag_rect = this.pop_rectangle(point);
|
this.drag_rect = this.pop_rectangle(point);
|
||||||
|
|
||||||
if (this.drag_rect === undefined) {
|
if (this.drag_rect === undefined) {
|
||||||
|
@ -128,31 +112,29 @@ export default class RectPad extends Vue {
|
||||||
this.rectangles.push(this.preview_rectangle);
|
this.rectangles.push(this.preview_rectangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private on_mousemove(event: MouseEvent) {
|
private on_mousemove(event: MouseEvent, point: Vector2D) {
|
||||||
if (this.drawing) {
|
if (this.drawing) {
|
||||||
this.preview_corner2 = get_event_thous(event);
|
this.preview_corner2 = point;
|
||||||
} else if (this.dragging && this.drag_rect) {
|
} else if (this.dragging && this.drag_rect) {
|
||||||
const movement = get_event_thous(event).minus(this.drag_origin);
|
const movement = point.minus(this.drag_origin);
|
||||||
|
|
||||||
this.preview_corner1 = this.drag_rect.origin.plus(movement);
|
this.preview_corner1 = this.drag_rect.origin.plus(movement);
|
||||||
this.preview_corner2 = this.drag_rect.corner.plus(movement);
|
this.preview_corner2 = this.drag_rect.corner.plus(movement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private remove_rect(event: MouseEvent) {
|
private remove_rect(event: MouseEvent, point: Vector2D) {
|
||||||
if (this.preview_visible) {
|
if (this.preview_visible) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pop_rectangle(get_event_thous(event));
|
this.pop_rectangle(point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
svg {
|
* {
|
||||||
cursor: crosshair;
|
cursor: crosshair;
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
70
ui/src/components/rects/ThouCanvas.vue
Normal file
70
ui/src/components/rects/ThouCanvas.vue
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<template>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 1000 1000"
|
||||||
|
preserveAspectRatio="none"
|
||||||
|
@contextmenu.prevent
|
||||||
|
@mousedown="transform_mouse_event"
|
||||||
|
@mousemove="transform_mouse_event"
|
||||||
|
@mouseup="transform_mouse_event"
|
||||||
|
@click="transform_mouse_event"
|
||||||
|
@dblclick="transform_mouse_event"
|
||||||
|
>
|
||||||
|
<slot name="default" />
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Vue, Options } from "vue-class-component";
|
||||||
|
import { Vector2D } from "./rectangles";
|
||||||
|
|
||||||
|
function get_event_thous(event: MouseEvent): Vector2D {
|
||||||
|
if (event.currentTarget === null) {
|
||||||
|
return new Vector2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
const target = event.currentTarget as Element;
|
||||||
|
|
||||||
|
return new Vector2D(
|
||||||
|
Math.round((event.offsetX / target.clientWidth) * 1000),
|
||||||
|
Math.round((event.offsetY / target.clientHeight) * 1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mouse_event_validator(event: object, point: object): boolean {
|
||||||
|
if (!(event instanceof MouseEvent)) {
|
||||||
|
console.warn(event, "is not a MouseEvent!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(point instanceof Vector2D)) {
|
||||||
|
console.warn(point, "is not a Vector2D!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Options({
|
||||||
|
emits: {
|
||||||
|
mousedown: mouse_event_validator,
|
||||||
|
mouseup: mouse_event_validator,
|
||||||
|
mousemove: mouse_event_validator,
|
||||||
|
click: mouse_event_validator,
|
||||||
|
dblclick: mouse_event_validator,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class ThouCanvas extends Vue {
|
||||||
|
private transform_mouse_event(event: MouseEvent) {
|
||||||
|
const point = get_event_thous(event);
|
||||||
|
this.$emit(event.type, event, point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
svg {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in a new issue