Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOM基础测试48期 #78

Open
zhangxinxu opened this issue May 29, 2020 · 5 comments
Open

DOM基础测试48期 #78

zhangxinxu opened this issue May 29, 2020 · 5 comments

Comments

@zhangxinxu
Copy link
Owner

移动端,页面上A,B两个div元素,请实现:

拖拽A元素到B元素上,A元素append到B元素中。


本题考点在于移动端的拖拽功能实现。大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。

```js
// 你的JS代码写在这里
 ```

其他
本期小测没有直播,也没有打分,但是会反馈要点。

@liyongleihf2006
Copy link
Contributor

liyongleihf2006 commented May 30, 2020

jsbin

#draggable {
  width: 200px;
  height: 20px;
  text-align: center;
  background: white;
}

#dropzone {
  position: absolute;
  top: 300px;
  width: 200px;
  height: 20px;
  background: blueviolet;
  margin-bottom: 10px;
  padding: 10px;
}

.abs {
  position: absolute;
  z-index: 1;
}
<div id="draggable">
  被拖拽的元素
</div>
<div id="dropzone"></div>
var draggable = document.querySelector('#draggable')
var dropzone = document.querySelector('#dropzone')
var { width, height } = draggable.getBoundingClientRect()
var hasTouch = false
draggable.addEventListener('touchstart', touchstart)
document.addEventListener('touchmove', touchmove)
draggable.addEventListener('touchend', touchend)
draggable.addEventListener('touchcancel', reset)

function touchstart() {
  hasTouch = true
  draggable.classList.add('abs')
}
function touchmove(e) {
  if (hasTouch) {
    var touch = e.changedTouches[0]
    var pageX = touch.pageX
    var pageY = touch.pageY
    Object.assign(draggable.style, {
      left: pageX - width / 2 + 'px',
      top: pageY - height / 2 + 'px'
    })
  }
}
function touchend(e) {
  hasTouch = false
  var touch = e.changedTouches[0]
  var pageX = touch.pageX
  var pageY = touch.pageY
  var elements = document.elementsFromPoint(pageX, pageY)
  if (elements.includes(dropzone)) {
    dropzone.appendChild(draggable)
    draggable.removeEventListener('touchstart', touchstart)
    document.removeEventListener('touchmove', touchmove)
    draggable.removeEventListener('touchend', touchend)
    draggable.removeEventListener('touchcancel', reset)
  }
  reset()
}
function reset() {
  draggable.classList.remove('abs')
  Object.assign(draggable.style, {
    left: '',
    top: ''
  })
}

@xxf1996
Copy link

xxf1996 commented May 31, 2020

移动端可以使用touchEvent来处理拖拽操作;

demo

<div id="t1">A</div>
<div id="t2">B</div>
body {
  max-width: 400px;
}
#t1 {
  width: 100px;
  height: 100px;
  background-color: lightcoral;
}
#t2 {
  min-height: 200px;
  margin-top: 30px;
  background-color: lightcyan;
}
const A = document.getElementById('t1')
const B = document.getElementById('t2')
let first = null

function start (e) {
  first = e.touches[0]
}

function move (e) {
  const cur = e.touches[0]
  if (first) {
    A.style.transform = `translate(${cur.pageX - first.pageX}px, ${cur.pageY - first.pageY}px)`
  }
}

function end (e) {
  const boxA = A.getBoundingClientRect()
  const boxB = B.getBoundingClientRect()

  if ( boxA.left > boxB.left
      && boxA.top > boxB.top
      && boxA.right < boxB.right
      && boxA.bottom < boxB.bottom ) { // 判断拖放停止的位置是否完全处于B之中
    A.removeEventListener('touchstart', start)
    A.removeEventListener('touchmove', move)
    A.removeEventListener('touchend', end)
    B.appendChild(A)
  }
  A.style.transform = 'none'
}

A.addEventListener('touchstart', start)
A.addEventListener('touchmove', move)
A.addEventListener('touchend', end)

@ziven27
Copy link

ziven27 commented May 31, 2020

在线DEMO: jsbin

并没有实现 移动中的效果,只判断结束时候的状态

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <style>
    .ele{
      min-height: 100px;
      background-color:rgba(255,0,0,0.4);
      padding:8px;
    }
  </style>
</head>
<body>
 <div draggable="true" class="ele" id="eleA"></div>
 <hr>  
 <div class="ele" id="eleB"></div>
</body>
</html>
var eleA = document.getElementById("eleA");
var eleB = document.getElementById("eleB");
document.addEventListener("touchend", function (e) {
  // 移动的是 A 元素,并且A 元素不在B元素之内
  if (e.target === eleA && !eleB.contains(eleA)) {
    var objTouch = e.changedTouches[0];
    var rect = eleB.getBoundingClientRect();
    var xIn = objTouch.clientX < rect.right && objTouch.clientX > rect.left;
    var yIn = objTouch.clientY < rect.bottom && objTouch.clientY > rect.top;
    xIn && yIn && eleB.appendChild(eleA);
  }
});

@livetune
Copy link

DEMO

  <div class="a"> </div>
  <div class="b"></div>
let inDrag = false, timer = null, touchpos = { x: 0, y: 0 }
  const a = document.querySelector('.a'), b = document.querySelector('.b')
  b.addEventListener('touchstart', (e) => {
    const { pageX, pageY } = e.changedTouches[0];
    timer = setTimeout(() => {
      inDrag = true
      touchpos.x = pageX
      touchpos.y = pageY
      b.style.opacity = '.5'
    }, 50)
  })
  b.addEventListener('touchend', (e) => {
    if (!inDrag) {
      return
    }
    // 防止 elementFromPoint 拿到b
    b.style.display = 'none'
    clearTimeout(timer)
    const { pageX, pageY } = e.changedTouches[0];
    let isIna = false,
      element = document.elementFromPoint(pageX, pageY);
    while (element && element.parentElement) {
      if (element.classList.contains('a')) {
        isIna = true
        break
      }
      element = element.parentElement
    }
    if (isIna) {
      a.appendChild(b)
    } else {
      document.body.appendChild(b)
    }
    inDrag = false
    // 还原
    b.style.display = ''
    b.style.transform = ''
    b.style.opacity = ''
  })
  b.addEventListener('touchmove', (e) => {
    if (!inDrag) {
      return
    }
    e.preventDefault()
    e.stopPropagation()
    const { pageX, pageY } = e.changedTouches[0]
    b.style.transform = `translate(${-touchpos.x + pageX}px,${-touchpos.y + pageY}px)`
  })

@zer0fire
Copy link

zer0fire commented Jun 1, 2020

Demo

    div {
      background-color: rgba(0,0,0,0.08);
      border: 1px solid
    }
    #dragable {
      height: 100px;
      width: 100px;
    }
    #container {
      height: 200px;
      width: 200px;
    }
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <div id="dragable">可拖动</div>
  <div id="container"></div>
</body>
</html>
    let dragable = document.getElementById('dragable'),
        container = document.getElementById('container')
    // console.log(dragable, container)
    dragable.addEventListener('touchend', (e) => {
      let b = container.getBoundingClientRect()
      // console.log(a, b)
      // console.log(e.touches, e.changedTouches, e.targetTouches)
      let touches = e.changedTouches[0]
      console.log(e.changedTouches)
      if(
        touches.clientX > b.left &&
        touches.clientX < b.right &&
        touches.clientY > b.top &&
        touches.clientY < b.bottom
      ) {
        container.appendChild(dragable)
      }
    })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants