上下拖拽元素动效

2,205 阅读2分钟

前言

在工作中实现的一个元素上下拖拽的动效,给大家分享一下,其中用到了本地存储记录拖拽的历史坐标,用EventBus做了拖拽时锁住点击方法(防止用户在拖拽鼠标松开后触发点击事件的方法),大家可根据自己的业务进行扩展修改

效果图

tutieshi_100x494_7s.gif

参数说明

参数说明默认值
el需要被拖拽的元素
value参数配置

value详细参数说明

参数说明默认值
vertical是否允许垂直滚动true
horizontal是否允许水平滚动true
arealimit是否开启边界限制false
margintop拖拽到头部的距离0
marginbottom拖拽到底部的距离0
marginleft拖拽到左边的距离0
marginright拖拽到右边的距离0

vue为例子将方法挂载到mounted

mounted() {
    drag(document.querySelector("#FeedBackPackMove"), {
        horizontal: false,
        arealimit: true,
        margintop: 40,
        marginbottom: 40,
    });
}

挂载EventBus接收拖拽信息

mounted() {
    EventBus.$on('screen',(e) => {
        this.screenX = e.screenX
        this.screenY = e.screenY
    })
    EventBus.$on('isLock',(e) => {
        const deviation =  this.screenY - e.screenY
        if(deviation <= 5 && deviation >= -5){//拖拽移动的范围,这里防止用户鼠标灵敏度太高,误触发点击事件
            this.lock = false
        }else{
            this.lock = true
        }
    })
}

完整vue代码

<template>
<div id="app">
    <div :style="{top:FeedBackPackMove,height:'86px'}" id="FeedBackPackMove"  @click.stop="curFn">
    </div>
    </div>
</template>
​
<script>
    import {EventBus} from "./event-bus"
    import {drag} from './drag'
    export default {
        name: 'App',
        components: {
        },
        data () {
            return {
                FeedBackPackMove:localStorage.getItem('FeedBackPackMove'),//展开的距离
            }
        },
        mounted() {
            drag(document.querySelector("#FeedBackPackMove"), {
                horizontal: false,
                arealimit: true,
                margintop: 40,
                marginbottom: 40,
            });
            EventBus.$on('screen',(e) => {
                this.screenX = e.screenX
                this.screenY = e.screenY
            })
            EventBus.$on('isLock',(e) => {
                const deviation =  this.screenY - e.screenY
                if(deviation <= 5 && deviation >= -5){//拖拽移动的范围,这里防止用户鼠标灵敏度太高,误触发点击事件
                    this.lock = false
                }else{
                    this.lock = true
                }
            })
        },
        methods: {
            //切换菜单
            curFn() {
                if(this.lock) return;//为true移动中,跳出方法
                //切换菜单逻辑
            }
        }
    }
</script>
<style>
    #FeedBackPackMove{
        position:fixed;
        right: 0;
        bottom: 20px;
        width: 30px;
        height: 86px;
        background-color:#0077ff;
    }
</style>

封装好的drag.js文件

/**
 * 元素可拖动方法
 * @param {*} el 需要被拖拽的元素
 * @param {*} value 配置参数
 */
import {EventBus} from "./event-bus"
export const drag = function(el, value = {}){
    const config = {vertical: true, horizontal: true, arealimit: false, margintop: 0, marginbottom: 0, marginleft: 0, marginright: 0, ...value};
    const _el = el;
    _el.onmousedown = e => {
        document.onselectstart = function() {
            return false; //禁止选择网页上的文字
        };
        const disX = e.clientX - _el.offsetLeft; //鼠标按下,计算当前元素距离可视区的距离
        const disY = e.clientY - _el.offsetTop;
        EventBus.$emit('screen',e)//记录点击坐标
        document.onmousemove = function(e) {
            if (config.horizontal) {
                const l = e.clientX - disX;
                if (config.arealimit) {
                    if (l < config.marginleft) {
                        _el.style.left = config.marginleft + 'px';
                    } else if (l >= this.body.clientWidth - config.marginright) {
                        _el.style.left = this.body.clientWidth - config.marginright + 'px';
                    } else {
                        _el.style.left = l + 'px';
                    }
                } else {
                    _el.style.left = l + 'px';
                }
            }
            if (config.vertical) {
                const t = e.clientY - disY;
                const PM = document.querySelector('#FeedBackPackMove');//获取展开按钮元素
                const PMH = parseInt(PM.style.height);//展开按钮元素的高度
                if (config.arealimit) {
                    if (t < config.margintop) {//拉到头部
                        _el.style.top = config.margintop + 'px';
                    } else if (t >= document.documentElement.clientHeight - config.marginbottom - PMH) {//拉到底部,减去元素的高度
                        _el.style.top = document.documentElement.clientHeight - config.marginbottom - PMH + 'px';
                    }else {
                        _el.style.top = t + 'px';
                    }
                    localStorage.setItem('FeedBackPackMove',PM.style.top);//记录拖拽点
                } else {
                    _el.style.top = t + 'px';
                }
            }
        };
        document.onmouseup = e => {
            EventBus.$emit('isLock',e)
            document.onmousemove = document.onmouseup = null;
            document.onselectstart = null;
        };
        return false;
    };
};

event-bus.js文件

import Vue from 'vue'
// 事件总线(用于方便跨组件间的传值)
export const EventBus = new Vue()

结语

这里还有展开收起的过渡动画链接~~~

如果你觉得此文对你有一丁点帮助,麻烦点个赞哈,谢谢大家。