Identify mouse events during requestPointerLock - javascript

Is there any way to identify right click event ("contextmenu") & scroll events while pointer lock API is enabled? I am trying to create a browser-based 3d game in which the player will be able to perform different activities by left clicking, right clicking, middle clicking and scrolling - while pointer is locked.
index.html
<body><button id="lock">Start game</button</body>
app.js
$("#lock").on("click", function(e) {
lockPointer(); // invokes the requestPointerLock API
e.stopPropagation();
});
// this works perfectly
$("body").on("click", function(e) {
// do stuff on left click
});
// this does not work
$("body").on("contextmenu", function(e) {
// do stuff on right click
});

For right click you can use mousedown or mouseup event, it works with requestPointerLock
$('body').on('mousedown', function(e) {
if (e.which === 1) {
// left button
} else if (e.which === 2) {
// middle button
} else if (e.which === 3) {
// right button
}
});
For scrolling you can use wheel event:
$('body').on('wheel', function(e) {
var dx = e.originalEvent.deltaX;
var dy = e.originalEvent.deltaY;
if (dy < 0) {
// scroll up
} else if (dy > 0) {
// scroll down
}
if (dx < 0) {
// scroll left (some mice support this)
} else if (dx > 0) {
// scroll right (some mice support this)
}
});

Related

jQuery - Multiple events, get deltaY for one event

I use two events (scroll and mousewheel).
I would like to get deltaY for mousewheel event to control a slider.
The variable getDelta returns numbers and undefined despite of my condition on mousewheel event.
I would like to get deltaY values outside.
What's wrong please ? Thank you in advance.
$(window).on('scroll mousewheel', function(e) {
if (e.type == "mousewheel") {
var getDelta = e.deltaY;
}
console.log(getDelta);
}
you put console log outside if condition.
$(window).on('scroll mousewheel', function(e) {
var getDelta;
if (e.type == "mousewheel") {
getDelta = e.deltaY;
}
if(getDelta)
{
console.log(getDelta);
}else{
console.log("delta is null");
}
}
The best way (in my view) to get your things done with deltaY / X is to use event listeners. They can be easily attached and detached - by human action or by some automatic trigger generated by your application / script.
Put the code below on a webpage and check if is OK for you.
<script>
// Getting delta trough event listeners
// then passing them as parameters to be consumed by other function(s)
function getDelta (e) // ... starting delta events capture
{
// We capture here both X and Y delta values (but you can use only deltaY) because
// some mice may have left and right buttons on the scroll wheel
// (Logitec g502 / Razer Basilisk / etc, ...)
console.log(e.deltaX + ' <- left right || up down -> ' + e.deltaY);
doSome(e.deltaY, e.deltaX); // ... the function which will consume events
}
function startDelta ()
{
document.addEventListener('wheel', getDelta);
}
function stopDelta () // we stop deltaX and deltaY capture
{
document.removeEventListener('wheel', getDelta);
}
function doSome (y, x) // we pass events as arguments so we can use them
{
if (x > 0)
console.log('some div with overflow will scroll left');
if (x < 0)
console.log('some div with overflow will scroll right');
if (y > 0)
console.log('some div with overflow will scroll up');
if (y < 0)
console.log('some div with overflow will scroll down');
}
</script>
<button onclick="startDelta()"> Start Delta </button>
<button onclick="stopDelta()"> Stop Delta </button>

How can I use a keydown event in a group?

I'm working on a group formed with rects and transformers, now there's a need to move it in ways other than the mouse. Using containers I can move it using the arrow keys but with the group the Keydown function does not work, I already tried using group.on without success.
I would like that when clicking the arrows would start to work in the group moving it.
You can't listen to keyboard event on canvas nodes (such as Group or Shape) with Konva. But you can easily emulate it.
You can make Stage node focusable and listen to keyboard events on it. Then do required action in an event handler.
var container = stage.container();
// make it focusable
container.tabIndex = 1;
// focus it
// also stage will be in focus on its click
container.focus();
const DELTA = 4;
container.addEventListener('keydown', function (e) {
if (e.keyCode === 37) {
circle.x(circle.x() - DELTA);
} else if (e.keyCode === 38) {
circle.y(circle.y() - DELTA);
} else if (e.keyCode === 39) {
circle.x(circle.x() + DELTA);
} else if (e.keyCode === 40) {
circle.y(circle.y() + DELTA);
} else {
return;
}
e.preventDefault();
layer.batchDraw();
});
Demo: https://konvajs.org/docs/events/Keyboard_Events.htm

Canceling a custom drag function when mouse slides off div

I have a draggable function in jquery to make it so I can drag and move elements on a div. Sometimes, when dragging the mouse comes off the div and I am not able to put back down the element.
I'm trying to add a keydown event for the escape button or something so that when pressed, the same thing happens on .on("mouseup", function(event) {
I've tried doing .on("mouseup keydown", function(event) { but it doesn't catch any keys that are being pressed.
Does anyone have any ideas on how I can cancel the drag? Either by a keydown or even on a mouseup regardless of if the mouse is on the div or not that is being dragged?
Just to be clear, the problem I am having is sometimes I will be dragging the element, I will mouseup but the mouse wasn't on the element when mouseup was called. Therefore, the element is still dragging and I no longer have my finger on the mouse and I have no way to stop the element from dragging to get it back on the document.
EDIT: Here is a jsfiddle, notice I am trying to get this to work on a scaled container. youtube video showing drag glitch
(function($) {
$.fn.drags = function(opt, callback) {
opt = $.extend({
handle: "",
cursor: "move"
}, opt);
if (opt.handle === "") {
var $el = this;
} else {
var $el = this.find(opt.handle);
}
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
if (opt.handle === "") {
var $drag = $(this).addClass('draggable');
} else {
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
}
var z_idx = $drag.css('z-index'),
drg_h = $drag.outerHeight(),
drg_w = $drag.outerWidth(),
pos_y = $drag.offset().top + drg_h - e.pageY,
pos_x = $drag.offset().left + drg_w - e.pageX;
$drag.css('z-index', 1000).parents().on("mousemove", function(e) {
$('.draggable').offset({
top: e.pageY + pos_y - drg_h,
left: e.pageX + pos_x - drg_w
}).on("mouseup", function() {
$(this).removeClass('draggable').css('z-index', z_idx);
});
});
e.preventDefault();
}).on("mouseup", function(event) {
if (opt.handle === "") {
$(this).removeClass('draggable');
} else {
$(this).removeClass('active-handle').parent().removeClass('draggable');
}
if (typeof callback == 'function') {
alert("this is a callback");
}
});
}
})(jQuery);
Here are a few things that might work:
Instead of listening for mouseup on the target element, listen for it on document.body. That way it will fire regardless of if the cursor is over the dragged element.
If you want to cancel the drag when the cursor wanders out of the page, add an event listener for mouseleave on document.body and use it to cancel the drag.
If you make a code-pen (or similar) test case, I will be happy to dig into the code.
Edit__
Handling mouseleave on the document prevents it from getting stuck in a draggable state. It also fixes the multiplied movement that you were seeing.
$(document.body).on('mouseleave', function(){
$el.removeClass('draggable').css('z-index', z_idx);
});
Edit2__
Previous JSFiddle was incorrect.
https://jsfiddle.net/spk4523t/6/

How to determine scroll direction without actually scrolling

I am coding a page where the first time the user scrolls, it doesn't actually scroll the page down, instead it adds a class with a transition.
I'd like to detect when the user is scrolling down, because if he scrolls up, I want it to do something else.
All the methods that I've found are based on defining the current body ScrollTop, and then comparing with the body scrollTop after the page scrolls, defining the direction, but since the page doesn't actually scroll, the body scrollTop() doesn't change.
animationIsDone = false;
function preventScroll(e) {
e.preventDefault();
e.stopPropagation();
}
$('body').on('mousewheel', function(e) {
if (animationIsDone === false) {
$("#main-header").removeClass("yellow-overlay").addClass("yellow-overlay-darker");
$(".site-info").first().addClass("is-description-visible");
preventScroll(e);
setTimeout(function() {
animationIsDone = true;
}, 1000);
}
});
This is what I have come with, but that way it doesn't matter the direction I scroll it triggers the event
The mousewheel event is quickly becoming obsolete. You should use wheel event instead.
This would also easily allow you to the vertical and/or horizontal scroll direction without scroll bars.
This event has support in all current major browsers and should remain the standard far into the future.
Here is a demo:
window.addEventListener('wheel', function(event)
{
if (event.deltaY < 0)
{
console.log('scrolling up');
document.getElementById('status').textContent= 'scrolling up';
}
else if (event.deltaY > 0)
{
console.log('scrolling down');
document.getElementById('status').textContent= 'scrolling down';
}
});
<div id="status"></div>
Try This using addEventListener.
window.addEventListener('mousewheel', function(e){
wDelta = e.wheelDelta < 0 ? 'down' : 'up';
console.log(wDelta);
});
Demo
Update:
As mentioned in one of the answers, the mousewheel event is depreciated. You should use the wheel event instead.
I know this post is from 5 years ago but I didn't see any good Jquery answer (the .on('mousewheel') doesn't work for me...)
Simple answer with jquery, and use window instead of body to be sure you are taking scroll event :
$(window).on('wheel', function(e) {
var scroll = e.originalEvent.deltaY < 0 ? 'up' : 'down';
console.log(scroll);
});
Try using e.wheelDelta
var animationIsDone = false, scrollDirection = 0;
function preventScroll(e) {
e.preventDefault();
e.stopPropagation();
}
$('body').on('mousewheel', function(e) {
if (e.wheelDelta >= 0) {
console.log('Scroll up'); //your scroll data here
}
else {
console.log('Scroll down'); //your scroll data here
}
if (animationIsDone === false) {
$("#main-header").removeClass("yellow-overlay").addClass("yellow-overlay-darker");
$(".site-info").first().addClass("is-description-visible");
preventScroll(e);
setTimeout(function() {
animationIsDone = true;
}, 1000);
}
});
Note: remember that MouseWheel is deprecated and not supported in FireFox
this one work in react app
<p onWheel={this.onMouseWheel}></p>
after add event listener, in function u can use deltaY To capture mouse Wheel
onMouseWheel = (e) => {
e.deltaY > 0
? console.log("Down")
: console.log("up")
}
Tested on chrome and
$('body').on('mousewheel', function(e) {
if (e.originalEvent.deltaY >= 0) {
console.log('Scroll up'); //your scroll data here
}
else {
console.log('Scroll down'); //your scroll data here
}
});

mimicking iPhone main screen slide in JavaScript

I'd like to mimick iPhone main screen in JavaScript on Safari / Chrome / Firefox.
By mimicking I mean:
- Having a couple of pages
- Switching between the pages by clicking & dragging / swiping with my mouse
- Having those dots from the bottom iPhone main screen displaying which page it is
The closest to what I want is:
http://jquery.hinablue.me/jqiphoneslide/
But the sliding doesn't work nearly as good as in iPhone (i have to slide first, and the animation appears after i release the mouse button), and there are no dots at the bottom.
I solved the problem by using jQuery & jquery.slide-0.4.3.js .
jQuery Slide automatically slides between each page, so I had to add a mouse event (onMouseDrag) that stops automatic slide & reacts to user. It works very well.
This is what I added to jSlide
var jSlide = function(element, options)
{
element = $(element);
$('ul.layers li', element).sliderDisableTextSelect();
// my code here
var dragging = false;
var srcX;
var offsetX;
var diff;
this.manualDown = function(event) {
dragging = true;
srcX = event.pageX;
offsetX = parseFloat($('ul.layers li', element).css('marginLeft'));
obj.settings.easing = "easeOutExpo";
if(obj.settings.loopNr != null) {
obj.toggleLoop(0);
};
return false;
};
this.manualMove = function(event) {
if (dragging) {
diff = event.pageX - srcX;
$('ul.layers li', element).css('marginLeft',(offsetX+diff)+'px');
console.log((offsetX+diff)+'px');
};
return false;
};
this.manualUp = function(event) {
if (dragging) {
dragging = false;
if ((diff<-obj.settings.layerWidth/5) && (obj.settings.slidePos<obj.settings.layersSize-1)) {
obj.slideTo(parseInt(obj.settings.slidePos)+1);
} else if ((diff>obj.settings.layerWidth/5) && (obj.settings.slidePos>0)) {
obj.slideTo(parseInt(obj.settings.slidePos)-1);
} else { // if not slid far enough nor is it the last slide
obj.slideTo(obj.settings.slidePos);
};
};
};
this.manualLeave = function(event) {
if (dragging) {
dragging = false;
if ((diff<0) && (obj.settings.slidePos<obj.settings.layersSize-1)) {
obj.slideTo(parseInt(obj.settings.slidePos)+1);
} else if ((diff>0) && (obj.settings.slidePos>0)) {
obj.slideTo(parseInt(obj.settings.slidePos)-1);
} else { // if it's the last slide
obj.slideTo(obj.settings.slidePos);
};
};
};
element.mousedown(this.manualDown);
element.mousemove(this.manualMove);
element.mouseup(this.manualUp);
element.mouseleave(this.manualLeave);
And also, to prevent text selection when dragging with mouse I added before jSlide class declaration:
$.extend($.fn.disableTextSelect = function() {
return this.each(function(){
if($.browser.mozilla){//Firefox
$(this).css('MozUserSelect','none');
}else if($.browser.msie){//IE
$(this).bind('selectstart',function(){return false;});
}else{//Opera, etc.
$(this).mousedown(function(){return false;}); // this is handled in jSlide
}
});
});
$.extend($.fn.sliderDisableTextSelect = function() {
return this.each(function(){
if($.browser.mozilla){//Firefox
$(this).css('MozUserSelect','none');
}else if($.browser.msie){//IE
$(this).bind('selectstart',function(){return false;});
}else{//Opera, etc.
// $(this).mousedown(function(){return false;}); // this is handled in jSlide
}
});
});
I'm not sure if all the code is necessary... most probably you'll still need to tweak it after pasting into jquery.slide, but it should get you started..

Categories

Resources