我在容器内有一个可拖动元素,并且仅限于其边界。我使用 InteractJs 来实现这一点。可拖动元素默认隐藏,并在触摸开始时变得可见。
但是我想让可拖动元素跟随用户的光标/触摸位置,以便它可以出现在第一个用户单击/触摸的位置的正下方,然后在拖动/触摸移动时跟随它并在触摸结束时消失。
您能否告诉我如何修改我的代码以实现这种行为?我尝试将
transform
样式属性与 touchstart 的坐标一起应用,但没有成功。
示例: https://codepen.io/moogeek/pen/oNQWwaN
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.17/interact.min.js"></script>
<style>
body{padding-top:100px;}
.container {
width:368px;
height:120px;
background-color:red;
margin:0 auto;
z-index:2
}
.draggable {
visibility:hidden;
height:60px;
width:80px;
background-color:#fff;
display:inline-block;
touch-action:none;
z-index:1;
}
</style>
</head>
<body>
<div class="container">
<div class="draggable"></div>
</div>
</body>
</html>
js:
let dragMoveListener=(event) => {
let draggable=document.getElementsByClassName("draggable")[0],
target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
draggable.style.visibility='visible';
target.style.backgroundPosition=x + 'px ' + y + 'px';
target.style.webkitTransform = target.style.transform
= 'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
let draggables=document.querySelectorAll(".draggable"),
containers=document.querySelectorAll(".container");
containers.forEach(function(element){
interact(element).on("tap down",function(e){
var wt=element.querySelector('.draggable');
var wect=wt.getBoundingClientRect();
wt.style.visibility='visible';
});
});
draggables.forEach(function(element){
interact(element)
.on("dragstart",function(e){
var x=element.getAttribute("data-x");
var y=element.getAttribute("data-y");
if(x!=null && y!=null){
//draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
}
}).
on("dragmove",function(e){
})
.on("dragend",function(e){
element.style.visibility='hidden';
//draggable.webkitTransform = draggable.style.transform = 'translate(0px, 0px)';
}).draggable({
onmove: dragMoveListener,
modifiers: [
interact.modifiers.restrict({
restriction: 'parent',
endOnly: false
})
]})
});
要实现这一目标,你可以尝试这个。
请参阅下面的演示
let dragMoveListener = (event) => {
let draggable = document.querySelector(".draggable"),
follower = document.querySelector(".follower"),
target = event.target,
x = event.clientX,
y = event.clientY;
follower.style.visibility = 'visible';
follower.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
target.style.backgroundPosition = x + 'px ' + y + 'px';
};
let containers = document.querySelectorAll(".container");
containers.forEach(function (element) {
interact(element).on("tap down", function (e) {
var wt = element.querySelector('.draggable');
var wect = wt.getBoundingClientRect();
var follower = element.querySelector('.follower');
// Set the position of the follower element to the position of the user's click/touch
var x = e.clientX - wect.left;
var y = e.clientY - wect.top;
follower.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
follower.style.visibility = 'visible';
});
});
containers.forEach(function (element) {
interact(element)
.on("dragstart", function (e) {
var x = element.getAttribute("data-x");
var y = element.getAttribute("data-y");
if (x != null && y != null) {
//draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
}
})
.on("dragmove", dragMoveListener)
.on("dragend", function (e) {
var draggable = document.querySelector(".draggable");
var follower = document.querySelector(".follower");
draggable.style.visibility = 'hidden';
follower.style.visibility = 'hidden';
//draggable.webkitTransform = draggable.style.transform = 'translate(0px, 0px)';
})
.draggable({
onmove: dragMoveListener,
modifiers: [
interact.modifiers.restrict({
restriction: 'parent',
endOnly: false
})
]
});
});
.container {
width: 300px;
height: 300px;
position: relative;
background-color: red;
}
.draggable {
width: 100px;
height: 100px;
background-color: #fff;
color: white;
text-align: center;
line-height: 100px;
user-select: none;
cursor: move;
position: absolute;
top: 0;
left: 0;
visibility: hidden;
}
.follower {
width: 100px;
height: 100px;
background-color: #fff;
opacity: 1;
position: absolute;
top: 0;
left: 0;
visibility: hidden;
}
<!DOCTYPE html>
<html>
<head>
<title>Draggable Element</title>
</head>
<body>
<div class="container">
<div class="draggable">Draggable Element</div>
<div class="follower"></div>
</div>
<script src="https://unpkg.com/interactjs"></script>
</body>
</html>
我已经修改了您的代码来执行您正在寻找的操作,但我建议您可以在普通的 JavaScript 中实现相同的结果,这将消除使用库的开销。请参阅MDN 拖放。
此外,如果您要拥有此示例的多个实例,您可能应该使用
event.target
而不是全局变量。
JS
let dragMoveListener = (event) => {
let draggable = document.getElementsByClassName("draggable")[0],
target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx,
y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;
//draggable.style.visibility = "visible";
target.style.backgroundPosition = x + "px " + y + "px";
target.style.webkitTransform = target.style.transform =
"translate(" + x + "px, " + y + "px)";
// update the posiion attributes
target.setAttribute("data-x", x);
target.setAttribute("data-y", y);
};
let draggables = document.querySelectorAll(".draggable"),
containers = document.querySelectorAll(".container");
containers.forEach(function (element) {
interact(element).on("tap down", function (e) {
const dragElem = element.querySelector(".draggable");
const dragBCR = dragElem.getBoundingClientRect();
const contBCR = element.getBoundingClientRect();
if (
dragBCR.left < e.x && e.x < dragBCR.right &&
dragBCR.top < e.y && e.y < dragBCR.bottom &&
!( contBCR.top == dragBCR.top && contBCR.left == dragBCR.left )
) return true;
dragElem.setAttribute("data-x", e.x - contBCR.x);
dragElem.setAttribute("data-y", e.y - contBCR.y);
dragMoveListener({ target: dragElem, dx: 0, dy: 0 });
dragElem.style.visibility = "visible";
});
});
draggables.forEach(function (element) {
interact(element)
.on("dragstart", function (e) {
var x = element.getAttribute("data-x");
var y = element.getAttribute("data-y");
if (x != null && y != null) {
//draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
}
})
.on("dragmove", function (e) {})
.on("dragend", function (e) {
const contElem = element.closest(".container");
const contBCR = contElem.getBoundingClientRect();
element.style.visibility = "hidden";
element.setAttribute("data-x", 0);
element.setAttribute("data-y", 0);
dragMoveListener({ target: element, dx: 0, dy: 0 });
})
.draggable({
onmove: dragMoveListener,
modifiers: [
interact.modifiers.restrict({
restriction: "parent",
endOnly: false
})
]
});
});