一、引言
useMouse
是 VueUse 提供的一个功能,用于在 Vue.js 应用中跟踪鼠标位置
。它会返回鼠标的 x 和 y 坐标,并可以配置处理触摸事件、滚动事件和自定义事件提取器。
基本用法是导入 useMouse 并访问坐标。还可以通过选项禁用触摸跟踪或指定目标元素进行自定义。
二、引入
npm i @vueuse/core
三、揭秘useMouse
- 默认使用
<script>
import {useMouse} from '@vueuse/core';
const { x, y } = useMouse();
</script>
2. 使用touch选项
<script lang="ts" setup>
import {ref,computed,watch,onMounted} from 'vue';
import {useMouse } from '@vueuse/core';
const {x,y} = useMouse({ // x,y就是鼠标位置
touch: false // 不响应触摸事件
});
</script>
①touch为false:仅响应鼠标事件;
②touch为true(默认):同时响应鼠标和触摸事件,比如手指按下屏幕然后上下拖时会得到触摸位置,而“”“仅响应鼠标事件”只会监测点击位置。
3. 使用target和type选项
<script lang="ts" setup>
// 必备依赖
import { ref } from 'vue';
import { useParentElement, useMouse } from '@vueuse/core';
import type { UseMouseEventExtractor } from '@vueuse/core' //
const red = ref(null);
const cursor = ref(null);
const parentEl = useParentElement(cursor);
// useParentElement()参数:
// 无参:什么都不传,默认父元素为最外层div;
// 有参:传一个元素,就会获取到该元素的父元素;
const extractor: UseMouseEventExtractor = event => {
console.log("看看这是啥",event);
return event instanceof Touch ? null : [event.offsetX, event.offsetY]
}
// 官网的extractor写法等价如下
// const extractor: UseMouseEventExtractor = event => {
// return event instanceof Touch ? null : [event.offsetX, event.offsetY];
// };
const { x, y } = useMouse({
target: parentEl, //只响应鼠标在curosr的父元素内的位置
type:extractor
});
</script>
控制台打印可以看到extractor的event就是鼠标对象,那么接下来就考的是js基本功了
红线标出区域,可以自定义:
①screenX 和 screenY:相对于整个屏幕的位置,适用于需要跨屏幕或绝对屏幕坐标的情况;
②clientX 和 clientY:相对于浏览器视口的位置,适用于网页中的用户交互,不考虑滚动;
③offsetX 和 offsetY:相对于事件目标元素的位置,适用于需要知道事件发生在元素内部具体位置的情况;(问题:如果元素内部有很多子元素,那么鼠标移动到每一个子元素的区域时,offset的值都会是相较于该子元素的左上角的点进行偏移,具体你可以试一下)
④pageX 和 pageY:相对于整个文档的位置,适用于需要考虑页面滚动的情况;
四、揭秘useMouselnElement
以上属性均被export,import之后即是响应式的,来个小案例直观感受一下,基于elementX、elementY和isOutside;
demo:自定义指针小案例
<template>
<div>
<div ref="red" class="red">
<div ref="cursor" class="curso"></div>
<h1>鼠标位置X:{{ x }},Y:{{ y }}</h1>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref,computed,watch,onMounted} from 'vue';
import {useMouseInElement } from '@vueuse/core';
const red = ref(null);
const cursor = ref(null);
const {
elementX,
elementY,
isOutside
} = useMouseInElement(red);
const x = computed({
get(){
if(!isOutside.value){ // 不在外面,返回元素内鼠标的位置
return Math.floor(elementX.value);
}
return 0; // 代码缺陷,鼠标离开指定区域后只能归位0
// 我想的解决方案是外边创建一个响应式位置锁positionLock,outX,outY。
// 鼠标移出,位置锁生效,根据isOutside交叉记录elementX和elementY为之前的位置
},
set(val){
elementX.value=val;
}
})
const y = computed({
get(){
if(!isOutside.value){ // 不在外面,返回元素内鼠标的位置
return Math.floor(elementY.value);
}
return 0; // 代码缺陷,鼠标离开指定区域后只能归位0
},
set(val){
elementY.value=val;
}
})
let cursorElement = null;
onMounted(()=>{
cursorElement = cursor.value;
})
watch([x,y],()=>{
cursorElement.style.left = x.value+'px';
cursorElement.style.top = y.value+'px';
// console.dir(cursorElement);
})
</script>
<style scoped>
div{
position: relative;
height: 100vh;
}
.curso{
position: absolute;
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid darkblue;
background-color: aqua;
}
.curso::after{
position: absolute;
content: " ";
width: 10px;
height: 20px;
top:-80%;
left: -8px;
transform: rotate(-45deg);
transform-origin: center center;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
background-color: aqua;
border: 1px solid darkblue;
}
.red{
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
min-width: 600px;
width: 70%;
height: 300px;
background-color: antiquewhite;
}
</style>
五、useMousePressed
useMousePressed()
提供了一个响应式的布尔值,表示鼠标按钮是否被按下。
const options: MousePressedOptions = {
touch: true, // 监听触摸事件
drag: true, // 监听拖动事件
capture: true, // 使用事件捕获
initialValue: false, // 初始值
target: parentEl, // 捕获点击的目标元素
};
// 使用 useMousePressed 组合式函数,传入自定义选项
const {
pressed: isPressed,
sourceType
} = useMousePressed(options);