You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.9 KiB
Vue

<template>
<div class="window-areas-layer">
<section
v-for="slice in slices"
:key="`${slice.area.id}-${slice.segmentIndex}-${slice.renderLeft}`"
class="window-area"
:style="{
left: `${slice.renderLeft}px`,
top: `${slice.renderTop}px`,
width: `${slice.renderWidth}px`,
height: `${slice.renderHeight}px`,
}"
>
<div
class="window-area-inner"
:style="{
width: `${slice.area.width}px`,
height: `${slice.area.height}px`,
transform: `translateX(${-slice.clipOffset}px)`,
}"
>
<div v-if="slice.area.isClockWindow" class="clock-window">
<span
class="clock-text"
:style="{
fontSize: `${slice.area.dynamicTextStyle.fontSize}px`,
color: slice.area.dynamicTextStyle.color,
fontWeight: slice.area.dynamicTextStyle.fontWeight,
}"
>
{{ nowTime }}
</span>
</div>
<template v-else>
<div class="window-no-region">
<span
class="window-no-text"
:class="{ circle: slice.area.windowNumberCircle }"
:style="resolveWindowNumberStyle(slice)"
>
{{ slice.area.windowNumber }}
</span>
</div>
<div class="window-text-region">
<div
class="window-text-line"
:style="{
fontSize: `${slice.area.staticTextStyle.fontSize}px`,
color: slice.area.staticTextStyle.color,
fontWeight: slice.area.staticTextStyle.fontWeight,
}"
>
{{ slice.area.staticText }}
</div>
<div
class="window-text-line"
:style="{
fontSize: `${slice.area.dynamicTextStyle.fontSize}px`,
color: slice.area.dynamicTextStyle.color,
fontWeight: slice.area.dynamicTextStyle.fontWeight,
}"
>
{{ slice.area.dynamicText }}
</div>
</div>
</template>
</div>
</section>
</div>
</template>
<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from "vue";
import type { ChildWindowAreaConfig } from "../models/config";
import type { WindowAreaSlice } from "../services/windowAreaSliceService";
defineProps<{
slices: WindowAreaSlice[];
}>();
const nowMs = ref(Date.now());
let timerId: number | null = null;
const nowTime = computed(() => {
const date = new Date(nowMs.value);
const hh = String(date.getHours()).padStart(2, "0");
const mm = String(date.getMinutes()).padStart(2, "0");
return `${hh}:${mm}`;
});
function resolveWindowNumberStyle(slice: WindowAreaSlice) {
const base = {
fontSize: `${slice.area.windowNumberStyle.fontSize}px`,
color: slice.area.windowNumberStyle.color,
fontWeight: slice.area.windowNumberStyle.fontWeight,
};
if (!slice.area.windowNumberCircle) {
return base;
}
return {
...base,
...resolveCircleStyle(slice.area),
};
}
function resolveCircleStyle(area: ChildWindowAreaConfig) {
const style = area.windowNumberCircleStyle ?? { size: 36, borderWidth: 1, borderRadius: 18 };
const size = Number.isFinite(style.size) && style.size > 0 ? Math.floor(style.size) : 36;
const borderWidth =
Number.isFinite(style.borderWidth) && style.borderWidth > 0 ? Math.floor(style.borderWidth) : 1;
const borderRadius =
Number.isFinite(style.borderRadius) && style.borderRadius >= 0 ? Math.floor(style.borderRadius) : 18;
return {
width: `${size}px`,
height: `${size}px`,
borderWidth: `${borderWidth}px`,
borderRadius: `${borderRadius}px`,
};
}
onMounted(() => {
timerId = window.setInterval(() => {
nowMs.value = Date.now();
}, 1000);
});
onUnmounted(() => {
if (timerId !== null) {
window.clearInterval(timerId);
timerId = null;
}
});
</script>