I write a little script to drag a div container. It will works for touch and mouse events.
I have some difficulties to write the momentum script in order to have my container moving after touchend. I know how to calculate a momentum but I don't know what is the right way to implement it...
Here my script :
var divToDrag = $('.container');
var divOnDrag = $(document);
var dragging = false;
var swipe = false;
var scrollY = false;
var threshold = {x:30, y:10};
var swipeLeft = false;
var swipeRight = false;
var swipeUp = false;
var swipeDown = false;
var threshx = false;
var threshy = false;
var maxSpeed = 5;
function prefix() {
styles = window.getComputedStyle(document.documentElement, ''),
pre = (Array.prototype.slice
.call(styles)
.join('')
.match(/-(moz|webkit|ms)-/) || (styles.OLink === '' && ['', 'o'])
)[1],
dom = ('WebKit|Moz|MS|O').match(new RegExp('(' + pre + ')', 'i'))[1];
}
prefix();
function pointerEventXY(e) {
out = {x:0, y:0};
if(e.type == 'touchstart' || e.type == 'touchmove' || e.type == 'touchend'){
touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
out.x = touch.pageX;
out.y = touch.pageY;
} else if (e.type == 'mousedown' || e.type == 'mouseup' || e.type == 'mousemove') {
out.x = e.pageX;
out.y = e.pageY;
}
return out;
};
divOnDrag.on('mousedown touchstart', function(event){
dragging = true;
divToDrag.stop();
pointerEventXY(event);
startCoordsX = prevCoordsX = out.x;
startCoordsY = prevCoordsY = out.y;
divCoordsX = divToDrag.position().left;
divCoordsY = divToDrag.position().top;
initialCoordsX = startCoordsX - divCoordsX;
initialCoordsY = startCoordsY - divCoordsY;
divToDrag.data("mouseEvents",[event]);
})
divOnDrag.on('mousemove touchmove', function(event){
if (dragging == true) {
pointerEventXY(event);
currentCoordsX = out.x;
currentCoordsY = out.y;
xthreshold = Math.abs(currentCoordsX - startCoordsX)
ythreshold = Math.abs(currentCoordsY - startCoordsY)
var mouseEvents = divToDrag.data( "mouseEvents" );
if ((event.timeStamp - mouseEvents[ mouseEvents.length - 1 ].timeStamp ) > 40){
mouseEvents.push(event);
if (mouseEvents.length > 2){
mouseEvents.shift();
}
}
if(xthreshold > threshold.x && ythreshold < threshold.y && scrollY == false || swipe == true ) {
event.preventDefault();
swipe = true;
dragDirection();
x = currentCoordsX - initialCoordsX - threshx;
y = currentCoordsY - initialCoordsY - threshy;
divToDrag.attr('style', '-'+pre+'-transition: all 0s ease-in !important; -'+pre+'-transform: translate3d('+x+'px, 0px, 0px)');
} else if (xthreshold < threshold.x && ythreshold > threshold.y) {
scrollY = true;
}
}
})
divOnDrag.on('mouseup touchend', function(event){
dragging = false;
scrollY = false;
swipe = false;
swipeLeft = false;
swipeRight = false;
swipeUp = false;
swipeDown = false;
momentum();
})
function dragDirection() {
if (prevCoordsX < currentCoordsX) {
swipeRight = true;
threshx = threshold.x;
} else if (prevCoordsX > currentCoordsX) {
swipeLeft = true;
threshx = -threshold.x;
}
if (prevCoordsY < currentCoordsY) {
swipeDown = true;
threshy = threshold.y;
} else if (prevCoordsY > currentCoordsY) {
swipeUp = true;
threshy = -threshold.y;
}
if (swipeRight == true && swipeLeft == true || swipeUp == true && swipeDown == true) {
threshx = 0;
threshy = 0;
prevCoordsX = currentCoordsX - initialCoordsX;
prevCoordsY = currentCoordsY - initialCoordsY;
}
prevCoordsX = currentCoordsX;
prevCoordsY = currentCoordsY;
}
function momentum() {
var lastEvent = divToDrag.data( "mouseEvents" ).shift();
if (!lastEvent){
return;
}
var deltaX = (event.pageX - lastEvent.pageX);
var deltaY = (event.pageY - lastEvent.pageY);
var deltaMS = Math.max((event.timeStamp - lastEvent.timeStamp),1);
var speedX = Math.max(Math.min( (deltaX / deltaMS), maxSpeed ),-maxSpeed);
var speedY = Math.max(Math.min( (deltaY / deltaMS), maxSpeed ),-maxSpeed);
var lastStepTime = new Date();
divToDrag.animate(
{textIndent: 0},
{duration: (Math.max(Math.abs( speedX ), Math.abs( speedY )) * 3000),
step: function( currentStep ){
speedX *= (currentStep / 100);
speedY *= (currentStep / 100);
var now = new Date();
var stepDuration = (now.getTime() - lastStepTime.getTime());
lastStepTime = now;
var position = divToDrag.position();
var newLeft = (position.left + (speedX * stepDuration));
var newTop = (position.top + (speedY * stepDuration));
console.log(newLeft)
divToDrag.css({transform: 'translateX('+newLeft+'px)'});
}
}
);
}
and the fiddle : http://jsfiddle.net/V5Jmu/2/
UPDATE
I made a new fiddle where it seems to work better thanks to matjazek answer
I would recommend that you solve the problem with a different aproach, but if you insist in using your method, something like this should get the job done:
You can set the drag coeficient with
var drag=0.95; // Drag coeficient