I am working on a function that will delete a div when you swipe it left...
Here is a div that I would like to delete when it is swiped:
<div class="listItem">Stuff here</div>
I have javascript to determine where on the page I have swiped by using the touchstart and touchend event listeners.
I have created a function called to delete the item:
function swipeLeft(){
//delete item
}
I am determining where I swipe like this:
var touchobj = e.changedTouches[0];
dist = touchobj.pageX - startX
Now is it possible to delete the div with this information?
Yeah, you just calculate the deltas between the div's sizes and swipe distance.
Here is a good example for a generic swipe pattern detection:
http://www.javascriptkit.com/javatutors/touchevents2.shtml
Code:
function swipedetect(el, callback){
var touchsurface = el,
swipedir,
startX,
startY,
distX,
distY,
threshold = 150, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 300, // maximum time allowed to travel that distance
elapsedTime,
startTime,
handleswipe = callback || function(swipedir){}
touchsurface.addEventListener('touchstart', function(e){
var touchobj = e.changedTouches[0]
swipedir = 'none'
dist = 0
startX = touchobj.pageX
startY = touchobj.pageY
startTime = new Date().getTime() // record time when finger first makes contact with surface
e.preventDefault()
}, false)
touchsurface.addEventListener('touchmove', function(e){
e.preventDefault() // prevent scrolling when inside DIV
}, false)
touchsurface.addEventListener('touchend', function(e){
var touchobj = e.changedTouches[0]
distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface
distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface
elapsedTime = new Date().getTime() - startTime // get time elapsed
if (elapsedTime <= allowedTime){ // first condition for awipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
swipedir = (distX < 0)? 'left' : 'right' // if dist traveled is negative, it indicates left swipe
}
else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe
}
}
handleswipe(swipedir)
e.preventDefault()
}, false)
}
//USAGE:
/*
var el = document.getElementById('someel')
swipedetect(el, function(swipedir){
swipedir contains either "none", "left", "right", "top", or "down"
if (swipedir =='left')
alert('You just swiped left!')
})
*/
All you do is adjust the threshold if you need to. Once detected you just remove the div from the DOM.
Related
Im building an online multiplayer game where you can click on tiles to move to them. The tiles have an x and z position.
I dont know how to reset the clearInterval if a player clicks another tile in socket.io. Right now it doubles the speed because it duplicates the setInterval I guess and if I try to clearInterval at the beginning it seems not to target the old setInterval. I tried to bind the setInterval to the player[socket.id] object but got a Maximum call stack size exceeded error then.
How do I clear this specific setInterval for the player so it hasnt 2 setIntervals when I click a second tile while moving?
index.js (server)
players[socket.id] = {
x: 0,
z: 0,
xTo:0,
zTo:0,
isMoving: false,
playerId: socket.id,
name: name,
room: 'lobby'
};
//when client clicks on a tile
socket.on('moveRequest', function(pos) {
//set clicked tile x/z to player entity
players[socket.id].xTo = pos[0];
players[socket.id].zTo = pos[2];
//only continiue if clicked tile is different from current tile
if (players[socket.id].x !== players[socket.id].xTo) {
//get direction left/right
var xDiff = players[socket.id].xTo - players[socket.id].x;
var xDirection = 'none';
if (xDiff > 0) {
console.log('player wants to move right');
xDirection = 'right';
} else {
console.log('player wants to move left');
xDirection = 'left';
}
//if there is wanted movement
if (xDirection !== 'none') {
//setInterval 60fps
const moveInterval = setInterval(function() {
//if direction is right and players current position is smaller then clicked position
if (xDirection == 'right' && players[socket.id].x < players[socket.id].xTo) {
//move player
players[socket.id].x = players[socket.id].x + 0.03;
} else {
//if reached destination clear the interval
xDirection = 'none';
clearInterval(moveInterval);
}
//now send move to all players in room
io.to('game').emit('playerMove', players[socket.id]);
}, 1000 / 60);
}
}
});
I want to make a Javascript function that will eventually cause a div to animate by updating a calculation as the user scrolls.
My aim is to do this by incrementing a number, initially from 0 up to 20. Once 20 is the value this number needs to be recognised and then the value needs to decrement down from 20 to -20 (For example)
At the moment I have a function that will count up as I scroll down the page and then when I scroll up will count down again but I'm not sure how best to get the values to also update when the numbers reach 20 and -20 as the user scrolls.
let scrollCount = 0;
window.addEventListener("mousewheel", function(e){
if(e.wheelDelta < 0 && scrollCount < 20){
scrollCount++
}
else if(e.wheelDelta > 0 && scrollCount > -20){
scrollCount--
}
let x = scrollCount * window.innerWidth
let y = 30 * window.innerHeight
moveEye(irisLeft, x, y)
moveEye(irisRight, x, y)
console.log(scrollCount)
});
I think using PageOffset would be a better option.
var scrollTop = window.pageYOffset;
This will give you an absolute px value of scroll position. Though it is not in range [-20,20], you can scale it mathematically(min-max scaling).
Scaling Answered Here
Round off scaled values to integers and you're done.
As I said in my comment - this behavior is quire weird as once 20 is reached your div will start trembling/bouncing and will throw your user in a epileptic shock.
let scrollCount = 0;
let direction = 1;
window.addEventListener("mousewheel", function (e) {
if (e.wheelDelta < 0) {
scrollCount += direction
if (scrollCount === 20 || scrollCount === -20) {
direction *= -1
}
}
else if (e.wheelDelta > 0) {
scrollCount -= direction
if (scrollCount === 20 || scrollCount === -20) {
direction *= -1
}
}
let x = scrollCount * window.innerWidth
let y = 30 * window.innerHeight
// moveEye(irisLeft, x, y)
// moveEye(irisRight, x, y)
console.log(scrollCount)
});
I have the following code:
swipeDetect = function(el, callback){
var touchsurface = el,
swipedir,
startX,
startY,
distX,
distY,
threshold = 7, //required min distance traveled to be considered swipe
restraint = 100, // maximum distance allowed at the same time in perpendicular direction
allowedTime = 500, // maximum time allowed to travel that distance
maxangle=40,
elapsedTime,
startTime,
touchinprocess=false,
handleswipe = callback || function(swipedir){};
touchsurface.addEventListener('touchstart', function(e){
touchinprogress = true;
var touchobj = e.changedTouches[0];
swipedir = 'none';
dist = 0;
startX = touchobj.pageX;
startY = touchobj.pageY;
startTime = new Date().getTime();
}, false);
touchsurface.addEventListener('touchmove', function(e){
var touchobj = e.changedTouches[0];
distX = startX - touchobj.pageX;
distY = startY - touchobj.pageY;
rads = Math.atan(distY,distX);
var deg = rads * (180 / 3.14);
console.log(deg);
if (Math.abs(distY) > restraint && Math.abs(deg) > maxangle) e.preventDefault();
}, false);
touchsurface.addEventListener('touchend', function(e){
var touchobj = e.changedTouches[0];
distX = touchobj.pageX - startX;
distY = touchobj.pageY - startY;
elapsedTime = new Date().getTime() - startTime;
if (elapsedTime <= allowedTime){ // first condition for awipe met
if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met
swipedir = (distX < 0)? 'left' : 'right'; // if dist traveled is negative, it indicates left swipe
}
else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met
swipedir = (distY < 0)? 'up' : 'down'; // if dist traveled is negative, it indicates up swipe
};
};
handleswipe(e,swipedir);
return true;
}, false);
},
I'm trying to get the angle in degrees of a touch swipe in the touch move function (and kill the default scroll if the swipe is above a certain number of degrees). But It keeps outputting numbers around 80. No matter how I swipe. What is wrong here?
I'm using this for image swiping and I want to let the user swipe and not have it scroll and swipe at the same time.
Maybe i'm going about this all wrong.
Thanks for your help.
The Math.atan(x)[1] function takes a single argument, which in your case should be the ratio of y over x:
rads = Math.atan(distY/distX);
It might be hard to see the difference, but in your initial code you have a , rather than a /. I ran your code with this change and it worked. Keep in mind that Math.atan2(y,x) does take two arguments.
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan
I did some testing and I think the issue may be with your atan function. Give atan2 a try?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/atan2
It seems to essentially work for me.
In javascript, is there a way I can create a variable and a function that "simulates" smooth mouse movement? i.e., say the function simulates a user starts from lower left corner of the browser window, and then moves mouse in a random direction slowly...
The function would return x and y value of the next position the mouse would move each time it is called (would probably use something like setInterval to keep calling it to get the next mouse position). Movement should be restricted to the width and height of the screen, assuming the mouse never going off of it.
What I don't want is the mouse to be skipping super fast all over the place. I like smooth movements/positions being returned.
A "realistic mouse movement" doesn't mean anything without context :
Every mouse user have different behaviors with this device, and they won't even do the same gestures given what they have on their screen.
If you take an FPS game, the movements will in majority be in a small vertical range, along the whole horizontal screen.
Here is a "drip painting" I made by recording my mouse movements while playing some FPS game.
If we take the google home page however, I don't even use the mouse. The input is already focused, and I just use my keyboard.
On some infinite scrolling websites, my mouse can stay at the same position for dozens of minutes and just go to a link at some point.
I think that to get the more realistic mouse movements possible, you would have to record all your users' gestures, and repro them.
Also, a good strategy could be to get the coordinates of the elements that will attract user's cursor the more likely (like the "close" link under SO's question) and make movements go to those elements' coordinates.
Anyway, here I made a snippet which uses Math.random() and requestAnimationFrame() in order to make an object move smoothly, with some times of pausing, and variable speeds.
// Canvas is here only to show the output of function
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
var maxX = canvas.width = window.innerWidth;
var maxY = canvas.height = window.innerHeight;
window.onresize = function(){
maxX = canvas.width = window.innerWidth;
maxY = canvas.height = window.innerHeight;
}
gc.onclick = function(){
var coords = mouse.getCoords();
out.innerHTML = 'x : '+coords.x+'<br>y : '+coords.y;
}
var Mouse = function() {
var that = {},
size = 15,
border = size / 2,
maxSpeed = 50, // pixels per frame
maxTimePause = 5000; // ms
that.draw = function() {
if (that.paused)
return;
that.update();
// just for the example
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(show.checked){
ctx.drawImage(that.img, that.x - border, that.y - border, size, size)
}
// use requestAnimationFrame for smooth update
requestAnimationFrame(that.draw);
}
that.update = function() {
// take a random position, in the same direction
that.x += Math.random() * that.speedX;
that.y += Math.random() * that.speedY;
// if we're out of bounds or the interval has passed
if (that.x <= border || that.x >= maxX - border || that.y <= 0 || that.y >= maxY - border || ++that.i > that.interval)
that.reset();
}
that.reset = function() {
that.i = 0; // reset the counter
that.interval = Math.random() * 50; // reset the interval
that.speedX = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the horizontal direction
that.speedY = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the vertical direction
// we're in one of the corner, and random returned farther out of bounds
if (that.x <= border && that.speedX < 0 || that.x >= maxX - border && that.speedX > 0)
// change the direction
that.speedX *= -1;
if (that.y <= border && that.speedY < 0 || that.y >= maxY - border && that.speedY > 0)
that.speedY *= -1;
// check if the interval was complete
if (that.x > border && that.x < maxX - border && that.y > border && that.y < maxY - border) {
if (Math.random() > .5) {
// set a pause and remove it after some time
that.paused = true;
setTimeout(function() {
that.paused = false;
that.draw();
}, (Math.random() * maxTimePause));
}
}
}
that.init = function() {
that.x = 0;
that.y = 0;
that.img = new Image();
that.img.src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABJUlEQVRIic2WXbHEIAyFI6ESKgEJkVIJlYCTSqiESIiESqiEb19gL9Od3f5R5mbmPPHwBTgnIPJfChiAGbCkCQgtG7BpmgAWIALaDDyOI2bGuq40BasqIoKZATgwNAWHEEjHbkBsBhYRVJUYIwBNwVlFaVOwiDDPMylmQ1OwquY7d0CBrglYkuEeidoeOKt61I6Cq0ftKFhqR+0MOKuo2BQsInnndvnOr4JvR+0qWO5G7Q44K0XtOXDf96jqh9z9WXAy1FJ8l0qd+zbtvU7lWs7wIzkuh8SvpqqDi3zGndPQauDkzvdESm8xZvbh4mVZ7k8ud/+aR0C3YPk7mVvgkCZPVrdZV3dHVem6bju1roMPNmbAmq8kG+/ynD7ZwNsAVVz9dL0AhBrZq7F+CSQAAAAASUVORK5CYII=";
that.reset();
}
that.getCoords = function(){
return {x: that.x, y:that.y};
}
that.init()
return that;
}
var mouse = new Mouse()
mouse.draw();
html,body {margin: 0}
canvas {position: absolute; top:0; left:0;z-index:-1}
#out{font-size: 0.8em}
<label for="show">Display cursor</label><input name="show" type="checkbox" id="show" checked="true"/><br>
<button id="gc">get cursor Coords</button>
<p id="out"></p>
Last I heard the browser's mouse position cannot be altered with JavaScript, so the question really has no answer "as is". The mouse position can be locked though. I'm not certain whether it would be possible to implement a custom cursor that allows setting the position. This would include hiding and perhaps locking the stock cursor.
Having something smoothly follow the cursor is quite straight forward. You may be able to reverse this process to achieve what you need. Here's a code snippet which simply calculates the distance between the cursor and a div every frame and then moves the div 10% of that distance towards the cursor:
http://jsfiddle.net/hpp0qb0d/
var p = document.getElementById('nextmove')
var lastX,lastY,cursorX,cursorY;
window.addEventListener('mousemove', function(e){
cursorX = e.pageX;
cursorY = e.pageY;
})
setInterval(function(){
var newX = p.offsetLeft + (cursorX - lastX)/10
var newY = p.offsetTop + (cursorY - lastY)/10
p.style.left = newX+'px'
p.style.top = newY+'px'
lastX = p.offsetLeft
lastY = p.offsetTop
},20)
I try to create a animation where a circle become moved by a touchevent:
function initi() {
console.log('init');
// Get a reference to our touch-sensitive element
var touchzone = document.getElementById("myCanvas");
// Add an event handler for the touchstart event
touchzone.addEventListener("mousedown", startTouch, false);
// You need mouseup to capture the stop event
touchzone.addEventListener("mouseup", stopTouch, false);
}
function startTouch(event) {
// You can access the event here too..
// But for demo I will only get the current Time
startTime = new Date().getTime();
}
function stopTouch(event) {
// Get a reference to our coordinates div
var can = document.getElementById("myCanvas");
// Write the coordinates of the touch to the div
if (event.pageX < x * 100 && event.pageY > y * 10) {
// Calculate the duration, only if needed
var duration = new Date().getTime() - startTime;
bally -= 0.005 * duration; // use duration
}
else if ( event.pageX > x * 100) {
}
// I hope bally if defined in the outer scope somewhere ;)
console.log(event, x, bally);
draw();
}
So my question is how can I make the bally smaller when this area: event.pageX < x * 100 && event.pageY > y * 10 become touched, after bally -= 0.005 * duration; become executed? I try it with arrays to save if its touched and then give it to update function and know that localstorage and cookies would work too but I think thats not the best solution. Any hints to realize that?
see fiddle