feat(KeyCommon): add common key button

This commit is contained in:
AkiChase 2024-04-27 17:43:20 +08:00
parent de89425d73
commit 0f38ca0d5c
6 changed files with 247 additions and 39 deletions

View File

@ -19,7 +19,7 @@ const message = useMessage();
const renderedButtons: Ref<any[]> = ref([]);
onBeforeRouteLeave(() => {
const maskElement = document.getElementById("mask") as HTMLElement;
const maskElement = document.getElementById("maskElement") as HTMLElement;
if (store.controledDevice) {
unlistenToKeyEvent();
@ -28,7 +28,7 @@ onBeforeRouteLeave(() => {
});
onActivated(async () => {
const maskElement = document.getElementById("mask") as HTMLElement;
const maskElement = document.getElementById("maskElement") as HTMLElement;
if (store.controledDevice) {
const mt = 30;
@ -42,13 +42,13 @@ onActivated(async () => {
[size.width - ml, size.height - mt]
);
refreshKeyMappingButton();
if (
applyShortcuts(
maskElement,
store.keyMappingConfigList[store.curKeyMappingIndex]
)
) {
refreshKeyMappingButton();
listenToKeyEvent();
} else {
message.error("按键方案异常,请删除此方案");
@ -61,31 +61,29 @@ function toStartServer() {
}
function refreshKeyMappingButton() {
const maskElement = document.getElementById("mask") as HTMLElement;
const maskElement = document.getElementById("maskElement") as HTMLElement;
const curKeyMappingConfig =
store.keyMappingConfigList[store.curKeyMappingIndex];
const relativeSize = curKeyMappingConfig.relativeSize;
const maskSizeW = maskElement.clientWidth;
const maskSizeH = maskElement.clientHeight;
if (maskSizeW && maskSizeH) {
const relativePosToMaskPos = (x: number, y: number) => {
return {
x: Math.round((x / relativeSize.w) * maskSizeW),
y: Math.round((y / relativeSize.h) * maskSizeH),
};
const relativePosToMaskPos = (x: number, y: number) => {
return {
x: Math.round((x / relativeSize.w) * maskSizeW),
y: Math.round((y / relativeSize.h) * maskSizeH),
};
const buttons = [];
for (let keyObject of curKeyMappingConfig.list) {
const { x, y } = relativePosToMaskPos(keyObject.posX, keyObject.posY);
buttons.push({
...keyObject,
x,
y,
});
}
renderedButtons.value = buttons;
};
const buttons = [];
for (let keyObject of curKeyMappingConfig.list) {
const { x, y } = relativePosToMaskPos(keyObject.posX, keyObject.posY);
buttons.push({
...keyObject,
x,
y,
});
}
renderedButtons.value = buttons;
}
</script>
@ -106,7 +104,7 @@ function refreshKeyMappingButton() {
v-show="store.controledDevice"
@contextmenu.prevent
class="mask"
id="mask"
id="maskElement"
>
<template v-for="button in renderedButtons">
<div

View File

@ -1,28 +1,124 @@
<script setup lang="ts">
import { ref } from "vue";
import { onActivated, ref } from "vue";
import KeyInfo from "./KeyInfo.vue";
import KeySetting from "./KeySetting.vue";
import KeyCommon from "./KeyCommon.vue";
import { useGlobalStore } from "../../store/global";
import { useDialog, useMessage } from "naive-ui";
import { onBeforeRouteLeave } from "vue-router";
// TODO active-1
// TODO
// TODO
// TODO
// TODO
const keyInfoShowFlag = ref(false);
const store = useGlobalStore();
const message = useMessage();
const dialog = useDialog();
const activeButtonIndex = ref(-1);
let edited = ref(false);
onActivated(() => {
// migrate keyMappingConfig if relativeSize does not match
migrateKeyMappingConfig();
// reset editKeyMappingList as the same as keyMappingList
store.resetEditKeyMappingList();
});
onBeforeRouteLeave(() => {
if (edited.value) {
dialog.warning({
title: "Warning",
content: "当前方案尚未保存,是否保存?",
positiveText: "保存",
negativeText: "取消",
onPositiveClick: () => {
store.applyEditKeyMappingList();
edited.value = false;
},
onNegativeClick: () => {
store.resetEditKeyMappingList();
edited.value = false;
},
});
}
});
function migrateKeyMappingConfig() {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const curKeyMappingConfig =
store.keyMappingConfigList[store.curKeyMappingIndex];
const relativeSize = curKeyMappingConfig.relativeSize;
const sizeW = keyboardElement.clientWidth;
const sizeH = keyboardElement.clientHeight;
if (sizeW !== relativeSize.w || sizeH !== relativeSize.h) {
const newConfig = {
...curKeyMappingConfig,
relativeSize: {
w: sizeW,
h: sizeH,
},
};
const relativePosToMaskPos = (x: number, y: number) => {
return {
x: Math.round((x / relativeSize.w) * sizeW),
y: Math.round((y / relativeSize.h) * sizeH),
};
};
for (let keyMapping of curKeyMappingConfig.list) {
const { x, y } = relativePosToMaskPos(keyMapping.posX, keyMapping.posY);
keyMapping.posX = x;
keyMapping.posY = y;
}
newConfig.title += "-迁移";
store.keyMappingConfigList.splice(store.curKeyMappingIndex, 1, newConfig);
store.curKeyMappingIndex += 1;
message.warning(
"当前按键方案与蒙版尺寸不一致,已自动迁移到新方案:" + newConfig.title
);
}
}
</script>
<template>
<div id="keyboardElement" class="keyboard">
<KeySetting v-model="keyInfoShowFlag" />
<KeyInfo v-model="keyInfoShowFlag" />
<template v-for="(_, index) in store.editKeyMappingList">
<KeyCommon
@edit="edited = true"
@active="activeButtonIndex = index"
:index="index"
:activeIndex="activeButtonIndex"
/>
</template>
</div>
</template>
<style scoped>
<style scoped lang="scss">
.keyboard {
color: var(--light-color);
background-color: rgba(0, 0, 0, 0.5);
overflow: hidden;
position: relative;
.keyboard-button {
position: absolute;
border-radius: 50%;
width: 40px;
height: 40px;
border: 1px solid red;
background-color: red;
}
}
</style>

View File

@ -0,0 +1,92 @@
<script setup lang="ts">
import { ref } from "vue";
import { useGlobalStore } from "../../store/global";
const emit = defineEmits<{
edit: [];
active: [];
}>();
const props = defineProps<{
index: number;
activeIndex: number;
}>();
const store = useGlobalStore();
const elementRef = ref<HTMLElement | null>(null);
function dragHandler(downEvent: MouseEvent) {
emit("active");
const oldX = store.editKeyMappingList[props.index].posX;
const oldY = store.editKeyMappingList[props.index].posY;
const element = elementRef.value;
if (element) {
const keyboardElement = document.getElementById(
"keyboardElement"
) as HTMLElement;
const maxX = keyboardElement.clientWidth - 40;
const maxY = keyboardElement.clientHeight - 40;
const x = downEvent.clientX;
const y = downEvent.clientY;
const moveHandler = (moveEvent: MouseEvent) => {
let newX = oldX + moveEvent.clientX - x;
let newY = oldY + moveEvent.clientY - y;
newX = Math.max(0, Math.min(newX, maxX));
newY = Math.max(0, Math.min(newY, maxY));
store.editKeyMappingList[props.index].posX = newX;
store.editKeyMappingList[props.index].posY = newY;
};
window.addEventListener("mousemove", moveHandler);
const upHandler = () => {
window.removeEventListener("mousemove", moveHandler);
window.removeEventListener("mouseup", upHandler);
if (
oldX !== store.editKeyMappingList[props.index].posX ||
oldY !== store.editKeyMappingList[props.index].posY
) {
emit("edit");
}
};
window.addEventListener("mouseup", upHandler);
}
}
</script>
<template>
<div
:class="{ active: props.index === activeIndex }"
:style="{
left: `${store.editKeyMappingList[props.index].posX - 20}px`,
top: `${store.editKeyMappingList[props.index].posY - 20}px`,
}"
@mousedown="dragHandler"
class="key-common"
ref="elementRef"
>
{{ store.editKeyMappingList[props.index].key }}
</div>
</template>
<style scoped lang="scss">
.key-common {
position: absolute;
height: 40px;
width: 40px;
border-radius: 50%;
border: 2px solid var(--blue-color);
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
font-weight: bold;
cursor: pointer;
&:not(.active):hover {
border: 2px solid var(--light-color);
}
}
.active {
border: 2px solid var(--primary-color);
color: var(--primary-color);
}
</style>

View File

@ -82,8 +82,8 @@ function dragHandler(downEvent: MouseEvent) {
};
window.addEventListener("mousemove", moveHandler);
const upHandler = (upEvent: MouseEvent) => {
lastPosX = lastPosX + upEvent.clientX - x;
lastPosY = lastPosY + upEvent.clientY - y;
lastPosX += upEvent.clientX - x;
lastPosY += upEvent.clientY - y;
window.removeEventListener("mousemove", moveHandler);
window.removeEventListener("mouseup", upHandler);
target.style.setProperty("cursor", "grab");

View File

@ -72,7 +72,6 @@ onMounted(async () => {
else if (keySettingPos.y > maxHeight) keySettingPos.y = maxHeight;
target.style.setProperty("right", `${keySettingPos.x}px`);
target.style.setProperty("bottom", `${keySettingPos.y}px`);
console.log("keySettingPos", keySettingPos);
});
function dragHandler(downEvent: MouseEvent) {
@ -140,10 +139,9 @@ function importKeyMappingConfig() {
return;
}
store.keyMappingConfigList.push(keyMappingConfig);
store.curKeyMappingIndex = store.keyMappingConfigList.length - 1;
store.setKeyMappingIndex(store.keyMappingConfigList.length - 1);
showImportModal.value = false;
localStore.set("keyMappingConfigList", store.keyMappingConfigList);
localStore.set("curKeyMappingIndex", store.curKeyMappingIndex);
message.success("按键方案已导入");
}
@ -180,9 +178,8 @@ function createKeyMappingConfig() {
list: [],
};
store.keyMappingConfigList.push(newConfig);
store.curKeyMappingIndex = store.keyMappingConfigList.length - 1;
store.setKeyMappingIndex(store.keyMappingConfigList.length - 1);
localStore.set("keyMappingConfigList", store.keyMappingConfigList);
localStore.set("curKeyMappingIndex", store.curKeyMappingIndex);
message.success("新方案已创建");
}
@ -194,9 +191,8 @@ function copyCurKeyMappingConfig() {
list: curConfig.list,
};
store.keyMappingConfigList.push(newConfig);
store.curKeyMappingIndex = store.keyMappingConfigList.length - 1;
store.setKeyMappingIndex(store.keyMappingConfigList.length - 1);
localStore.set("keyMappingConfigList", store.keyMappingConfigList);
localStore.set("curKeyMappingIndex", store.curKeyMappingIndex);
message.success("方案已复制为:" + curConfig.title + "-副本");
}
@ -207,10 +203,10 @@ function delCurKeyMappingConfig() {
}
const title = store.keyMappingConfigList[store.curKeyMappingIndex].title;
store.keyMappingConfigList.splice(store.curKeyMappingIndex, 1);
store.curKeyMappingIndex =
store.curKeyMappingIndex > 0 ? store.curKeyMappingIndex - 1 : 0;
store.setKeyMappingIndex(
store.curKeyMappingIndex > 0 ? store.curKeyMappingIndex - 1 : 0
);
localStore.set("keyMappingConfigList", store.keyMappingConfigList);
localStore.set("curKeyMappingIndex", store.curKeyMappingIndex);
message.success("方案已删除:" + title);
}
@ -259,8 +255,8 @@ function exportKeyMappingConfig() {
</NButton>
<NH4 prefix="bar">按键方案</NH4>
<NSelect
v-model:value="store.curKeyMappingIndex"
@update:value="(value: string)=>localStore.set('curKeyMappingIndex', value)"
:value="store.curKeyMappingIndex"
@update:value="(value: number)=>store.setKeyMappingIndex(value)"
:options="keyMappingNameOptions"
/>
<NP>

View File

@ -1,7 +1,10 @@
import { defineStore } from "pinia";
import { Ref, ref } from "vue";
import { Device } from "../invoke";
import { KeyMappingConfig } from "../keyMappingConfig";
import { KeyMapping, KeyMappingConfig } from "../keyMappingConfig";
import { Store } from "@tauri-apps/plugin-store";
const localStore = new Store("store.bin");
export const useGlobalStore = defineStore("counter", () => {
const showLoadingRef = ref(false);
@ -23,8 +26,27 @@ export const useGlobalStore = defineStore("counter", () => {
const controledDevice: Ref<ControledDevice | null> = ref(null);
const keyMappingConfigList: KeyMappingConfig[] = [];
const keyMappingConfigList: Ref<KeyMappingConfig[]> = ref([]);
const curKeyMappingIndex = ref(0);
const editKeyMappingList: Ref<KeyMapping[]> = ref([]);
function applyEditKeyMappingList() {
keyMappingConfigList.value[curKeyMappingIndex.value].list =
editKeyMappingList.value;
localStore.set("keyMappingConfigList", keyMappingConfigList.value);
}
function resetEditKeyMappingList() {
editKeyMappingList.value = JSON.parse(
JSON.stringify(keyMappingConfigList.value[curKeyMappingIndex.value].list)
);
}
function setKeyMappingIndex(index: number) {
curKeyMappingIndex.value = index;
resetEditKeyMappingList();
localStore.set("curKeyMappingIndex", index);
}
return {
showLoading,
@ -35,5 +57,9 @@ export const useGlobalStore = defineStore("counter", () => {
screenSizeH,
keyMappingConfigList,
curKeyMappingIndex,
editKeyMappingList,
applyEditKeyMappingList,
resetEditKeyMappingList,
setKeyMappingIndex,
};
});