2023-01-17 18:25:56 +00:00
|
|
|
<template>
|
|
|
|
<svg
|
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
viewBox="0 0 1000 1000"
|
|
|
|
preserveAspectRatio="none"
|
2023-01-17 22:42:21 +00:00
|
|
|
@mousedown.left="draw_start"
|
|
|
|
@mouseup.left="draw_finish"
|
2023-01-17 23:34:42 +00:00
|
|
|
@contextmenu.prevent
|
|
|
|
@mousedown.right="drag_start"
|
|
|
|
@mouseup.right="drag_finish"
|
|
|
|
@mousemove="on_mousemove"
|
2023-01-17 23:56:07 +00:00
|
|
|
@click.middle="remove_rect"
|
2023-01-17 23:34:42 +00:00
|
|
|
@dblclick.left="remove_rect"
|
2023-01-17 18:25:56 +00:00
|
|
|
>
|
|
|
|
<Rect
|
2023-01-19 00:27:38 +00:00
|
|
|
v-for="(rect, index) in _rectangles"
|
2023-01-17 18:25:56 +00:00
|
|
|
:key="'rect' + index"
|
|
|
|
:rectangle="rect"
|
|
|
|
/>
|
2023-01-17 23:34:42 +00:00
|
|
|
<Rect
|
|
|
|
v-if="preview_visible"
|
2023-01-17 23:58:46 +00:00
|
|
|
:focused="true"
|
2023-01-17 23:34:42 +00:00
|
|
|
:rectangle="preview_rectangle"
|
|
|
|
/>
|
2023-01-17 18:25:56 +00:00
|
|
|
</svg>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import { Vue, Options } from "vue-class-component";
|
|
|
|
import { Vector2D, Rectangle } from "./rectangles";
|
|
|
|
import Rect from "./Rect.vue";
|
|
|
|
|
|
|
|
function get_event_thous(event: MouseEvent): Vector2D {
|
|
|
|
if (event.currentTarget === null) {
|
|
|
|
return new Vector2D();
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:50:25 +00:00
|
|
|
const target = event.currentTarget as Element;
|
2023-01-17 18:25:56 +00:00
|
|
|
|
|
|
|
return new Vector2D(
|
|
|
|
Math.round((event.offsetX / target.clientWidth) * 1000),
|
|
|
|
Math.round((event.offsetY / target.clientHeight) * 1000)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Options({
|
|
|
|
components: {
|
|
|
|
Rect,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
export default class RectPad extends Vue {
|
2023-01-18 00:04:43 +00:00
|
|
|
private readonly min_rect_area = 300;
|
2023-01-17 23:34:42 +00:00
|
|
|
private drawing = false;
|
|
|
|
private preview_corner1 = new Vector2D();
|
|
|
|
private preview_corner2 = new Vector2D();
|
|
|
|
private dragging = false;
|
2023-01-17 23:42:07 +00:00
|
|
|
private drag_rect?: Rectangle;
|
2023-01-17 23:34:42 +00:00
|
|
|
private drag_origin = new Vector2D();
|
2023-01-19 00:27:38 +00:00
|
|
|
private _rectangles: Rectangle[] = [];
|
2023-01-17 18:25:56 +00:00
|
|
|
|
2023-01-17 23:34:42 +00:00
|
|
|
private get preview_visible(): boolean {
|
|
|
|
return this.drawing || this.dragging;
|
|
|
|
}
|
|
|
|
|
|
|
|
private get preview_rectangle(): Rectangle {
|
|
|
|
return new Rectangle(
|
|
|
|
this.preview_corner1,
|
|
|
|
this.preview_corner2
|
|
|
|
).normalize();
|
|
|
|
}
|
|
|
|
|
2023-01-19 00:27:38 +00:00
|
|
|
public get rectangles(): Rectangle[] {
|
|
|
|
return this._rectangles; //.map((rect) => rect.normalize());
|
|
|
|
}
|
|
|
|
|
|
|
|
public set rectangles(rects: Rectangle[]) {
|
|
|
|
this._rectangles = rects; //.map((rect) => rect.normalize());
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
private pop_rectangle(point: Vector2D): Rectangle | undefined {
|
2023-01-19 00:27:38 +00:00
|
|
|
const idx = this._rectangles.findIndex((rect) => rect.contains(point));
|
2023-01-17 23:42:07 +00:00
|
|
|
|
|
|
|
if (idx === -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-19 00:27:38 +00:00
|
|
|
return this._rectangles.splice(idx, 1)[0];
|
2023-01-17 23:34:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 22:42:21 +00:00
|
|
|
private draw_start(event: MouseEvent) {
|
2023-01-17 23:34:42 +00:00
|
|
|
if (this.preview_visible) {
|
2023-01-17 22:15:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:34:42 +00:00
|
|
|
this.drawing = true;
|
|
|
|
this.preview_corner1 = get_event_thous(event);
|
|
|
|
this.preview_corner2 = get_event_thous(event);
|
2023-01-17 18:25:56 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 23:34:42 +00:00
|
|
|
private draw_finish() {
|
|
|
|
if (!this.drawing) {
|
2023-01-17 22:42:21 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:34:42 +00:00
|
|
|
this.drawing = false;
|
2023-01-17 18:25:56 +00:00
|
|
|
|
2023-01-17 23:50:25 +00:00
|
|
|
if (this.preview_rectangle.area < this.min_rect_area) {
|
|
|
|
return;
|
2023-01-17 18:25:56 +00:00
|
|
|
}
|
2023-01-17 23:50:25 +00:00
|
|
|
|
2023-01-19 00:27:38 +00:00
|
|
|
this._rectangles.push(this.preview_rectangle);
|
2023-01-17 18:25:56 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 23:34:42 +00:00
|
|
|
private drag_start(event: MouseEvent) {
|
|
|
|
if (this.preview_visible) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:50:25 +00:00
|
|
|
const point = get_event_thous(event);
|
2023-01-17 23:42:07 +00:00
|
|
|
this.drag_rect = this.pop_rectangle(point);
|
2023-01-17 23:34:42 +00:00
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
if (this.drag_rect === undefined) {
|
2023-01-17 23:34:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.dragging = true;
|
|
|
|
this.drag_origin = point;
|
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
this.preview_corner1 = this.drag_rect.origin;
|
|
|
|
this.preview_corner2 = this.drag_rect.corner;
|
2023-01-17 23:34:42 +00:00
|
|
|
}
|
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
private drag_finish() {
|
2023-01-17 23:34:42 +00:00
|
|
|
if (!this.dragging) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.dragging = false;
|
2023-01-19 00:27:38 +00:00
|
|
|
this._rectangles.push(this.preview_rectangle);
|
2023-01-17 23:34:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private on_mousemove(event: MouseEvent) {
|
|
|
|
if (this.drawing) {
|
2023-01-17 23:50:25 +00:00
|
|
|
this.preview_corner2 = get_event_thous(event);
|
2023-01-17 23:42:07 +00:00
|
|
|
} else if (this.dragging && this.drag_rect) {
|
2023-01-17 23:50:25 +00:00
|
|
|
const movement = get_event_thous(event).minus(this.drag_origin);
|
2023-01-17 23:34:42 +00:00
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
this.preview_corner1 = this.drag_rect.origin.plus(movement);
|
|
|
|
this.preview_corner2 = this.drag_rect.corner.plus(movement);
|
2023-01-17 23:34:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private remove_rect(event: MouseEvent) {
|
2023-01-19 00:27:21 +00:00
|
|
|
if (this.preview_visible) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-17 23:42:07 +00:00
|
|
|
this.pop_rectangle(get_event_thous(event));
|
2023-01-17 18:25:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
svg {
|
|
|
|
cursor: crosshair;
|
2023-01-18 22:45:12 +00:00
|
|
|
height: 100%;
|
|
|
|
width: 100%;
|
2023-01-17 18:25:56 +00:00
|
|
|
}
|
|
|
|
</style>
|