現在要實現一個按鈕長按的功能,大概有如下幾個要點:
1、長按按鈕,按鈕覆蓋整個輸入框
2、長按的過程中移動手指,判斷手指移動的位置是否在按鈕內
3、長按鬆開,按鈕還原
按鈕結構如下:
<view
id="audio-full"
:class="[
'audio-full',
isLongpress && 'touch-longpress'
]"
v-if="isAudio"
@longtap="onLongtap"
@touchmove="onTouchmove"
@touchend="onTouchend">
{{isLongpress ? '長按':'未長按'}}-位置 {{isOutOfBounds ? '外' : '內'}}
</view>
長按主要用到以下核心功能:
● @longtap
● @touchmove
● @touchend
具體描述官網有寫:https://uniapp.dcloud.net.cn/component/canvas.html#canvas
下面拆解一下如何實現:
當我們長按的時候,會觸發@longtap事件,我們在該事件內獲取到按鈕的dom元素信息
import { getCurrentInstance,nextTick } from 'vue';
const { proxy } = getCurrentInstance();
const query = uni.createSelectorQuery().in(proxy);
let buttonRect = null; // dom元素
const isLongpress = ref(false); // 是否長按
const onLongtap = () => {
isLongpress.value = true;
// 在nextTick內獲取dom信息,此時可以拿到正確的dom大小
nextTick(() => {
query
.select('#audio-full')
.boundingClientRect((data) => {
buttonRect = data;
console.log('dom信息' + JSON.stringify(buttonRect));
})
.exec();
});
};
通過uni.createSelectorQuery + query.select('#domId').boundingClientRect查詢節點信息
文檔:https://uniapp.dcloud.net.cn/api/ui/nodes-info.html#createsel...
拿到dom信息後,用户可能會移動手指,比如語音上滑取消錄音功能,此時我們要判斷手指移動是否處在按鈕範圍內,移動手指會觸發@touchmove事件
const isOutOfBounds = ref(false); // 是否超出邊界
const onTouchmove = (e) => {
if (!buttonRect) return
const touch = e.touches[0];
const { left, top, width, height } = buttonRect;
// 判斷觸摸點是否超出按鈕範圍
isOutOfBounds.value = touch.clientX < left || touch.clientX > left + width || touch.clientY < top || touch.clientY > top + height;
};
最後鬆開,還原按鈕
const onTouchend = () => {
isLongpress.value = false;
};
完整核心代碼如下:
<view
id="audio-full"
:class="[
'audio-full',
isLongpress && 'touch-longpress'
]"
v-if="isAudio"
@longtap="onLongtap"
@touchmove="onTouchmove"
@touchend="onTouchend">
{{isLongpress ? '長按':'未長按'}}-位置 {{isOutOfBounds ? '外' : '內'}}
</view>
let buttonRect = null; // dom信息
const isOutOfBounds = ref(false); // 是否超出按鈕邊界
// 長按觸發
const onLongtap = () => {
isLongpress.value = true;
nextTick(() => {
query
.select('#audio-full')
.boundingClientRect((data) => {
buttonRect = data;
console.log('dom信息' + JSON.stringify(buttonRect));
})
.exec();
});
};
// 移動觸發
const onTouchmove = (e) => {
if (!buttonRect) return
const touch = e.touches[0];
const { left, top, width, height } = buttonRect;
// 判斷觸摸點是否超出按鈕範圍
isOutOfBounds.value = touch.clientX < left || touch.clientX > left + width || touch.clientY < top || touch.clientY > top + height;
};
// 觸摸鬆開
const onTouchend = () => {
isLongpress.value = false;
};
參考文檔:
uniapp按鈕長按和觸摸事件
查詢節點信息的對象