Rework SVGRect and Doors

This commit is contained in:
Jörn-Michael Miehe 2023-09-22 19:02:51 +00:00
parent de5fff311c
commit cfea9b051f
3 changed files with 89 additions and 76 deletions

View file

@ -1,5 +1,10 @@
<template>
<SVGRect :rectangle="door.position" @click.left="on_click" />
<SVGRect
style="cursor: pointer"
:rectangle="door.position"
@click.left="on_click"
>
</SVGRect>
</template>
<script lang="ts">
@ -32,9 +37,3 @@ export default class extends Vue {
}
}
</script>
<style scoped>
rect {
cursor: pointer;
}
</style>

View file

@ -1,5 +1,22 @@
<template>
<foreignObject
:x="Math.round(parent_aspect_ratio * rectangle.left)"
:y="rectangle.top"
:width="Math.round(parent_aspect_ratio * rectangle.width)"
:height="rectangle.height"
:style="`transform: scaleX(${1 / parent_aspect_ratio})`"
>
<div
v-if="variant !== undefined"
xmlns="http://www.w3.org/1999/xhtml"
class="px-4 is-flex is-align-items-center is-justify-content-center is-size-1 has-text-weight-bold"
>
<slot name="default" />
</div>
</foreignObject>
<rect
ref="rect"
v-bind="$attrs"
:class="variant !== undefined ? variant : ''"
:x="rectangle.left"
:y="rectangle.top"
@ -12,7 +29,13 @@
import { Rectangle } from "@/lib/rectangle";
import { Options, Vue } from "vue-class-component";
type RectColor = "primary" | "link" | "info" | "success" | "warning" | "danger";
type BulmaVariant =
| "primary"
| "link"
| "info"
| "success"
| "warning"
| "danger";
@Options({
props: {
@ -24,14 +47,56 @@ type RectColor = "primary" | "link" | "info" | "success" | "warning" | "danger";
},
})
export default class extends Vue {
public variant?: RectColor;
public variant?: BulmaVariant;
public rectangle!: Rectangle;
private refreshKey = 0;
declare $refs: {
rect: unknown;
};
private refresh() {
window.setTimeout(() => {
// don't loop endlessly
if (this.refreshKey < 10000) {
this.refreshKey++;
}
}, 100);
}
public get parent_aspect_ratio(): number {
this.refreshKey; // read it just to force recompute on change
if (
!(this.$refs.rect instanceof SVGRectElement) ||
this.$refs.rect.parentElement === null
) {
this.refresh();
return 1;
}
const parent = this.$refs.rect.parentElement;
const result = parent.clientWidth / parent.clientHeight;
// force recompute for suspicious results
if (result === 0 || result === Infinity) {
this.refresh();
return 1;
}
return result;
}
}
</script>
<style lang="scss" scoped>
@import "@/bulma-vars";
foreignObject > div {
height: inherit;
}
rect {
fill: transparent;
fill-opacity: 0.3;

View file

@ -1,35 +1,24 @@
<template>
<SVGRect
style="cursor: text"
:rectangle="door.position"
:variant="editing ? 'success' : 'primary'"
/>
<foreignObject
:x="Math.round(parent_aspect_ratio * door.position.left)"
:y="door.position.top"
:width="Math.round(parent_aspect_ratio * door.position.width)"
:height="door.position.height"
:style="`transform: scaleX(${1 / parent_aspect_ratio})`"
@click.left="on_click"
>
<div
xmlns="http://www.w3.org/1999/xhtml"
class="px-4 is-flex is-align-items-center is-justify-content-center"
@click.left="on_click"
>
<input
v-if="editing"
v-model="day_str"
ref="day_input"
class="input is-large"
type="number"
:min="MIN_DAY"
placeholder="Tag"
@keydown="on_keydown"
/>
<div v-else class="is-size-1 has-text-weight-bold has-text-danger">
{{ door.day > 0 ? door.day : "*" }}
</div>
<input
v-if="editing"
v-model="day_str"
ref="day_input"
class="input is-large"
type="number"
:min="MIN_DAY"
placeholder="Tag"
@keydown="on_keydown"
/>
<div v-else class="has-text-danger">
{{ door.day > 0 ? door.day : "*" }}
</div>
</foreignObject>
</SVGRect>
</template>
<script lang="ts">
@ -52,48 +41,18 @@ export default class extends Vue {
public day_str = "";
public editing = false;
private refreshKey = 0;
declare $refs: {
day_input: HTMLInputElement | unknown;
};
private refresh() {
window.setTimeout(() => {
// don't loop endlessly
if (this.refreshKey < 10000) {
this.refreshKey++;
}
}, 100);
}
public get parent_aspect_ratio(): number {
this.refreshKey; // read it just to force recompute on change
if (!(this.$el instanceof Text) || this.$el.parentElement === null) {
this.refresh();
return 1;
}
const parent = this.$el.parentElement;
const result = parent.clientWidth / parent.clientHeight;
// force recompute for suspicious results
if (result === 0 || result === Infinity) {
this.refresh();
return 1;
}
return result;
}
private toggle_editing() {
this.day_str = String(this.door.day);
this.editing = !this.editing;
}
public on_click(event: MouseEvent) {
if (event.target === null || !(event.target instanceof HTMLDivElement)) {
if (event.target === null || !(event.target instanceof SVGRectElement)) {
return;
}
@ -131,13 +90,3 @@ export default class extends Vue {
}
}
</script>
<style lang="scss" scoped>
foreignObject {
cursor: text;
> div {
height: inherit;
}
}
</style>