• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • YouClaw
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
邹天得
博客园    首页    新随笔    联系   管理    订阅  订阅

原生JavaScript实现简单的鼠标拖拽效果

不使用html5中支持的draggable属性和drag时间,使用原生JavaScript实现拖拽效果

http://www.qdfuns.com/notes/19044/b3c57594c1f1b220f1a102d4e9147828.html

 

之前在聊天群里看到有人说面试的时候被问到了怎样实现一个拖拽效果,当时看到后在心里默默思考了下,结果发现好像我也写不出来啊。本着遇到一个解决一个的思想,就亲自敲了一个,看到张鑫旭大神写的代码,真的很厉害,多多学习了,(感觉随便搜一个关于前端方面的问题都能看到他的网站,真是太佩服了,写了那么多文章,十分感谢。)
好了,接下来就进入正题了。
想实现一个效果首先得明白其中的逻辑,知道了实现逻辑后,就可以码代码了。
首先我实现的效果是:

  1. 鼠标按下后,才可以执行后续效果
  2. 鼠标已经按下,然后鼠标移动,需要拖拽的元素跟着一起移动
  3. 鼠标松开,然后停止移动


大步骤就是这样一个过程,其实对应的就是三个事件:

  1. onmousedown
  2. onmousemove
  3. onmouseup


然后我们来看这三个事件发生时分别作做什么事。

当鼠标按下时,我们得记录当前元素的位置newSite。同时设置一个标记,用于表示此时鼠标时按下的状态,方便鼠标移动事件的执行。
当鼠标松开时,我们要将标记改变,说明此时鼠标松开了,当鼠标移动时就不能再移动元素了。
当鼠标按下并且移动时,我们就要记录鼠标每次移动的位置currentSite,currentSite和newSite的差值就是鼠标移动的距离,同时也是元素应该移动的距离,然后设置元素的位置就OK了。

当然有个很重要的点就是需要移动的元素的position属性应该设为absolute或者relative,这样元素才可以移动。
同时,如果该元素内部有可能导致浏览器默认事件发生的元素时,要阻止默认事件的发生,例如里面有一个图片时,点击拖动的时候浏览器会默认弹出一个新窗口显示该图片,这时我们应该阻止这个事件的发生。具体方式可以查看代码。

<!DOCTYPE html>
<html>
<head>
    <title>图片拖动</title>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="./css/style.css">
    <style type="text/css">
    #content {
        position: relative;
        width: 300px;
        height: 200px;
        top: 100px;
        left: 100px;
        background: orange;
        cursor: move;
    }
    </style>
</head>

<body>
    <div id="content">
        <img src="./images/3.jpg">
    </div>
    <script type="text/javascript" src="./js/drag.js"></script>
    <script>
    window.onload = function() {
        var content = document.getElementById("content");
        startDrag(content);
    }
    </script>
</body>

</html>
// 参数列表
var params = {
    left: 0,
    top: 0,
    currentX: 0,
    currentY: 0,
    flag: false
};
//获取相关CSS属性
var getCss = function(o, key) {
    // getComputedStyle是为了兼容FF浏览器
    return o.currentStyle ? o.currentStyle[key] : document.defaultView.getComputedStyle(o, false)[key];
};

//拖拽的实现
var startDrag = function(target, callback) {
    // 首先获取目标元素的left、top属性值
    if (getCss(target, "left") !== "auto") {
        params.left = getCss(target, "left");
    }
    if (getCss(target, "top") !== "auto") {
        params.top = getCss(target, "top");
    }
    
    target.onmousedown = function(event) {
        // 当鼠标按下时表示元素可以移动,将标记设为true;
        params.flag = true;
        
        /*为了阻止拖动浏览器中元素时发生默认事件,
        例如拖动图片时会出现一个新窗口显示该图片,下面代码可以阻止这种事件发生
        */
        if (event.preventDefault) {
            event.preventDefault();
        }else {
            event.returnValue = false;
        }
        
        var e = event;
        params.currentX = e.clientX;
        params.currentY = e.clientY;
    };
    target.onmouseup = function() {
        // 当鼠标松开时将标记设为false,表示不可移动
        params.flag = false;
        // 当鼠标松开时再次更新元素的位置
        if (getCss(target, "left") !== "auto") {
            params.left = getCss(target, "left");
        }
        if (getCss(target, "top") !== "auto") {
            params.top = getCss(target, "top");
        }
    };
    target.onmousemove = function(event) {
        var e = event ? event : window.event;
        /*当params.flag==true时才可以移动,表明此时鼠标时按下状态
        */
        if (params.flag) {
            // 获取到当前鼠标的位置
            var nowX = e.clientX,
                nowY = e.clientY;
            // 获取当前鼠标移动的距离,即当前鼠标位置减去初始位置
            var disX = nowX - params.currentX,
                disY = nowY - params.currentY;
            // 将元素的位置更新,parsenInt为了将属性值变为数字类型
            target.style.left = parseInt(params.left) + disX + "px";
            target.style.top = parseInt(params.top) + disY + "px";
        }
    }
};

 

posted on 2017-07-27 16:51  邹天得  阅读(259)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3