vue实现全局拖拽按钮,修复Uniapp版

  • 按钮样式
<template>
    <!--  子组件 -->
    <view class="float_button">
        <!-- :style="{'width': itemWidth + 'px','margin':'5px 10px', 'height': itemHeight + 'px', 'left': left + 'px', 'top': top + 'px'}"-->
        <view
                id="btnHome"
                @click="onBtnClicked"
                ref="floatButton"
                class="float_info"
                :style="{'left': left + 'px', 'top': top + 'px','opacity':opacity, }">
            <view class="text">
                <u-icon name="home-fill" color="#ffffff" size="24"></u-icon>
                <text>首页</text>
            </view>
        </view>
    </view>
</template>
<script>
    let mySelf;
    var mo=function(e){e.preventDefault();};
    function stop(){
        document.body.style.overflow='hidden';
        document.addEventListener("touchmove",mo,{passive:false});//禁止页面滑动
    }

    /***取消滑动限制***/
    function move(){
        document.body.style.overflow='';//出现滚动条
        document.removeEventListener("touchmove",mo,{passive:false});
    }

    export default {

        data() {
            return {
                clientWidth: 0,
                clientHeight: 0,
                timer: null,
                currentTop: 0,
                left: 0,
                top: 0,

                itemWidth: 54,  //按钮宽度
                isShort: true,
                itemHeight: 54, // 悬浮按钮高度
                gapWidth: 5,    // 距离左右两边距离
                coefficientHeight: 0.6,  // 从上到下距离比例

                opacity:0.5,


            }
        },
        props: {},
        computed: {},
        created() {
            // console.log('屏幕宽度', document.documentElement.clientWidth)
            // console.log('屏幕高度度', document.documentElement.clientHeight)
            let type = navigator.userAgent;

            // console.log('设备', type)

            this.clientWidth = document.documentElement.clientWidth
            this.clientHeight = document.documentElement.clientHeight
            // this.left = this.clientWidth - this.itemWidth - this.gapWidth - 20;
            this.left = this.clientWidth - this.itemWidth - this.gapWidth;
            this.top = this.clientHeight * this.coefficientHeight
        },
        watch: {
            left(n, o) {


            }
        },
        methods: {
            onBtnClicked() {
                console.log('点击了按钮--->',11)
                uni.reLaunch({
                    url: "/index-new/index",
                });
            },

            handleScrollStart() {
                console.log('这是啥时候触发呀?ScrollStart')
                this.timer && clearTimeout(this.timer)
                this.timer = setTimeout(() => {
                    this.handleScrollEnd()
                }, 300)
                this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
                if (this.left > this.clientWidth / 2) {
                    this.left = this.clientWidth - this.itemWidth / 2
                } else {
                    this.left = -this.itemWidth / 2
                }
            },
            handleScrollEnd() {
                let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
                if (scrollTop === this.currentTop) {
                    if (this.left > this.clientWidth / 2) {
                        this.left = this.clientWidth - this.itemWidth - this.gapWidth
                    } else {
                        this.left = this.gapWidth
                    }
                    clearTimeout(this.timer)
                }
            },

        },
        mounted() {

            mySelf = this;
            this.$nextTick(() => {

                let floatButton = document.getElementById("btnHome");
                console.log('floatButton--->',floatButton);


                if (floatButton){

                    floatButton.addEventListener("touchstart", () => {
                        floatButton.style.transition = 'none'
                        mySelf.opacity = 1
                    });

                    // 在拖拽的过程中,组件应该跟随手指的移动而移动。
                    floatButton.addEventListener("touchmove", (e) => {
                        // console.log('移动中', e)
                        if (e.targetTouches.length === 1) {         // 一根手指

                            stop();//禁止页面滑动
                            let touch = e.targetTouches[0]
                            // this.left = touch.clientX - 20

                            let maxX = this.clientWidth - touch.clientX;
                            if (maxX <= 50) {
                                this.left = this.clientWidth - 50;//禁止超出屏幕外
                            }else {
                                this.left = touch.clientX - this.gapWidth;
                            }

                            // this.left = touch.clientX - this.gapWidth;//原来的
                            if (this.left <=0) this.left = 0

                            let maxY = this.clientHeight - touch.clientY;
                            if (maxY <= 50) {
                                this.top = this.clientHeight - 75;//禁止超出屏幕外
                            }else {
                                this.top = touch.clientY - 25//原来的
                            }
                            if (this.top <=0) this.top = 0



                        }

                    });

                    // 拖拽结束以后,重新调整组件的位置并重新设置过度动画。
                    floatButton.addEventListener("touchend", () => {
                        floatButton.style.transition = 'all 0.3s'
                        console.log('拖拽结束后left', this.left,'clientHeight-->',this.clientHeight)

                        //3秒后变透明
                        setTimeout(()=>{
                            mySelf.opacity = 0.5
                        },3000);

                        move();//解除页面禁止滑动
                        if (this.left > document.documentElement.clientWidth / 2) {
                            // this.left = document.documentElement.clientWidth - this.itemWidth - 20;
                            this.left = document.documentElement.clientWidth - this.itemWidth - this.gapWidth;

                        } else {
                            this.left = 0
                        }
                    });
                }

            })

        },
        beforeDestroy() {
            // 添加监听页面滚动
            window.removeEventListener('scroll', this.handleScrollStart)
        },
        destroyed() {
        }
    }
</script>
<style lang="scss" scoped>
    .float_button {
        .float_info {
            box-shadow: #1666ca;
            transition: all 0.3s;
            position: fixed;
            bottom: 436px;
            right: 0;
            display: flex;
            flex-flow: row;
            justify-content: center;
            align-items: center;
            z-index: 999;
            border-radius: 12px;
            cursor: pointer;

            background: rgb(146, 146, 146);
            width: 54px !important;
            height: 54px !important;
            opacity: 0.5;

            .text {
                font-size: 12px;
                color: #fff;
            }
        }
    }
</style>

  • 全局注册 main.js
import FloatingButton from '@/components/floatingButton.vue';
Vue.component('FloatingButton', FloatingButton)
  • 页面调用
 <FloatingButton />
  • 原生写法

<html>

<style>
            
            #float_info {
                box-shadow: #1666ca;
                transition: all 0.3s;
                position: fixed;
                bottom: 436px;
                right: 0;
                display: flex;
                flex-flow: row;
                justify-content: center;
                align-items: center;
                z-index: 999;
                border-radius: 12px;
                cursor: pointer;

                background: rgb(146, 146, 146);
                width: 54px !important;
                height: 54px !important;
                opacity: 0.5;
            }
            .text-home{
                color: #ffffff;
                font-size: 14px;
            }


        </style>
                <div id="homeBtn">
            <div id="float_info">
                <div class="text">
                    <div style="width: 22px;height: 22px;color: white; position: relative; left: 3px;">
                        <svg xmlns="http://www.w3.org/2000/svg"
                             viewBox="0 0 1024 1024">
                            <path fill="currentColor"
                                  d="M512 128 128 447.936V896h255.936V640H640v256h255.936V447.936z">
                            </path>
                        </svg>
                    </div>
                    <div class="text-home">首页</div>
                </div>
            </div>
        </div>
</html>
<script>
            let w = '54px';
            let h = '54px';
            let gapWidth = 5;
            let itemWidth = 54;
            let clientWidth = document.documentElement.clientWidth  // 获取手机的像素宽度
            let clientHeight = document.documentElement.clientHeight// 获取手机的像素高度

            let div = document.getElementById('float_info');
            // let div = document.createElement('div');
            // div.style.opacity = 0.5 ;
            // // div.style.boxShadow = '0px 0px 0px 0.5em #e0e1e9' ;
            // div.style.width = w;
            // div.style.height = h;
            // // div.style.left = clientWidth - 50+'px';
            // div.style.left = clientWidth - itemWidth - gapWidth+'px';
            // console.log("初始位置left"+div.style.left)
            // div.style.top = clientHeight * 0.6+'px';
            // // div.style.zIndex = '100000';
            // // div.style.position= 'fixed';
            // // div.style.background = 'red';
            //
            // div.style.transition='all 0.3s';
            // // div.style.bottom='436px';
            // // div.style.right= 0;
            // // div.style.margin='5px 10px';
            // // div.style.background='rgb(197 203 211)'
            // // div.style.borderRadius = '15px';
            // document.body.appendChild(div);
            // var divattr = document.createAttribute("id");
            // divattr.value = "float_info";
            // //把属性id = "float_info"添加到div
            // div.setAttributeNode(divattr);

            let flag = 0; //标记是拖曳还是点击
            var oDiv = document.getElementById('float_info');
            div.style.left = clientWidth - itemWidth - gapWidth  +'px';
            // oDiv.style.display = 'block'; // 显示元素
            oDiv.addEventListener("touchstart", () => {
                flag = 0;
                oDiv.style.transition = 'none'
                div.style.opacity = 1;
            })

            // 在拖拽的过程中,按钮应该跟随鼠标的移动而移动。
            oDiv.addEventListener("touchmove", (e) => {
                flag=1
                console.log('移动中', e)
                if (e.targetTouches.length === 1) {  // 一根手指
                    e.preventDefault();// 阻止默认的滚动行为
                    let touch = e.targetTouches[0];
                    // div.style.left = e.targetTouches[0].clientX-20 +'px';//clientX:触摸目标在视口中的x坐标。

                    let maxX = clientWidth - touch.clientX;
                    if (maxX <= 50) {
                        div.style.left = clientWidth - 50 +'px';//禁止超出屏幕外
                    }else {
                        div.style.left = touch.clientX - gapWidth +'px';
                        if (touch.clientX <= 5){
                            div.style.left = 0+'px'
                        }
                    }
                    console.log('移动中-->clientWidth-->',clientWidth,
                            'clientX-->',touch.clientX,'maxX-->',maxX )


                    let maxY = clientHeight - touch.clientY;
                    if (maxY <= 50) {
                        div.style.top = clientHeight - 75 +'px';//禁止超出屏幕外
                    }else {
                        div.style.top = touch.clientY - 25 +'px'//原来的
                    }
                    let phrases = div.style.top.split("px"); // 使用逗号作为分隔符
                    // console.log('移动中',
                    //      div.style.left,'clientHeight-->',clientHeight,
                    //      'clientY-->',touch.clientY,
                    //      'div.style.top-->',div.style.top,'phrases-->',phrases)
                    if (Number(phrases[0]) <=0) div.style.top = 0+'px'

                    // div.style.top = e.targetTouches[0].clientY -25 +'px'//clientY:触摸目标在视口中的y坐标。
                    div.style.opacity = 1;

                }
            })

            // 拖拽结束以后,重新调整按钮的位置并重新设置过度动画。
            oDiv.addEventListener("touchend", () => {
                // 如果是点击跳转到首页
                if(flag==0){
                    console.log('点击了按钮--->',1111)
                }else {
                    div.style.transition = 'all 0.3s'
                    console.log('拖拽结束后left', div.style.left)
                    console.log('拖拽结束后top', div.style.top)
                    setTimeout(()=>{
                        div.style.opacity = 0.5;
                    },3000);
                    if ( parseInt(div.style.left)> (document.documentElement.clientWidth / 2)) {
                        // div.style.left = document.documentElement.clientWidth - 50+'px';
                        div.style.left = document.documentElement.clientWidth - itemWidth - gapWidth +'px';
                    } else {
                        div.style.left = 0+'px'
                    }
                    // 控制其超出屏幕回到原始位置
                    if ( parseInt(div.style.top)> (document.documentElement.clientHeight)|| parseInt(div.style.top)<0) {
                        div.style.top = document.documentElement.clientHeight* 0.6+'px'
                    }

                }

            })
        </script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,183评论 6 516
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,850评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,766评论 0 361
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,854评论 1 299
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,871评论 6 398
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,457评论 1 311
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,999评论 3 422
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,914评论 0 277
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,465评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,543评论 3 342
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,675评论 1 353
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,354评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,029评论 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,514评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,616评论 1 274
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,091评论 3 378
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,685评论 2 360

推荐阅读更多精彩内容