scrcpy-mask/src/components/Mask.vue

192 lines
4.5 KiB
Vue
Raw Normal View History

2024-04-13 09:53:41 +08:00
<script setup lang="ts">
2024-04-25 22:48:05 +08:00
import { Ref, onActivated, ref } from "vue";
import { NDialog, useMessage } from "naive-ui";
2024-04-13 09:53:41 +08:00
import { useGlobalStore } from "../store/global";
2024-04-14 17:15:39 +08:00
import { onBeforeRouteLeave, useRouter } from "vue-router";
import {
applyShortcuts,
clearShortcuts,
listenToKeyEvent,
unlistenToKeyEvent,
updateScreenSizeAndMaskArea,
} from "../hotkey";
import { getCurrent } from "@tauri-apps/api/window";
2024-04-13 09:53:41 +08:00
const store = useGlobalStore();
const router = useRouter();
const message = useMessage();
2024-04-13 09:53:41 +08:00
2024-04-25 22:48:05 +08:00
const renderedButtons: Ref<any[]> = ref([]);
2024-04-14 17:15:39 +08:00
onBeforeRouteLeave(() => {
2024-04-27 17:43:20 +08:00
const maskElement = document.getElementById("maskElement") as HTMLElement;
2024-04-27 09:26:14 +08:00
if (store.controledDevice) {
unlistenToKeyEvent();
2024-04-27 09:26:14 +08:00
clearShortcuts(maskElement);
2024-04-14 17:15:39 +08:00
}
});
2024-04-13 09:53:41 +08:00
onActivated(async () => {
2024-04-27 17:43:20 +08:00
const maskElement = document.getElementById("maskElement") as HTMLElement;
2024-04-27 09:26:14 +08:00
if (store.controledDevice) {
const mt = 30;
const ml = 70;
const appWindow = getCurrent();
const size = (await appWindow.outerSize()).toLogical(
await appWindow.scaleFactor()
);
updateScreenSizeAndMaskArea(
[store.screenSizeW, store.screenSizeH],
[size.width - ml, size.height - mt]
);
if (
applyShortcuts(
2024-04-27 09:26:14 +08:00
maskElement,
store.keyMappingConfigList[store.curKeyMappingIndex]
)
) {
2024-04-27 17:43:20 +08:00
refreshKeyMappingButton();
listenToKeyEvent();
2024-04-27 09:26:14 +08:00
} else {
message.error("按键方案异常,请删除此方案");
}
2024-04-13 09:53:41 +08:00
}
});
function toStartServer() {
router.replace({ name: "device" });
}
2024-04-25 22:48:05 +08:00
function refreshKeyMappingButton() {
2024-04-27 17:43:20 +08:00
const maskElement = document.getElementById("maskElement") as HTMLElement;
2024-04-27 09:26:14 +08:00
const curKeyMappingConfig =
store.keyMappingConfigList[store.curKeyMappingIndex];
2024-04-25 22:48:05 +08:00
const relativeSize = curKeyMappingConfig.relativeSize;
2024-04-27 09:26:14 +08:00
const maskSizeW = maskElement.clientWidth;
const maskSizeH = maskElement.clientHeight;
2024-04-27 17:43:20 +08:00
const relativePosToMaskPos = (x: number, y: number) => {
return {
x: Math.round((x / relativeSize.w) * maskSizeW),
y: Math.round((y / relativeSize.h) * maskSizeH),
2024-04-25 22:48:05 +08:00
};
2024-04-27 17:43:20 +08:00
};
const buttons = [];
for (let keyObject of curKeyMappingConfig.list) {
const { x, y } = relativePosToMaskPos(keyObject.posX, keyObject.posY);
buttons.push({
...keyObject,
x,
y,
});
2024-04-25 22:48:05 +08:00
}
2024-04-27 17:43:20 +08:00
renderedButtons.value = buttons;
2024-04-25 22:48:05 +08:00
}
2024-04-13 09:53:41 +08:00
</script>
<template>
<div v-show="!store.controledDevice" class="notice">
<div class="content">
<NDialog
:closable="false"
title="未找到受控设备"
content="请启动服务端并控制任意设备"
positive-text="去启动"
type="warning"
@positive-click="toStartServer"
/>
</div>
</div>
<div
v-show="store.controledDevice"
2024-04-14 17:15:39 +08:00
@contextmenu.prevent
2024-04-13 09:53:41 +08:00
class="mask"
2024-04-27 17:43:20 +08:00
id="maskElement"
2024-04-25 22:48:05 +08:00
>
<template v-for="button in renderedButtons">
<div
v-if="button.type === 'SteeringWheel'"
class="mask-steering-wheel"
:style="{
left: button.x - 75 + 'px',
top: button.y - 75 + 'px',
}"
>
<div class="wheel-container">
<i />
<span>{{ button.key.up }}</span>
<i />
<span>{{ button.key.left }}</span>
<i />
<span>{{ button.key.right }}</span>
<i />
<span>{{ button.key.down }}</span>
<i />
2024-04-25 22:48:05 +08:00
</div>
</div>
<div
v-else
class="mask-button"
:style="{
left: button.x + 'px',
top: button.y - 14 + 'px',
}"
>
{{ button.key }}
</div>
</template>
</div>
2024-04-13 09:53:41 +08:00
</template>
<style scoped lang="scss">
.mask {
background-color: transparent;
2024-04-13 09:53:41 +08:00
overflow: hidden;
2024-04-14 17:15:39 +08:00
cursor: pointer;
2024-04-25 22:48:05 +08:00
position: relative;
border-right: 1px solid var(--bg-color);
border-bottom: 1px solid var(--bg-color);
border-radius: 0 0 5px 0;
& > .mask-button {
position: absolute;
background-color: rgba(0, 0, 0, 0.2);
color: rgba(255, 255, 255, 0.6);
border-radius: 5px;
padding: 5px;
font-size: 12px;
}
& > .mask-steering-wheel {
position: absolute;
background-color: rgba(0, 0, 0, 0.2);
color: rgba(255, 255, 255, 0.6);
border-radius: 50%;
width: 150px;
height: 150px;
font-size: 12px;
.wheel-container {
display: grid;
grid-template-columns: repeat(3, 50px);
grid-template-rows: repeat(3, 50px);
justify-items: center;
align-items: center;
}
}
2024-04-13 09:53:41 +08:00
}
.notice {
background-color: rgba(0, 0, 0, 0.5);
2024-04-13 09:53:41 +08:00
display: flex;
justify-content: center;
align-items: center;
.content {
width: 80%;
}
}
</style>