Skip to content

Commit 1123df2

Browse files
committed
feat(组件): 为文本属性组件添加自动清除焦点功能
在多个文本属性组件(FontFamilyProps, FontSizeProps等)中添加了自动清除焦点的功能,通过调用DOMUtils.clearFocus()方法 在用户完成属性选择后自动清除输入框的焦点,提升用户体验
1 parent f6a689b commit 1123df2

File tree

7 files changed

+68
-19
lines changed

7 files changed

+68
-19
lines changed

src/components/ui/right/props/FontFamilyProps.vue

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { FontFamilyList } from "@/styles/ElementStyles";
4-
import { ref, watch } from "vue";
4+
import DOMUtils from "@/utils/DOMUtils";
5+
import { nextTick, ref, watch } from "vue";
56
67
const stageStore = useStageStore();
78
const fontFamily = ref(DefaultStage.fontFamily);
@@ -20,6 +21,11 @@ watch(
2021
fontFamilyMixin.value = newValue;
2122
},
2223
);
24+
25+
function setElementsFontFamily(value: string) {
26+
stageStore.setElementsFontFamily(value);
27+
nextTick(() => DOMUtils.clearFocus());
28+
}
2329
</script>
2430
<template>
2531
<div class="font-props right-props" v-show="stageStore.fontEnable">
@@ -32,7 +38,7 @@ watch(
3238
v-model="fontFamily"
3339
:placeholder="`${fontFamilyMixin ? '混合字体' : fontFamily}`"
3440
size="small"
35-
@change="value => stageStore.setElementsFontFamily(value)"
41+
@change="setElementsFontFamily"
3642
:disabled="stageStore.inputDisabled || !stageStore.fontInputEnable"
3743
>
3844
<template #label="{ label, value }">

src/components/ui/right/props/FontLetterSpacingProps.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { FontLetterSpacingList } from "@/styles/ElementStyles";
4-
import { ref, watch } from "vue";
4+
import DOMUtils from "@/utils/DOMUtils";
5+
import { nextTick, ref, watch } from "vue";
56
67
const stageStore = useStageStore();
78
const fontLetterSpacing = ref(DefaultStage.fontLetterSpacing);
@@ -20,6 +21,11 @@ watch(
2021
fontLetterSpacingMixin.value = newValue;
2122
},
2223
);
24+
25+
function setElementsFontLetterSpacing(value: number) {
26+
stageStore.setElementsFontLetterSpacing(value);
27+
nextTick(() => DOMUtils.clearFocus());
28+
}
2329
</script>
2430
<template>
2531
<div class="font-props right-props" v-show="stageStore.fontEnable">
@@ -33,7 +39,7 @@ watch(
3339
v-model="fontLetterSpacing"
3440
:placeholder="`${stageStore.fontLetterSpacingMixin ? '混合字间距' : `${fontLetterSpacing}px`}`"
3541
size="small"
36-
@change="value => stageStore.setElementsFontLetterSpacing(value)"
42+
@change="setElementsFontLetterSpacing"
3743
:disabled="stageStore.inputDisabled || !stageStore.fontLetterSpacingInputEnable"
3844
>
3945
<el-option v-for="item in FontLetterSpacingList" :key="item.name" :label="`${item.value}px`" :value="item.value"> {{ item.value }}px </el-option>
@@ -47,7 +53,7 @@ watch(
4753
:min="1"
4854
:max="100"
4955
:precision="0"
50-
@change="value => stageStore.setElementsFontLetterSpacing(Number(value))"
56+
@change="value => setElementsFontLetterSpacing(Number(value))"
5157
>
5258
<template #prepend>自定义</template>
5359
<template #append>px</template>

src/components/ui/right/props/FontLineHeightProps.vue

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { DefaultFontSize, FontLineHeightFactorList, FontLineHeightList } from "@/styles/ElementStyles";
4-
import { ref, watch } from "vue";
4+
import DOMUtils from "@/utils/DOMUtils";
5+
import { nextTick, ref, watch } from "vue";
56
67
const stageStore = useStageStore();
78
const fontLineHeight = ref(DefaultStage.fontLineHeight);
@@ -36,6 +37,16 @@ watch(
3637
fontLineHeightFactorInputEnable.value = newValue;
3738
},
3839
);
40+
41+
function setElementsFontLineHeightFactor(value: number) {
42+
stageStore.setElementsFontLineHeightFactor(value);
43+
nextTick(() => DOMUtils.clearFocus());
44+
}
45+
46+
function setElementsFontLineHeight(value: number) {
47+
stageStore.setElementsFontLineHeight(value);
48+
nextTick(() => DOMUtils.clearFocus());
49+
}
3950
</script>
4051
<template>
4152
<div class="font-props right-props" v-show="stageStore.fontEnable">
@@ -59,7 +70,7 @@ watch(
5970
<el-select
6071
v-model="fontLineHeightFactor"
6172
size="small"
62-
@change="value => stageStore.setElementsFontLineHeightFactor(value)"
73+
@change="setElementsFontLineHeightFactor"
6374
:disabled="stageStore.inputDisabled || !stageStore.fontLineHeightFactorInputEnable"
6475
>
6576
<el-option v-for="item in FontLineHeightFactorList" :key="item.name" :label="`${item.value}x字号`" :value="item.value"> {{ item.value }}x字号 </el-option>
@@ -73,7 +84,7 @@ watch(
7384
:min="0"
7485
:max="2"
7586
:precision="1"
76-
@change="value => stageStore.setElementsFontLineHeightFactor(Number(value))"
87+
@change="value => setElementsFontLineHeightFactor(Number(value))"
7788
>
7889
<template #prepend>自定义</template>
7990
<template #append>x字号</template>
@@ -85,7 +96,7 @@ watch(
8596

8697
<div class="font-props__row" v-show="!fontLineHeightAutoFit">
8798
<div class="font-props__row-item">
88-
<el-select v-model="fontLineHeight" size="small" @change="value => stageStore.setElementsFontLineHeight(value)" :disabled="stageStore.inputDisabled || !stageStore.fontLineHeightInputEnable">
99+
<el-select v-model="fontLineHeight" size="small" @change="setElementsFontLineHeight" :disabled="stageStore.inputDisabled || !stageStore.fontLineHeightInputEnable">
89100
<el-option v-for="item in FontLineHeightList" :key="item.name" :label="`${item.value}px`" :value="item.value"> {{ item.value }}px </el-option>
90101
<template #header>
91102
<el-input
@@ -97,7 +108,7 @@ watch(
97108
:min="DefaultFontSize"
98109
:max="100"
99110
:precision="1"
100-
@change="value => stageStore.setElementsFontLineHeight(Number(value))"
111+
@change="value => setElementsFontLineHeight(Number(value))"
101112
>
102113
<template #prepend>自定义</template>
103114
<template #append>px</template>

src/components/ui/right/props/FontParagraphSpacingProps.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { ParagraphSpacingList } from "@/styles/ElementStyles";
4-
import { ref, watch } from "vue";
4+
import DOMUtils from "@/utils/DOMUtils";
5+
import { nextTick, ref, watch } from "vue";
56
67
const stageStore = useStageStore();
78
const paragraphSpacing = ref(DefaultStage.paragraphSpacing);
@@ -12,6 +13,11 @@ watch(
1213
paragraphSpacing.value = newValue;
1314
},
1415
);
16+
17+
function setElementsParagraphSpacing(value: number) {
18+
stageStore.setElementsParagraphSpacing(value);
19+
nextTick(() => DOMUtils.clearFocus());
20+
}
1521
</script>
1622
<template>
1723
<div class="font-props right-props" v-show="stageStore.fontEnable">
@@ -25,7 +31,7 @@ watch(
2531
v-model="paragraphSpacing"
2632
placeholder=""
2733
size="small"
28-
@change="value => stageStore.setElementsParagraphSpacing(value)"
34+
@change="setElementsParagraphSpacing"
2935
:disabled="stageStore.inputDisabled || !stageStore.paragraphSpacingInputEnable"
3036
>
3137
<el-option v-for="item in ParagraphSpacingList" :key="item.name" :label="`${item.value}px`" :value="item.value"> {{ item.value }}px </el-option>
@@ -39,7 +45,7 @@ watch(
3945
:min="0"
4046
:max="100"
4147
:precision="0"
42-
@change="value => stageStore.setElementsParagraphSpacing(Number(value))"
48+
@change="value => setElementsParagraphSpacing(Number(value))"
4349
>
4450
<template #prepend>自定义</template>
4551
<template #append>px</template>

src/components/ui/right/props/FontSizeProps.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { FontSizeList } from "@/styles/ElementStyles";
4-
import { ref, watch } from "vue";
4+
import DOMUtils from "@/utils/DOMUtils";
5+
import { nextTick, ref, watch } from "vue";
56
67
const stageStore = useStageStore();
78
const fontSize = ref(DefaultStage.fontSize);
@@ -20,6 +21,11 @@ watch(
2021
fontSizeMixin.value = newValue;
2122
},
2223
);
24+
25+
function setElementsFontSize(value: number) {
26+
stageStore.setElementsFontSize(value);
27+
nextTick(() => DOMUtils.clearFocus());
28+
}
2329
</script>
2430
<template>
2531
<div class="font-props right-props" v-show="stageStore.fontEnable">
@@ -33,7 +39,7 @@ watch(
3339
v-model="fontSize"
3440
:placeholder="`${fontSizeMixin ? '混合字号' : `${fontSize}px`}`"
3541
size="small"
36-
@change="value => stageStore.setElementsFontSize(value)"
42+
@change="setElementsFontSize"
3743
:disabled="stageStore.inputDisabled || !stageStore.fontInputEnable"
3844
>
3945
<el-option v-for="item in FontSizeList" :key="item.name" :label="`${item.value}px`" :value="item.value"> {{ item.value }}px </el-option>
@@ -47,7 +53,7 @@ watch(
4753
:min="1"
4854
:max="100"
4955
:precision="0"
50-
@change="value => stageStore.setElementsFontSize(Number(value))"
56+
@change="value => setElementsFontSize(Number(value))"
5157
>
5258
<template #prepend>自定义</template>
5359
<template #append>px</template>

src/components/ui/right/props/StrokeProps.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<script lang="ts" setup>
22
import { DefaultStage, useStageStore } from "@/stores/stage";
33
import { CreatorTypes } from "@/types/Creator";
4-
import { getStokeTypes } from "@/styles/ElementStyles";
4+
import { getStokeTypes, StrokeTypes } from "@/styles/ElementStyles";
55
import { Plus, Minus } from "@element-plus/icons-vue";
6-
import { ref, watch } from "vue";
6+
import { nextTick, ref, watch } from "vue";
7+
import DOMUtils from "@/utils/DOMUtils";
78
89
const colorPickerRef = ref();
910
const stageStore = useStageStore();
@@ -28,6 +29,11 @@ const toggleColorPickerVisible = () => {
2829
if (!stageStore.strokeInputEnable) return;
2930
colorPickerRef.value.show();
3031
};
32+
33+
function setElementsStrokeType(value: StrokeTypes, index: number) {
34+
stageStore.setElementsStrokeType(value, index);
35+
nextTick(() => DOMUtils.clearFocus());
36+
}
3137
</script>
3238
<template>
3339
<div class="stroke-props right-props" v-show="stageStore.strokeEnable">
@@ -75,7 +81,7 @@ const toggleColorPickerVisible = () => {
7581
v-model="stroke.type"
7682
placeholder="描边类型"
7783
size="small"
78-
@change="value => stageStore.setElementsStrokeType(value, index)"
84+
@change="value => setElementsStrokeType(value, index)"
7985
:disabled="stageStore.inputDisabled || !stageStore.strokeInputEnable"
8086
>
8187
<el-option v-for="item in strokeTypes" :key="item.type" :label="item.name" :value="item.type" />

src/utils/DOMUtils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,12 @@ export default class DOMUtils {
5454
static isFocusOnInput(): boolean {
5555
return document.activeElement?.tagName === "INPUT" || document.activeElement?.tagName === "TEXTAREA";
5656
}
57+
58+
/**
59+
* 清除焦点
60+
*/
61+
static clearFocus() {
62+
window.getSelection()?.removeAllRanges();
63+
(document.activeElement as HTMLElement)?.blur();
64+
}
5765
}

0 commit comments

Comments
 (0)