vue实现移动端拖拽悬浮按钮
(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun)
本文实例为大家分享了vue实现移动端拖拽悬浮按钮的具体代码,供大家参考,具体内容如下
功能介绍:
在移动端开发中,实现悬浮按钮在侧边显示,为不遮挡页面内容,允许手指拖拽换位。
大致需求:
1、按钮在页面侧边悬浮显示;
2、手指长按按钮,按钮改变样式,允许拖拽改变位置;
3、按钮移动结束,手指松开,计算距离左右两侧距离并自动移动至侧边显示;
4、移动至侧边后,按钮根据具体左右两次位置判断改变现实样式;
整体思路:
1、按钮实行position:fixed布局,在页面两侧最上层悬浮显示;
2、手指长按可使用定时器来判断,若手指松开,则关闭定时器,等待下次操作再启用;
3、跟随手指移动计算按钮与页面两侧的距离,判断手指松开时停留的位置;
简单效果展示:
具体实现:
一、position:fixed布局:
使用定位实现
<!-- 外层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事件绑定:
应用到touchstart,touchmove,touchend事件,使用定时器实现长按效果:
<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) { ? ? ? ? // 定时器控制长按时间,超过500毫秒开始进行拖拽 ? ? ? ? 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) { ? ? ? ? // 未达到500毫秒就移动则不触发长按,清空定时器 ? ? ? ? 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) { ? ? ? ? // 清空定时器 ? ? ? ? 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>
三、页面引入:
单个页面引入
<template> ?? ?<floatBtn/> </template>
<script> import floatBtn from './floatBtn'; export default { ? ? components: { ? ? ? ? floatBtn ? ? }, }; </script>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持程序员之家。
相关文章
vue-infinite-loading2.0 中文文档详解
本篇文章主要介绍了vue-infinite-loading2.0 中文文档详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-04-04
最新评论