touchmove handler after touchstart handler wont work - javascript

I have a problem with an touchmove event. When the user touches the display (touchstart) the touchmove event handler and game() should be executed and if the user leaves the screen everything should be stopped. But then the if conditions for the collisiondetection interval won't work right because e.pageX and e.pageY always have the coordinates of the touchstart and won't update their values when the user moves their finger (touchmove) on the screen. How can I fix this? demo
$("body").on({
'touchstart mousedown': function (e) {
$(this).on('touchmove mousemove');
collisiondetection = setInterval(function() {
var xp1 = $("#n1").position();
if (e.pageY >= xp1.top && e.pageY <= xp1.top + cy * 10 && e.pageX >= xp1.left && e.pageX <= xp1.left + cx * 25) {
console.log("hit");
}
var xp2 = $("#n2").position();
if (e.pageY >= xp2.top && e.pageY <= xp2.top + cy * 10 && e.pageX >= xp2.left && e.pageX <= xp2.left + cx * 25) {
console.log("hit");
}
},10);
game();
},
'touchend mouseup': function (e) {
$(this).off('touchmove mousemove');
clearInterval(animaterects);
clearInterval(collisiondetection);
}
});
UPDATE: If I edit it to 'touchstart mousedown touchmove mousemove': function (e) { the collision detection and the updating coordinates works well but the animation dont.

Becasue your code doesn't update the coordinates when users move their fingers.
$("body").on({
'touchstart mousedown': function (e) {
var pageX = e.pageX
var pageY = e.pageY;
$(this).on('touchmove mousemove',function(e){
pageX = e.pageX;
pageY = e.pageY;
});
collisiondetection = setInterval(function() {
var xp1 = $("#n1").position();
if (pageY >= xp1.top && pageY <= xp1.top + cy * 10 && pageX >= xp1.left && pageX <= xp1.left + cx * 25) {
console.log("hit");
}
var xp2 = $("#n2").position();
if (pageY >= xp2.top && pageY <= xp2.top + cy * 10 && pageX >= xp2.left && pageX <= xp2.left + cx * 25) {
console.log("hit");
}
},10);
game();
},
'touchend mouseup': function (e) {
$(this).off('touchmove mousemove');
clearInterval(animaterects);
clearInterval(collisiondetection);
}
});

Related

Detect direction of touchpad swipe properly

I was able to scale in scale out x axis and y axis , Its working very good with arrow keys , I want to do that with touchpad aswel.I tried this below code ,its working but its not smooth .Sometimes when i zoom in X , its even zooming in Y and vice versa.
window.addEventListener('mousewheel', function(e) {
window.addEventListener('mousewheel', function(e) {
e.preventDefault();
yDelta = e.deltaY;
xDelta = e.deltaX;
if (yDelta < -1 && Math.round(xDelta) < 1) {
zoomOutY();
} else if (yDelta > 1 && Math.round(xDelta) < 1) {
zoomInY();
} else if (xDelta < -1 && Math.round(yDelta) < 1) {
zoomOut();
} else if (xDelta > -1 && Math.round(yDelta) < 1) {
zoomIn();
}
}, {
passive: false
});
And Again Same issue with mousemove method , how to detect the 4 directions smoothly , below is my code.
document.addEventListener('mousemove', mouseMoveMethod);
document.addEventListener('mousedown', mouseDownMethod);
document.addEventListener('mouseup', mouseUpMethod);
// Prevent context menu popup, so we can move our mouse.
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
return false;
}, false);
mouseMoveMethod = function(e) {
if (e.ctrlKey || mouseIsHeld) {
let offsetX = 0
let offsetY = 0
if (e.pageX > oldx && e.pageY == oldy) {
direction = "East";
offsetX -= 1
} else if (e.pageX == oldx && e.pageY > oldy) {
direction = "South";
offsetY += 1
} else if (e.pageX == oldx && e.pageY < oldy) {
direction = "North";
offsetY -= 1
} else if (e.pageX < oldx && e.pageY == oldy) {
offsetX += 1
direction = "West";
}
updateKeyboardPan(offsetX, offsetY);
oldx = e.pageX;
oldy = e.pageY;
})
Again in the above code I am able to find the direction , but its lagging and hanging in middle.Is this the right approach ? or can I improve my code to improve my swipe/mousewheel direction , thank you.
I found a quite interesting example of multi-touch trackpad gestures in JavaScript.
The code snippet below utilizes this for overriding LCJS chart interactions for trackpad. To me it seems to perform in a surprisingly intuitive manner for zooming in/out on pinch interaction (2 fingers, move to opposite directions) and panning with dragging 2 fingers in same direction.
I did not find any way to differentiate pinch interaction along X and Y separately, it seems that the JS events just get a single value for both, which is assigned to deltaY.
const {
lightningChart
} = lcjs;
const {
createProgressiveTraceGenerator
} = xydata;
const chart = lightningChart().ChartXY();
const series = chart.addLineSeries()
createProgressiveTraceGenerator()
.setNumberOfPoints(1000)
.generate()
.toPromise()
.then(data => {
series.add(data)
})
chart.setMouseInteractionWheelZoom(false)
chart.onSeriesBackgroundMouseWheel((_, e) => {
const xInterval = chart.getDefaultAxisX().getInterval()
const yInterval = chart.getDefaultAxisY().getInterval()
if (e.ctrlKey) {
// Zoom in / out (no separation of X or Y amount!)
const zoomAmount = e.deltaY * 0.01
chart.getDefaultAxisX().setInterval(xInterval.start + zoomAmount * (xInterval.end - xInterval.start), xInterval.end - zoomAmount * (xInterval.end - xInterval.start), false, true)
chart.getDefaultAxisY().setInterval(yInterval.start + zoomAmount * (yInterval.end - yInterval.start), yInterval.end - zoomAmount * (yInterval.end - yInterval.start), false, true)
} else {
// Pan X and Y simultaneously.
const panX = e.deltaX * 0.001 * (xInterval.end - xInterval.start)
const panY = e.deltaY * -0.001 * (yInterval.end - yInterval.start)
chart.getDefaultAxisX().setInterval(xInterval.start + panX, xInterval.end + panX, false, true)
chart.getDefaultAxisY().setInterval(yInterval.start + panY, yInterval.end + panY, false, true)
}
e.preventDefault()
})
<script src="https://unpkg.com/#arction/xydata#1.4.0/dist/xydata.iife.js"></script>
<script src="https://unpkg.com/#arction/lcjs#3.0.0/dist/lcjs.iife.js"></script>

event propagation in three.js

I have a scene with several objects. I use an orthographic camera controller. When I have a selected object, I want to rotate it with the mouse using shiftKey + but 1 (rotation around its own center) and translate it in the scene using shiftKey + but 3.
When setting up my mouse events handlers, I tried to stop the camera controls to fire, but it still does as soon as button is up.
Can someone show me where I'm wrong ?
$(canva).mousedown(function (e) {
if (selObject && e.shiftKey) {
e.preventDefault();
e.stopPropagation()
e.cancelBubble=true;
e.returnValue=false;
controls.enabled = false
mDown = e.which
clientX = e.clientX
clientY = e.clientY
return false
}
});
$(canva).mousemove(function (e) {
if (! selObject || ! mDown) {
return true
}
e.stopPropagation()
e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
dX = e.clientX - clientX
dY = e.clientY - clientY
if (mDown == 1) {
dX /= 100
dY /= 100
selObject.rotation.x += dX
selObject.rotation.y += dY
} else if (mDown == 3) {
dX /= 2
dY /= 2
var pos = mouse2world(e)
selObject.position = pos
}
clientX = e.clientX
clientY = e.clientY
return false
});
$(canva).mouseup(function (e) {
if (mDown) {
mDown = 0
e.preventDefault();
e.stopPropagation()
e.cancelBubble=true;
e.returnValue=false;
controls.enabled = true
return false
}
});
Try
event.stopImmediatePropagation();
instead of
event.stopPropagation();
Source: MDN https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation
Semicolon is missing on all e.stopPropagation() statements.

Moving a div when mouse near

I want that the div I created will move when the mouse is getting near to him.
Here is the fiddle link: http://jsfiddle.net/jLAq3/2/
Basic starting code (because I don't have a clue how to do it):
$('#leaf').();
Bind a function to the movement of the mouse. As the mouse moves:
Get the coordinates of the element.
Get the coordinates of the cursor.
Compare cursor coordinates with element coordinates.
If cursor is near element, move element - else do nothing.
Easy stuff.
This is a start. Every time the mouse is moving outside the leaf then a message appears.
$('body').mousemove(function(e){
var w = $('#leaf').outerWidth(),
h = $('#leaf').outerHeight(),
x = e.pageX,
y = e.pageY;
if(x > w && y > h)
{
console.log("The leaf is moving");
}
})
Furthermore you can apply some css with js to the leaf for movement etc. In a more complex example you have to spot more carefully the position and not simply rely on the width and the height of the image.
Here is a start.
http://jsfiddle.net/Lpg8x/80/
$( 'body' ).mousemove( function( event ) {
if( isNear( $( '#near' ), 20, event ) ) {
$( '#near' ).html( 'is near!' );
} else {
$( '#near' ).empty();
};
} );
function isNear( $element, distance, event ) {
var left = $element.offset().left - distance,
top = $element.offset().top - distance,
right = left + $element.width() + ( 2 * distance ),
bottom = top + $element.height() + ( 2 * distance ),
x = event.pageX,
y = event.pageY;
return ( x > left && x < right && y > top && y < bottom );
};
Have fun!
Here is a basic working example of how you actually would do all that
http://jsfiddle.net/jLAq3/10/
var leafX = 0, leafY = 0;
$('#leaf').css({position: 'relative'});
$(document).mousemove(function(e){
var offset = $('#leaf').offset()
,x1 = offset.left - 20
,x2 = offset.left + $('#leaf').width() + 20
,y1 = offset.top
,y2 = offset.top + $('#leaf').height() + 20
,center, mousePos
;
if(e.pageX > x1 && e.pageX < x2 && e.pageY > y1 && e.pageY < y2) {
center = (x2 - x1) / 2;
mousePos = e.pageX - x1;
if(mousePos < center) {
leafX += 20;
} else {
leafX -= 20;
}
center = (y2 - y1) / 2;
mousePos = e.pageY - y1;
if(mousePos < center) {
leafY += 20;
} else {
leafY -= 20;
}
}
$('#leaf').css({ top : leafY + 'px', left : leafX + 'px'});
});
But you should really learn the basics of DHTML before jumping into things, for example the difference between position absolute and relative, how to actually move HTML elements, layering, event binding etc.
Here are couple of good resources:
http://www.quirksmode.org/sitemap.html
http://www.w3schools.com/

Make HTML5 draggable items scroll the page?

I'm using the HTML5 attribute draggable = "true" on some of my divs on my webpage. I want it so that when you drag one of these items to the bottom of the page, it scrolls the page down and when you drag it to the top, it scrolls the page up.
I will eventually make a playlist on my sidebar, and since it will not always be on view depending on where you're looking on the page, the page needs to scroll when you're dragging.
My page is here and you can try dragging the pictures of the posts around. On Chrome, it automatically lets me scroll down when I drag to the bottom, but not up. On Firefox, it doesn't automatically let me scroll either direction. Any help?
Here's a simple jsfiddle to get you started. On Chrome you should be able to drag the Google icon down and have it scroll the page down, but not going up.
here is a code that will scroll-up or scroll-down your page while you are dragging something. Just placing your dragging object at top or bottom of the page. :)
var stop = true;
$(".draggable").on("drag", function (e) {
stop = true;
if (e.originalEvent.clientY < 150) {
stop = false;
scroll(-1)
}
if (e.originalEvent.clientY > ($(window).height() - 150)) {
stop = false;
scroll(1)
}
});
$(".draggable").on("dragend", function (e) {
stop = true;
});
var scroll = function (step) {
var scrollY = $(window).scrollTop();
$(window).scrollTop(scrollY + step);
if (!stop) {
setTimeout(function () { scroll(step) }, 20);
}
}
I have made a simple JavaScript drag and drop class. It can automatically scroll up or down the page while dragging.
See this jsfiddle. Also avaliable at my github page.
Dragging at a high speed is not recommended now. I need to work out that.
Code below is a part of the library.
var autoscroll = function (offset, poffset, parentNode) {
var xb = 0;
var yb = 0;
if (poffset.isBody == true) {
var scrollLeft = poffset.scrollLeft;
var scrollTop = poffset.scrollTop;
var scrollbarwidth = (document.documentElement.clientWidth - document.body.offsetWidth); //All
var scrollspeed = (offset.right + xb) - (poffset.right + scrollbarwidth);
if (scrollspeed > 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = offset.left - (xb);
if (scrollspeed < 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = (offset.bottom + yb) - (poffset.bottom);
if (scrollspeed > 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
scrollspeed = offset.top - (yb);
if (scrollspeed < 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
} else {
var scrollLeft = offset.scrollLeft;
var scrollTop = offset.scrollTop;
var scrollbarwidth = parentNode.offsetWidth - parentNode.clientWidth; //17
var scrollbarheight = parentNode.offsetHeight - parentNode.clientHeight; //17
var scrollspeed = (offset.right + xb) - (poffset.right - scrollbarwidth);
if (scrollspeed > 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = offset.left - (xb + poffset.left);
if (scrollspeed < 0) {
this.scrollLeft(parentNode, scrollLeft + scrollspeed);
}
scrollspeed = (offset.bottom + scrollbarheight + yb) - (poffset.bottom);
if (scrollspeed > 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
scrollspeed = offset.top - (yb + poffset.top);
if (scrollspeed < 0) {
this.scrollTop(parentNode, scrollTop + scrollspeed);
}
}
};
Here is the javascript version of AngularPlayers answer, I added horizontal support. I noticed both the JQuery solution and Javascript solution have a bug on mobile safari that allows the page to infinitely grow when the bounce effect from overscrolling happens.
The purpose of VerticalMaxed and HorizontalMaxed is to check that the scroll bars are not maxed before scrolling again. This prevents the page from growing during overscroll bounce.
var stopX = true;
var stopY = true;
document.addEventListener('drag', function(e) {
if (event.target.classList.contains('draggable')) {
stopY = true;
// Handle Y
if (e.clientY < 150) {
stopY = false;
scroll(0,-1)
}
if ((e.clientY > ( document.documentElement.clientHeight - 150)) && !VerticalMaxed()) {
stopY = false;
scroll(0,1)
}
// Handle X
stopX = true;
if (e.clientX < 150) {
stopX = false;
scroll(-1,0)
}
if ((e.clientX > ( document.documentElement.clientWidth - 150)) && !HorizontalMaxed()) {
stopX = false;
scroll(1,0)
}
}
});
document.addEventListener('dragend', function(e) {
if (event.target.classList.contains('draggable')) {
stopY = true;
//stopY = true;
stopX = true;
}
});
// On drag scroll, prevents page from growing with mobile safari rubber-band effect
var VerticalMaxed = function(){ return (window.innerHeight + window.scrollY) >= document.body.offsetHeight}
var HorizontalMaxed = function(){ return (window.pageXOffset) > (document.body.scrollWidth - document.body.clientWidth);}
var scroll = function (stepX, stepY) {
var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
window.scrollTo((scrollX + stepX), (scrollY + stepY));
if (!stopY || !stopX) {
setTimeout(function () { scroll(stepX, stepY) }, 20);
}
}

This javascript fails on mouseover

can anyone figure out why this JavaScript won't work? It correctly generates the document.write output, but when you try to drag it it starts complaining about top and left not being set. any idea whats wrong?
abilitynames=new Array('Heal','Slash','Stab','Poison Slash','Knockout','','','','Tornado','','','','','','','','Icespike','','','','','','','','Bolt','Jumping Bolt','','','','','','','Roast','Burn','','','','','','','Earthquake','Rockwall','','','','','','','Kill','Deflect','Anti-Heal','','','','','','Backslash','Darkwall','Steal','Take','','','','');
abilitytypes=new Array(3,1,1,1,1,2,2,2,1,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,2,1,2,3,2,2,2,2,2,1,2,3,3,2,2,2,2);
abilitycolors=new Array('#00FF00','#FFFFFF','#0000FF','#FFFF00','#FF0000','#AD6C00','#AD00FF','#000000');
for(i=0;i<64;i++){
document.write("<div onmousedown='dragging=this.id;this.style.position=\"fixed\";this.style.zIndex=1000;this.style.left=event.clientX-75;this.style.top=event.clientY-15;' onmouseout='if(dragging===this.id){this.style.left=event.clientX-75;this.style.top=event.clientY-15;}' onmousemove='if(dragging===this.id){this.style.left=event.clientX-75;this.style.top=event.clientY-15;}' onmouseup='dragging=false;if(event.clientX<450||event.clientY>"+(180+(abilitytypes[i]*90))+"||event.clientY<"+(100+((abilitytypes[i]-1)*(90*abilitytypes[i])/((4%abilitytypes[i])+1)))+"){this.style.position=\"relative\";this.style.top=0;this.style.left=0;this.style.zIndex=0;}else{this.style.left=460;this.style.top=(Math.round((event.clientY-30)/45)*45)+15;if(abilitys[Math.round((event.clientY-120)/45)]!=\"\"&&abilitys[Math.round((event.clientY-120)/45)]!=this.id){document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.position=\"relative\";document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.left=0;document.getElementById(abilitys[Math.round((event.clientY-120)/45)]).style.top=0;}abilitys[Math.round((event.clientY-120)/45)]=this.id;alert(abilitys);}' id='"+i+"' class='abilityblock"+abilitytypes[i]+"'><div class='abilityicon' style='background-position:"+(Math.floor(i/8)*-20)+"px "+((i%8)*-20)+"px;'></div><div class='abilityname' style='color:"+abilitycolors[Math.floor(i/8)]+";'>"+abilitynames[i]+"</div></div>");
}
I've probably broken the script just TRYING to clean up this unholy mess and simplifying things a little, but at least it seems to be a bit more readable now (not including the array definitions):
<script type="text/javascript">
var dragging;
function mouseDown(el) {
dragging = el.id;
el.style.position = "fixed";
el.style.zIndex = 1000;
el.style.left = event.clientX - 75;
el.style.top = event.clientY-15;
}
function mouseOut(el) {
if (dragging === el.id) {
el.style.left = event.clientX - 75;
el.style.top = event.clientY - 15;
}
}
function mouseMove(el) {
if (dragging === el.id) {
el.style.left = event.clientX - 75;
el.style.top = event.clientY - 15;
}
}
function mouseUp(el, i) {
dragging = false;
if ( (event.clientX < 450) ||
(event.clientY > (180 + (abilitytypes[i] * 90)) ) ||
(event.clientY < (100 + (abilitytypes[i] - 1) * (90 * abilitytypes[i]) / ((4 % abilitytypes[i]) + 1)))) {
el.style.position = "relative";
el.style.top = 0;
el.style.left = 0;
el.style.zIndex = 0;
} else {
el.style.left = 460;
el.style.top = (Math.round((event.clientY - 30) / 45) * 45) + 15;
if ((abilitys[Math.round((event.clientY - 120) / 45)] != "") && (abilitys[Math.round((event.clientY - 120) / 45)] != el.id)) {
var subel = document.getElementById(abilitys[Math.round((event.clientY-120)/45)]);
subel.style.position="relative";
subel.style.left=0;
subel.style.top=0;
}
abilitys[Math.round((event.clientY - 120) / 45)] = el.id;
alert(abilitys);
}
}
for(var i = 0; i < 64; i++){
document.write("
<div onmousedown='mouseDown(this);'
onmouseout='mouseOut(this);'
onmousemove='mouseMove(el);'
onmouseup='mouseUp(this, i);'
id='"+i+"'
class='abilityblock"+abilitytypes[i]+"'>
<div class='abilityicon' style='background-position:"+(Math.floor(i/8)*-20)+"px "+((i%8)*-20)+"px;'></div>
<div class='abilityname' style='color:"+abilitycolors[Math.floor(i/8)]+";'>"+abilitynames[i]+"</div>
</div>");
}
</script>
Phew. And after all that, I'm guessing your missing 'left' and 'top' parameters are because your dynamically computed element IDs are generating non-existent IDs in the mouseup handler.
My suggestion? Scrap this home-brew drag 'n drop stuff and use the functionality provided by Mootools or jQuery. Far less trouble, especially when having to deal with cross-browser differences.
Searching your code, you haven't defined an onmouseover event. You define onmousedown, onmouseout, onmousemove, and onmouseup. No onmouseover.

Categories