-
Notifications
You must be signed in to change notification settings - Fork 43
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
Comments
#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: ''
})
} |
移动端可以使用touchEvent来处理拖拽操作; <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) |
在线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);
}
}); |
<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)`
}) |
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
移动端,页面上A,B两个div元素,请实现:
拖拽A元素到B元素上,A元素append到B元素中。
本题考点在于移动端的拖拽功能实现。大家提交回答的时候,注意缩进距离,起始位置从左边缘开始;另外,github自带代码高亮,所以请使用下面示意的格式。
其他
本期小测没有直播,也没有打分,但是会反馈要点。
The text was updated successfully, but these errors were encountered: