原生实现html5的拖拽功能 drag and drop

题目

页面内有一个正方形元素 A 以及一个待放置区域 B,实现对其拖拽和放下到 B 区域内,并且改变 B 区域背景颜色 (不可用 html5 原生事件)。

这也是一道腾讯面试题,要求远程编程。

思路

  • 用鼠标的mousedown事件来模拟dragstart

  • 用持续的mousedown事件来模拟drag过程,用event的坐标来改变相关element的坐标

  • 经试验,H5原生是以被拖拽元素在容器元素中的面积达到一半时可以触发drop(待确认),简易版的就不算面积了,以鼠标进入容器中为准,用mouseup事件作为触发条件模拟drop

代码

html部分

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>demo</title>
  <link rel="stylesheet" type="text/css" href="demo.css" />
</head>

<body>
  <div id="div1"></div>
  <div id="div2"></div>

  <script src="demo.js"></script>
</body>
</html>

css部分

#div1{
    width:100px;
    height: 100px;
    margin:200px auto;
    background: olive;
}


#div2{
    width: 200px;
    height: 300px;
    position: absolute;
    left:100px;
    top:500px;
    background: lightpink;
}

js部分

//var _origin = {x: div1.offsetLeft, y:div1.offsetTop}
var _newele = document.createElement('div')

var div1Style = getComputedStyle(div1)

var dropFlag = 0, dragFlag = 0

div1.addEventListener('mousedown', (event) => {

    var _ele = event.target

    _newele.style.width = div1Style.width

    _newele.style.height  = div1Style.height

    _newele.style.backgroundColor = div1Style.backgroundColor

    _newele.style.position = 'absolute'

    _newele.style.left = _ele.offsetLeft + 'px'

    _newele.style.top = _ele.offsetTop + 'px'

    _newele.style.zIndex = 1

    _ele.style.position = 'absolute'

    _ele.style.left = _newele.style.left

    _ele.style.top = _newele.style.top

    _ele.style.margin = '0'

    _ele.style.opacity = .5

    _ele.style.zIndex = 2

    document.body.append(_newele)

    dragFlag = 1

})


div1.addEventListener('mouseup', (event) => {

    dragFlag = 0

    console.log(dropFlag)
    // 恢复原样,简易版就直接干掉div1,否则应该存储所有的style值,干掉new div,让div1回归原位
    if(!dropFlag){

        document.body.removeChild(div1)
    }

    else{

        console.log('now drop in div2')

        div2.style.backgroundColor = '#ccc000'
    }
})

div1.addEventListener('mousemove',(event) => {

    if(!dragFlag) return false;

    var _ele = event.target

    _ele.style.left = event.clientX  - parseInt(div1Style.width)/2 + 'px'

    _ele.style.top = event.clientY - parseInt(div1Style.height)/2 + 'px'

    if(isEnter({left: event.clientX, top: event.clientY}, div2)){

        dropFlag = 1

        div1.style.cursor = 'copy'
    }

    else{

        dropFlag = 0

        div1.style.cursor = 'move'
    }

})

//mouseenter事件直到mouseup事件触发后才触发,不能用mouseenter了,只能用函数判断鼠标坐标是不是在div2元素的范围内了

function isEnter( point = {left : 0 ,top : 0}, ele ){

    var minLeft = ele.offsetLeft, maxLeft = ele.offsetLeft + ele.offsetWidth

    var minTop = ele.offsetTop, maxTop = ele.offsetTop + ele.offsetHeight

    if( point.left > minLeft && point.left < maxLeft && point.top > minTop && point.top < maxTop){

        //console.log('enter', ele)

        return true
    }  

    return false
}

效果图

忽略那个圆圈,,,那个是录屏软件的。

这里写图片描述

顺带吐个槽,screencastify 还需要load才能使用,不然安装了也不行。最后用的是mac自带的 quicktime

拖拽库

常用的应该是jquery UI 吧。

还有专门的拖放库dnd.js

HTML5的拖拽API

解决完毕,再来了解一下html5的原生api:HTML5魔法堂:全面理解Drag & Drop API - ^_^肥仔John - 博客园

html5的原生事件版本

div1.addEventListener('dragstart',(event) => {

    //event.dataTransfer.setDragImage(img, 20, 20)

    event.dataTransfer.setData('Text', event.target.id)
})

div2.addEventListener('dragenter',(e) => {

    console.log('now enter the div2')
})

div2.addEventListener('dragover',(e) => {

    e.dataTransfer.dropEffect = 'copy' //chrome 下默认就是copy, 也可以对链接用 link 

    e.preventDefault()

})

div2.addEventListener('drop', (e) => {

    var _id = e.dataTransfer.getData('Text')

    e.target.appendChild(document.getElementById(_id))
})

猜你喜欢

转载自blog.csdn.net/github_36487770/article/details/80077294