I have one draggable element inside container and restricted to its bounds. I use InteractJs to implement this. Draggable element is hidden by default and becomes visible as touch starts.
However I want to make the draggable element to follow the cursor/touch position of the user so that it can appear right under the position of the first users click/touch and then follow it while drag/touchmove and dissapear on touchend.
Could you please advise how can I modify my code to reach such behavior? I've tried to apply the transform
style property with the coordinates of touchstart but no luck.
Example: 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
})
]})
});
To achieve this you can try this.
See the demo below
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>