vue實(shí)現(xiàn)移動(dòng)端拖拽懸浮按鈕
本文實(shí)例為大家分享了vue實(shí)現(xiàn)移動(dòng)端拖拽懸浮按鈕的具體代碼,供大家參考,具體內(nèi)容如下
功能介紹:
在移動(dòng)端開發(fā)中,實(shí)現(xiàn)懸浮按鈕在側(cè)邊顯示,為不遮擋頁面內(nèi)容,允許手指拖拽換位。
大致需求:
1、按鈕在頁面?zhèn)冗厬腋★@示;
2、手指長(zhǎng)按按鈕,按鈕改變樣式,允許拖拽改變位置;
3、按鈕移動(dòng)結(jié)束,手指松開,計(jì)算距離左右兩側(cè)距離并自動(dòng)移動(dòng)至側(cè)邊顯示;
4、移動(dòng)至側(cè)邊后,按鈕根據(jù)具體左右兩次位置判斷改變現(xiàn)實(shí)樣式;
整體思路:
1、按鈕實(shí)行position:fixed布局,在頁面兩側(cè)最上層懸浮顯示;
2、手指長(zhǎng)按可使用定時(shí)器來判斷,若手指松開,則關(guān)閉定時(shí)器,等待下次操作再啟用;
3、跟隨手指移動(dòng)計(jì)算按鈕與頁面兩側(cè)的距離,判斷手指松開時(shí)停留的位置;
簡(jiǎn)單效果展示:
具體實(shí)現(xiàn):
一、position:fixed布局:
使用定位實(shí)現(xiàn)
<!-- 外層ul控制卡片范圍 --> <div> ? ? <div class="floatBtn"? ? ? ? ? :class="[{moveBtn: longClick}, `${btnType}Btn`]"> ? ? <span>懸浮按鈕</span> ? </div> </div>
<style lang="scss" scoped> ? @mixin notSelect{ ? ? -moz-user-select:none; /*火狐*/ ? ? -webkit-user-select:none; /*webkit瀏覽器*/ ? ? -ms-user-select:none; /*IE10*/ ? ? -khtml-user-select:none; /*早期瀏覽器*/ ? ? user-select:none; ? } ? @mixin not-touch { ? ? -webkit-touch-callout: none; ? ? -webkit-user-select: none; ? ? -khtml-user-select: none; ? ? -moz-user-select: none; ? ? -ms-user-select: none; ? ? user-select: none; ? } ? .floatBtn { ? ? @include notSelect; ? ? @include not-touch(); ? ? position: fixed; ? ? z-index: 1; ? ? overflow: hidden; ? ? width: 100px; ? ? left: calc(100% - 100px); ? ? top: calc(100% - 100px); ? ? color: #E0933A; ? ? background: #FCEBD0; ? ? font-size: 14px; ? ? height: 36px; ? ? line-height: 36px; ? ? text-align: center; ? ? box-sizing: border-box; ? ? display: flex; ? ? justify-content: center; ? ? align-items: center; ? ? padding: 10px; ? ? &.rightBtn { ? ? ? border-radius: 20px 0 0 20px; ? ? } ? ? &.leftBtn { ? ? ? border-radius: 0 20px 20px 0; ? ? } ? ? &.moveBtn { ? ? ? border-radius: 20px; ? ? } ? } </style>
二、touch事件綁定:
應(yīng)用到touchstart,touchmove,touchend事件,使用定時(shí)器實(shí)現(xiàn)長(zhǎng)按效果:
<div class="floatBtn" ? ? :class="[{moveBtn: longClick}, `${btnType}Btn`]" ? ? @touchstart="touchstart($event)" ? ? @touchmove="touchMove($event)" ? ? @touchend="touchEnd($event)" > ? ? <span>懸浮按鈕</span> </div>
<script> export default { ? ? data() { ? ? ? ? return { ? ? ? ? ? ? timeOutEvent: 0, ? ? ? ? ? ? longClick: 0, ? ? ? ? ? ? // 手指原始位置 ? ? ? ? ? ? oldMousePos: {}, ? ? ? ? ? ? // 元素原始位置 ? ? ? ? ? ? oldNodePos: {}, ? ? ? ? ? ? btnType: 'right' ? ? ? ? }; ? ? }, ? ? touchstart(ev) { ? ? ? ? // 定時(shí)器控制長(zhǎng)按時(shí)間,超過500毫秒開始進(jìn)行拖拽 ? ? ? ? this.timeOutEvent = setTimeout(() => { ? ? ? ? ? ? this.longClick = 1; ? ? ? ? }, 500); ? ? ? ? const selectDom = ev.currentTarget; ? ? ? ? const { pageX, pageY } = ev.touches[0]; // 手指位置 ? ? ? ? const { offsetLeft, offsetTop } = selectDom; // 元素位置 ? ? ? ? // 手指原始位置 ? ? ? ? this.oldMousePos = { ? ? ? ? ? ? x: pageX, ? ? ? ? ? ? y: pageY ? ? ? ? }; ? ? ? ? // 元素原始位置 ? ? ? ? this.oldNodePos = { ? ? ? ? ? ? x: offsetLeft, ? ? ? ? ? ? y: offsetTop ? ? ? ? }; ? ? ? ? selectDom.style.left = `${offsetLeft}px`; ? ? ? ? selectDom.style.top = `${offsetTop}px`; ? ? }, ? ? touchMove(ev) { ? ? ? ? // 未達(dá)到500毫秒就移動(dòng)則不觸發(fā)長(zhǎng)按,清空定時(shí)器 ? ? ? ? clearTimeout(this.timeOutEvent); ? ? ? ? if (this.longClick === 1) { ? ? ? ? ? ? const selectDom = ev.currentTarget; ? ? ? ? ? ? // x軸偏移量 ? ? ? ? ? ? const lefts = this.oldMousePos.x - this.oldNodePos.x; ? ? ? ? ? ? // y軸偏移量 ? ? ? ? ? ? const tops = this.oldMousePos.y - this.oldNodePos.y; ? ? ? ? ? ? const { pageX, pageY } = ev.touches[0]; // 手指位置 ? ? ? ? ? ? selectDom.style.left = `${pageX - lefts}px`; ? ? ? ? ? ? selectDom.style.top = `${pageY - tops}px`; ? ? ? ? } ? ? }, ? ? touchEnd(ev) { ? ? ? ? // 清空定時(shí)器 ? ? ? ? clearTimeout(this.timeOutEvent); ? ? ? ? if (this.longClick === 1) { ? ? ? ? ? ? this.longClick = 0; ? ? ? ? ? ? const selectDom = ev.currentTarget; ? ? ? ? ? ? const {clientWidth, clientHeight} = document.body; ? ? ? ? ? ? const {offsetLeft, offsetTop} = selectDom; ? ? ? ? ? ? selectDom.style.left =? ? ? ? ? ? ? ? ? (offsetLeft + 50) > (clientWidth / 2) ?? ? ? ? ? ? ? ? ? 'calc(100% - 100px)' : 0; ? ? ? ? ? ? if (offsetTop < 90) { ? ? ? ? ? ? ? ? selectDom.style.top = '90px'; ? ? ? ? ? ? } else if (offsetTop + 36 > clientHeight) { ? ? ? ? ? ? ? ? selectDom.style.top = `${clientHeight - 36}px`; ? ? ? ? ? ? } ? ? ? ? ? ? this.btnType =? ? ? ? ? ? ? ? ? (offsetLeft + 50) > (clientWidth / 2) ?? ? ? ? ? ? ? ? ? 'right' : 'left'; ? ? ? ? } ? ? }, }; </script>
三、頁面引入:
單個(gè)頁面引入
<template> ?? ?<floatBtn/> </template>
<script> import floatBtn from './floatBtn'; export default { ? ? components: { ? ? ? ? floatBtn ? ? }, }; </script>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue如何監(jiān)聽頁面的滾動(dòng)的開始和結(jié)束
這篇文章主要介紹了vue如何監(jiān)聽頁面的滾動(dòng)的開始和結(jié)束,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07vue解析Json數(shù)據(jù)獲取Json里面的多個(gè)id問題
這篇文章主要介紹了vue解析Json數(shù)據(jù)獲取Json里面的多個(gè)id問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12淺談vue+webpack項(xiàng)目調(diào)試方法步驟
本篇文章主要介紹了淺談vue+webpack項(xiàng)目調(diào)試方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09詳解vue服務(wù)端渲染瀏覽器端緩存(keep-alive)
在使用服務(wù)器端渲染時(shí),除了服務(wù)端的接口緩存、頁面緩存、組建緩存等,瀏覽器端也避免不了要使用緩存,減少頁面的重繪。這篇文章主要介紹了詳解vue服務(wù)端渲染瀏覽器端緩存(keep-alive),感興趣的小伙伴們可以參考一下2018-10-10關(guān)于移動(dòng)端與大屏幕自適應(yīng)適配方案
這篇文章主要介紹了關(guān)于移動(dòng)端與大屏幕自適應(yīng)適配方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Vue項(xiàng)目打包優(yōu)化實(shí)踐指南(推薦!)
如果引入的庫眾多,那么vendor.js文件體積將會(huì)相當(dāng)?shù)拇?影響首開的體驗(yàn),這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目打包優(yōu)化實(shí)踐的相關(guān)資料,需要的朋友可以參考下2022-06-06