Reputation: 9825
I've gone ahead and implemented a drag feature for my image that should move the image in whichever direction you drag the image. I;m not sure whats wrong with it, if its slow and needs to be throttled, if my maths off, or I'm just plain doing something wrong. I made a minimal viable example. Any help would be really appreciated.
<div class="img-cntnr">
<img class="my-img" src="http://www.fillmurray.com/g/900/900" alt="" />
</div>
.img-cntnr {
position: relative;
border: dodgerBlue solid 20px;
width: 500px;
height: 500px;
overflow: hidden;
}
.img-cntnr img {
position: absolute;
left: 50%;
transform: translateX(-50%);
top: 0;
bottom: 0;
margin: auto;
cursor: -webkit-grab;
}
var images = document.getElementsByClassName('my-img');
var imgCntnrs = document.getElementsByClassName('img-cntnr');
var dragImgMouseStart = {};
var imgCntnrH;
var imgCntnrW;
function mousedownDragImg(e) {
dragImgMouseStart.x = e.pageX;
dragImgMouseStart.y = e.pageY;
imgCntnrH = imgCntnrs[0].offsetHeight;
imgCntnrW = imgCntnrs[0].offsetWidth;
// add listeners for mousemove, mouseup
window.addEventListener('mousemove', mousemoveDragImg);
window.addEventListener('mouseup', mouseupDragImg);
}
function mousemoveDragImg(e) {
var diffX = -1 * (dragImgMouseStart.x - e.pageX);
var diffY = -1 * (dragImgMouseStart.y - e.pageY);
var oldLeft = isNaN(parseFloat(images[0].style.left)) ? 0 : parseFloat(images[0].style.left);
var newLeft = oldLeft + diffX / imgCntnrW;
images[0].style.left = newLeft + '%';
var oldTop = isNaN(parseFloat(images[0].style.top)) ? 0 : parseFloat(images[0].style.top);
var newTop = oldTop + diffY / imgCntnrH;
images[0].style.top = newTop + '%';
console.log(newLeft, newTop);
}
function mouseupDragImg(e) {
window.removeEventListener('mousemove', mousemoveDragImg);
window.removeEventListener('mouseup', mouseupDragImg);
}
for (var i = images.length - 1; i >= 0; i--) {
// make images unselectable
images[i].ondragstart = function() {
return false;
};
};
images[0].addEventListener('mousedown', mousedownDragImg);
Upvotes: 1
Views: 315
Reputation: 26161
There were a few rectifications needed in your code.
requestAnimationFrame()
. Then i had to refactor the code for a better performance. Moving DOM objects are best done by CSS3 transform: translate(x,y);
transform: translate(x,y);
CSS property as we move the mouse. So we only need this CSS property's initial values. Since you have chosen to center the over-sized image horizontally by doing left: 50%;
(first move the image to the right up until it's left edge is at the containing div's half width) then transform: translateX(-50%);
(move the image to the left as much as haft of it's width) we can easily see that our translateX
value is half of the image width (-50%). The translateY
value has never been modified so it remains as 0. I have changed this property into transform: translate(-50%, 0);
for consistency. Well, now lets calculate our initial x
value for the translate(x,y)
. The image.getBoundingClientRect()
tool is very useful to get the width of the image
element in integers.So please see the below snippets for the rest. It's pretty self explanatory.
Also at JSBin and CodePen
https://jsbin.com/bawalebowi/1/edit?css,js,output
http://codepen.io/omerillo/pen/EKWOZQ
var image = document.getElementsByClassName('my-img')[0],
imgCntnrs = document.getElementsByClassName('img-cntnr'),
dragImgMouseStart = {},
lastDiff = {x:0, y:0},
initialPos = image.getBoundingClientRect(),
currentPos = {x: -initialPos.width/2, y: 0};
function mousedownDragImg(e) {
e.preventDefault();
dragImgMouseStart.x = e.clientX;
dragImgMouseStart.y = e.clientY;
currentPos.x += lastDiff.x;
currentPos.y += lastDiff.y;
lastDiff = {x: 0, y: 0};
window.addEventListener('mousemove', mousemoveDragImg);
window.addEventListener('mouseup', mouseupDragImg);
requestAnimationFrame(function(){
image.style.transform = "translate(" + (currentPos.x + lastDiff.x) + "px," + (currentPos.y + lastDiff.y) + "px)";
});
}
function mousemoveDragImg(e) {
e.preventDefault();
lastDiff.x = e.clientX - dragImgMouseStart.x;
lastDiff.y = e.clientY - dragImgMouseStart.y;
requestAnimationFrame(function(){
image.style.transform = "translate(" + (currentPos.x + lastDiff.x) + "px," + (currentPos.y + lastDiff.y) + "px)";
});
}
function mouseupDragImg(e) {
e.preventDefault();
window.removeEventListener('mousemove', mousemoveDragImg);
window.removeEventListener('mouseup', mouseupDragImg);
}
image.addEventListener('mousedown', mousedownDragImg);
.img-cntnr {
position: relative;
border: dodgerBlue solid 10px;
border-radius: 10px;
width: 250px;
height: 250px;
overflow: hidden;
margin: 0;
padding:0;
}
.img-cntnr img {
position: absolute;
left: 50%;
transform: translate(-50%, 0);
top: 0px;
bottom:0px;
margin: auto;
padding: 0;
cursor: -webkit-grab;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="img-cntnr">
<img class="my-img" src="http://www.fillmurray.com/g/900/900" alt="" />
</div>
</body>
</html>
Upvotes: 1