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
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>
|