mouse wheel to be use for swipe - javascript

i have a function which works for mouse wheel and i want to use the same function for swipe.
// Mouse Wheel support
this.MouseWheel =
{
init: function()
{
// Init mouse wheel listener
if(window.addEventListener)
{
my.ImageFlowDiv.addEventListener('DOMMouseScroll', my.MouseWheel.get, false);
}
my.Helper.addEvent(my.ImageFlowDiv,'mousewheel',my.MouseWheel.get);
},
get: function(event)
{
var delta = 0;
if (!event)
{
event = window.event;
}
if (event.wheelDelta)
{
delta = event.wheelDelta / 120;
}
else if (event.detail)
{
delta = -event.detail / 3;
}
if (delta)
{
my.MouseWheel.handle(delta);
}
my.Helper.suppressBrowserDefault(event);
},
handle: function(delta)
{
alert('handle called');
var change = false;
var newImageID = 0;
if(delta > 0)
{
if(my.imageID >= 1)
{
newImageID = my.imageID -3;
change = true;
}
}
else
{
if(my.imageID < (my.max-1))
{
newImageID = my.imageID +4;
change = true;
}
}
/* Glide to next (mouse wheel down) / previous (mouse wheel up) image */
if(change)
{
//alert('new image id='+newImageID);
my.glideOnEvent(newImageID);
}
}
};
Earlier i used the touchswipe plugin and it was working fine but i want to use another plugin as touchswipe is disturbing touch support.
$("#imageFlow").swipe({
swipe:function(event, direction, distance, duration, fingerCount) {
alert('swipe called');
if(direction == 'left') {
my.MouseWheel.handle(-1);
} else if (direction == 'right') {
my.MouseWheel.handle(1);
}
}
});

Have you taken a look at Hammer JS? I find their syntax is fairly simple to use and does not interfere with my other touch events.
Your code could then look similar to this:
Hammer($('#imageFlow')).on("swipe", function(event) {
console.log('swipe called'); //(instead of alert)
if (event.gesture.direction === 'left'){
my.MouseWheel.handle(-1);
} else if (event.gesture.direction === 'right'){
my.MouseWheel.handle(1);
};
});
In the docs
Also bear in mind to use 3 equals signs in JavaScript. so:
if (myName === 'Jean-Marie'){//dostuff}
instead of
if (myName == 'Jean-Marie'){//dostuff}

Related

requestAnimationFrame not working as intended Javascript

I'm making a game in which a player character moves left and right.
Since simply using an onKeyDown eventListener had my character move in a choppy fashion, and with a slight delay, I tried using requestAnimationFrame to call the movement function as often as possible, as suggested by another answer(How can I move my JS objects smoothly using keyboard input?)
however, that has changed nothing.
Here is my Javascript Code
var NodoCampo = document.getElementById("campo");
var NodoGiocatore = null;
var Left = false;
var Right = false;
var FRAMERATE = 20;
//cache giocatore
var LARG_GIOCATORE = 30;
var ALT_GIOCATORE = 30;
var X_GIOCATORE = 300;
var Y_GIOCATORE = 1100;
var VEL_GIOCATORE = 10;
function mostra_giocatore() {
if (NodoGiocatore === null) {
NodoGiocatore = document.createElement('div');
NodoGiocatore.setAttribute ('id', 'player');
NodoCampo.appendChild (NodoGiocatore);
}
NodoGiocatore.style.marginLeft = (X_GIOCATORE - LARG_GIOCATORE) + 'px';
NodoGiocatore.style.marginTop = (Y_GIOCATORE - ALT_GIOCATORE) + 'px';
}
function muovi() {
if (Left) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
else if (Right) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function stop() {
Left = false;
Right = false;
}
function interfaccia(e) {
//freccia sinstra
if (e.keyCode === 37) {
X_GIOCATORE = X_GIOCATORE - VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
//freccia destra
else if (e.keyCode === 39) {
X_GIOCATORE = X_GIOCATORE + VEL_GIOCATORE;
//aggiorno immagine
mostra_giocatore();
}
}
function inizia() {
mostra_giocatore();
requestAnimationFrame(muovi);
}
window.document.onkeypress = interfaccia;
window.document.onkeyup = stop;
Your choppy movement is likely a result of the amount you are moving the player on each frame with VEL_GIOCATORE. Try reducing this amount to observe smoother movement.
The delay you are experiencing is likely due to your operating system or browsers individual settings on how key presses should repeat. You can work around this by implementing your own key tracking -- it looks like you've started to experiment with this. Track the state of your left and right keys by updating a boolean value in onkeydown and onkeyup event listeners.
var keys = {
left: false,
right: false
};
window.document.onkeydown = function (e) {
if (e.keyCode === 37) {
keys.left = true;
} else if (e.keyCode === 39) {
keys.right = true;
}
window.document.onkeyup = function (e) {
if (e.keyCode === 37) {
keys.left = false;
} else if (e.keyCode === 39) {
keys.right = false;
}
Then, in your muovi function, check the state of these variables to determine if you should update the position of the player.

mousewheel e.delta not working right in firefox?

I'm making a single-page website that reacts to mouse wheel events.
var supportsWheel = false;
function DoSomething (e) {
if (e.type == "wheel") supportsWheel = true;
else if (supportsWheel) return;
var delta = ((e.deltaY || -e.wheelDelta || e.detail) >> 10) || 1;
//if mousewheel is going up
if (delta > 0) {
slideDown();
}
//if mousewheel is going down
else if (delta < 0) {
slideUp();
}
}
document.addEventListener('wheel', DoSomething);
document.addEventListener('mousewheel', DoSomething);
document.addEventListener('DOMMouseScroll', DoSomething);
So this works perfectly in chrome and safari but in firefox, both directions of the mouse wheel activate slideDown() function. As opposed to declaring slideUp when the mouse wheel goes up and slideDown when it's going down. Any ideas how to fix it?
This is because you normalize deltaY = 0 as down, and that you probably have some smooth-scrolling set-up in Firefox, or in your OS:
This smooth scrolling feature will make your delta get linearly smaller, until they reach 0. So, when you initiate a Wheel event from your mouse/scrollpad, it will often end with an event which deltaY will be 0.
You can check this theory with this modified code, which will output the cases where the deltaY is 0 separately.
var supportsWheel = false;
function DoSomething(e) {
if (e.type == "wheel") supportsWheel = true;
else if (supportsWheel) return;
var e_delta = (e.deltaY || -e.wheelDelta || e.detail);
var delta = e_delta && ((e_delta >> 10) || 1) || 0;
if (delta > 0) {
slideDown();
} else if (delta < 0) {
slideUp();
} else if (!delta) {
donnotSlide();
}
}
document.addEventListener('wheel', DoSomething);
function slideDown() {
console.log('down');
}
function slideUp() {
console.log('up');
}
function donnotSlide() {
console.log('was zero');
}
Use your mouse wheel
But to say the truth, I don't really see why you do normalize this delta info... Usually you want to react to its values.

Speed up wheel scroll based event

I have a custom script which advances a small icon upon wheel scroll. It works well but it's not advancing the element as quickly as I would like. I'd like to increase the distance that the element (pill) moves per wheel scroll. How can I alter the code to facilitate this? Thanks for any insight. Code:
function wheel(e) {
var modelContentWrapper = $('.model-content-wrapper');
var howModelWorks_steps = $('#howModelWorks_steps');
var currentIndex = $('.model-content.active', modelContentWrapper).index();
var $pill = $('.step_' + (currentIndex + 1) + ' > a.clickable-icon');
var $li = $('ul.steps li');
var $pillStep = ($li.width()) / wheelSpeed;
direction = 'right';
if ((e.wheelDelta && e.wheelDelta >= 0) || (e.detail && e.detail < 0)) {
wheelValue++;
if ((firstElement && parseInt($pill.css('margin-left')) > initialIconLeft) || (!firstElement)) {
$pill.css('margin-left', (parseInt($pill.css('margin-left')) - $pillStep) + 'rem');
}
if (wheelValue >= wheelSpeed) {
wheelValue = wheelValue - wheelSpeed;
forceModelBackward();
}
//direction = 'left';
}
else {
wheelValue--;
//direction = 'right';
if (!lastElement) {
$pill.css('margin-left', (parseInt($pill.css('margin-left')) + $pillStep) + 'rem');
}
if (Math.abs(wheelValue) == wheelSpeed) {
wheelValue = wheelValue + wheelSpeed;
forceModelForward();
}
}
//if (wheelValue > (wheelSpeed * 5) || wheelValue < (wheelSpeed * -5)) {
if (stepsCounter == 1 || stepsCounter == 4) {
enableScroll();
}
preventDefault(e);
}
Try adding the follow to your event listener..
capture: true,
passive: true
Passive Event Listeners allow you to attach un-cancelable handlers to events, letting browsers optimize around your event listeners. The browser can then, for example, keep scrolling at native speed without waiting for your event handlers to finish executing.
Usage
Probably what is used mostly:
// Really, if you're using wheel, you should instead be using the 'scroll' event,
// as it's passive by default.
document.addEventListener('wheel', (evt) => {
// ... do stuff with evt
}, true)
You’ll need to replace it with this:
document.addEventListener('wheel', (evt) => {
// ... do stuff with evt
}, {
capture: true,
passive: true
})
Copied information from alligator dot io

KeyDown doesn't continuously fire when pressed and hold

I have this Plunkr,
This contains a div, on which I bind a keydown event. On pressing right or left arrow, the div should start moving.
This works, in all browsers, but when the key is pressed and hold, the first keydown event is fired immediately (div once moves), and it waits for a time gap, and then it continues to move.
So this means the keydown event is once fired, then the browser waits to detect if there is a subsequent keyUp event as well, then after a short time (when there is no keyup), it continues to fires keydown events.
(to see the problem, focus on window, press right arrow and hold, div should move once 5px, then wait, and then again continue to move)
Question: Is there a way around, so I can just keep the key pressed, and div should immediately start moving, without waiting to detect subsequent keyup (once)?
$(function() {
$(window).keydown(function(e) {
console.log(e.keyCode)
if (e.keyCode == 39)
move(5, 'left', $('.mover'))
else if (e.keyCode == 37)
move(-5, 'left', $('.mover'))
})
})
function move(offset, direction, target) {
console.log($(target))
$(target).css(direction, (parseInt($(target).css(direction)) + offset) + 'px')
}
.mover {
height: 50px;
width: 50px;
display: inline-block;
background: black;
position: absolute;
left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class='mover'></div>
I would suggest something on a timeout, like this
http://codepen.io/kevrowe/pen/qEgGVO
$(function() {
var direction,
movingTimeout = -1;
$(window).on('keydown', function(e) {
if (e.keyCode == 39) {
direction = 'right';
} else if (e.keyCode == 37) {
direction = 'left';
}
startMoving(direction);
});
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = -1;
}
function startMoving(direction) {
if (movingTimeout === -1) {
loop(direction);
}
}
function loop(direction) {
move(direction === 'left' ? -5 : 5, $('.mover'));
movingTimeout = setTimeout(loop, 10, direction);
}
function move(offset, $target) {
$target.css('left', (parseInt($target.css('left')) + offset) + 'px')
}
$(window).on('keyup', function(e) {
stopMoving();
});
})
When keydown event occurs on the key you want to track, then store this information in a mapping or a flag somewhere.
When keyup event occurs, then clear the flag for the given key.
Then, on a timer, you could poll the state of the key mapping, and move the object for whatever key direction is being pressed.
Possibly there is a better solution then polling, but I don't know of a way to test if a key is down other than polling.
On keyup, would also need to check if needed to interrupt moving the object.
One solution would be to just continuously run the move function in a loop until keyup happens
if (e.keyCode == 39){
var stop = setInterval(function(){
move(5, 'left', $('.mover'))
}, 25);
window.on("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.off("keyup", arguments.callee);
})
} else if //etc...
For those that might interest, here is another approach to handle bi-directional movement. Ex: up + right keys = "North East" direction :
const FPS = 60;
const STEP = 5;
const UP_KEY = 90; // Z
const DOWN_KEY = 83; // S
const LEFT_KEY = 81; // Q
const RIGHT_KEY = 68; // D
const pressedKeys = [];
let movingTimeout = null;
function handleKeyDown(e) {
pressedKeys[e.keyCode] = true;
switch(e.keyCode) {
case DOWN_KEY:
case LEFT_KEY:
case RIGHT_KEY:
case UP_KEY:
e.preventDefault();
startMoving();
}
}
function handleKeyUp(e) {
pressedKeys[e.keyCode] = false;
const shouldStop = !pressedKeys[UP_KEY]
&& !pressedKeys[DOWN_KEY]
&& !pressedKeys[LEFT_KEY]
&& !pressedKeys[RIGHT_KEY]
;
if(shouldStop) {
stopMoving();
}
}
function startMoving() {
if(!movingTimeout){
loop();
}
}
function stopMoving() {
clearTimeout(movingTimeout);
movingTimeout = null;
}
function loop() {
const x = pressedKeys[RIGHT_KEY] ? STEP
: pressedKeys[LEFT_KEY] ? -STEP : 0;
const y = pressedKeys[DOWN_KEY] ? STEP
: pressedKeys[UP_KEY] ? -STEP : 0;
move(x, y);
movingTimeout = setTimeout(loop, 1000 / FPS);
}
function move(x, y) {
// Implement you own logic here for positioning / handling collisions
// Ex: store.dispatch({ type: "MOVE_PLAYER", x, y });
console.log(`Moving ${x} ${y} !`);
}
window.addEventListener('keydown', e => handleKeyDown(e));
window.addEventListener('keyup', e => handleKeyUp(e));
Hope this helps.
Cheers !
pure javascript
<input id="some" type="text">
var input=document.getElementById("some");
input.addEventListener("keydown",function(e){
if (e.which == 40) {
var stop = setInterval(function(){
console.log("ss:");
}, 60);
window.addEventListener("keyup", function(){
//stop the loop
clearInterval(stop);
//and remove the keyup listener
window.removeEventListener("keyup", arguments.callee);
})
}
})

Swipe Events in Mobile Safari Intermittently Breaking

I'm trying to set up swipe events for a site I'm working on. Basically, when someone swipes the content container, child div elements of that will change content depending on the page one is on. The actual div "contentwrapper" that I am attaching the swipe listeners to does not change.
To do some animations, I have a previous and next page container that stores content. I removed the ajax function where I populate these for simplicity.
This works when going forwards but when going backwards, I seem to lose the preventDefault behavior and the whole page moves with my finger swipe. This problem only happens intermittently and aways when going backwards.
// Slightly modified code by Dave Dunkin
// http://rabblerule.blogspot.com/2009/08/detecting-swipe-in-webkit.html
function addSwipeListener(el, listener)
{
var startX;
var dx;
var direction;
function cancelTouch()
{
el.removeEventListener('touchmove', onTouchMove);
el.removeEventListener('touchend', onTouchEnd);
startX = null;
startY = null;
direction = null;
}
function onTouchMove(e)
{
if (e.touches.length > 1)
{
cancelTouch();
}
else
{
dx = e.touches[0].pageX - startX;
var dy = e.touches[0].pageY - startY;
if (direction == null)
{
direction = dx;
}
else if ((direction < 0 && dx > 0) || (direction > 0 && dx < 0) || Math.abs(dy) > 400)
{
cancelTouch();
}
}
}
function onTouchEnd(e)
{
cancelTouch();
if (Math.abs(dx) > 30)
{
listener({ target: el, direction: dx > 0 ? 'right' : 'left' });
dx = 0;
}
}
function onTouchStart(e)
{
e.preventDefault();
e.stopPropagation();
if (e.touches.length == 1)
{
startX = e.touches[0].pageX;
startY = e.touches[0].pageY;
el.addEventListener('touchmove', onTouchMove, false);
el.addEventListener('touchend', onTouchEnd, false);
}
}
el.addEventListener('touchstart', onTouchStart, false);
}
Add Swipe Listener
addSwipeListener(document.getElementById("contentwrapper"), function(e) {
swipePageChange(e);
});
function swipePageChange(e) {
if(e.direction == "left") {
moveforward();
}
if(e.direction == "right") {
movebackward();
}
}
Page Movement Events
function moveforward() {
$("#previouspagecontainer").css("z-index","20");
$("#newpagecontainer").css("z-index","40");
$("#previouspage").html($("#circular").html())
$("#newpagecontainer")[0].style.webkitAnimationName = 'flippageright';
$("#newpagecontainer")[0].addEventListener('webkitAnimationEnd', function() {
$("#currentpagecontainer").css("z-index","30");
$("#newpagecontainer")[0].style.webkitAnimationName = '';
$("#circular").html($("#nextpage").html());
});
return false;
}
function movebackward() {
$("#previouspagecontainer").css("z-index","40");
$("#currentpagecontainer").css("z-index","30");
$("#newpagecontainer").css("z-index","20");
$("#previouspagecontainer")[0].style.webkitAnimationName = 'flippageleft';
$("#previouspagecontainer")[0].addEventListener('webkitAnimationEnd', function() {
$("#previouspagecontainer")[0].style.webkitAnimationName = '';
$("#circular").html($("#previouspage").html());
});
return false;
}
The problem was caused by an unrelated element being removed from the DOM. I'm not quite sure why this resulted in breaking the swipe events but stopping this practice fixed my issue.

Categories

Resources