vue3 Typescript 实现鼠标框选
首先,我们需要定义一个 Selection 类型,来表示当前选择区域的位置和大小:
interface Selection {
startX: number;
startY: number;
endX: number;
endY: number;
}
然后,我们可以创建一个 SelectionBox 组件,来实现鼠标框选的功能:
<template>
<div class="selection-box" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp">
<div class="overlay" v-if="selection">
<div :style="selectionStyle"></div>
</div>
<slot></slot>
</div>
</template>
<script lang="ts">
import { defineComponent, ref, watchEffect } from 'vue';
interface Selection {
startX: number;
startY: number;
endX: number;
endY: number;
}
export default defineComponent({
name: 'SelectionBox',
setup() {
const startX = ref(0);
const startY = ref(0);
const endX = ref(0);
const endY = ref(0);
const selection = ref<Selection | null>(null);
const onMouseDown = (event: MouseEvent) => {
startX.value = event.clientX;
startY.value = event.clientY;
endX.value = event.clientX;
endY.value = event.clientY;
selection.value = {
startX: startX.value,
startY: startY.value,
endX: endX.value,
endY: endY.value,
};
};
const onMouseMove = (event: MouseEvent) => {
if (selection.value) {
endX.value = event.clientX;
endY.value = event.clientY;
selection.value = {
startX: startX.value,
startY: startY.value,
endX: endX.value,
endY: endY.value,
};
}
};
const onMouseUp = () => {
selection.value = null;
};
const selectionStyle = ref({
left: `${Math.min(startX.value, endX.value)}px`,
top: `${Math.min(startY.value, endY.value)}px`,
width: `${Math.abs(endX.value - startX.value)}px`,
height: `${Math.abs(endY.value - startY.value)}px`,
});
watchEffect(() => {
if (selection.value) {
selectionStyle.value = {
left: `${Math.min(startX.value, endX.value)}px`,
top: `${Math.min(startY.value, endY.value)}px`,
width: `${Math.abs(endX.value - startX.value)}px`,
height: `${Math.abs(endY.value - startY.value)}px`,
};
}
});
return { onMouseDown, onMouseMove, onMouseUp, selectionStyle, selection };
},
});
</script>
<style scoped>
.selection-box {
position: relative;
}
.overlay {
position: absolute;
z-index: 1;
border: 2px dashed #000;
opacity: 0.5;
}
</style>
在 SelectionBox 组件中,我们监听了 mousedown、mousemove 和 mouseup 事件,实现了鼠标框选的功能。同时,我们也定义了一个 selectionStyle 变量,用于动态设置选择区域的样式。
最后,我们可以在应用中使用 SelectionBox 组件:
<template>
<div>
<SelectionBox>
<div v-for="item in items" :key="item.id" :style="itemStyle(item)">
{{ item.text }}
</div>
</SelectionBox>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import SelectionBox from './SelectionBox.vue';
interface Item {
id: number;
text: string;
x: number;
y: number;
}
export default defineComponent({
name: 'App',
components: { SelectionBox },
setup() {
const items = [
{ id: 1, text: 'Item 1', x: 100, y: 100 },
{ id: 2, text: 'Item 2', x: 200, y: 200 },
{ id: 3, text: 'Item 3', x: 300, y: 300 },
{ id: 4, text: 'Item 4', x: 400, y: 400 },
];
const itemStyle = (item: Item) => ({
position: 'absolute',
left: `${item.x}px`,
top: `${item.y}px`,
border: '1px solid #000',
padding: '10px',
});
return { items, itemStyle };
},
});
</script>
在这个例子中,我们将 SelectionBox 组件包裹在一些元素的外面,然后通过 v-for 渲染了一些带有位置信息的元素。当用户使用鼠标框选时,我们可以通过计算选择区域和元素的位置信息,来确定哪些元素被选中了
原文地址: https://www.cveoy.top/t/topic/exbR 著作权归作者所有。请勿转载和采集!