Hello allWhat I mean is while the mouse is moving towards the edge of the window (x or y or both), I want the page to scroll, and when the mouse stops moving, I want the page to stop scrolling.There are numerous examples of how to scroll based on using a onClick event or a scroll zone at the edge of a window, but not much based on the movement of the mouse cursor.
Any help would be much appreciated.
Web pages are already designed to scroll using the scroll bar, page/home/end/arrow keys, etc. Is there any reason that's insufficient for your page? It's usually not a good idea to alter expected functionality.
You can read up on the mousemove event here. Anyway, the code below should work, but I really don't recommend using it. It can be especially disorienting for people with sensitive mice:
// Variables for current position
var x, y;
function handleMouse(e) {
// Verify that x and y already have some value
if (x && y) {
// Scroll window by difference between current and previous positions
window.scrollBy(e.clientX - x, e.clientY - y);
}
// Store current position
x = e.clientX;
y = e.clientY;
}
// Assign handleMouse to mouse movement events
document.onmousemove = handleMouse;
Related
I'll try and keep it simple and I hope you can help.
var el1 = document.getElementById('el1');
var el2 = document.getElementById('el2');
window.addEventListener('mousemove',function(e){
var mouseX = e.offsetX;
var mouseY = e.offsetY;
var x = (mouseX + el1.offsetLeft) / 50;
var y = (mouseY + el2.offsetTop) / 50;
el1.style.transform = "translateX("+ x +"px) translateY("+ y +"px)";
el2.style.transform = "translateX("+ x +"px) translateY("+ y +"px)";
});
Simple function for a parallax effect but it fires on every dom element inside window.
So when it hits an inner DOM element the el1/el2 snap to a new position based on mouseover being fired.
How can I ensure the mousemove works on window and not the inner elements of the window?
Important note: I cannot apply pointer-events:none; because an inner element has href tag that needs to be used.
Your help is appreciated.
Thanks
Moe
offsetX/offsetY refers to the position relative to the element the mouse is currently over.
The offsetX read-only property of the MouseEvent interface provides the offset in the X coordinate of the mouse pointer between that event and the padding edge of the target node.
You are probably looking for clientX/clientY:
The clientX read-only property of the MouseEvent interface provides the horizontal coordinate within the application's client area at which the event occurred (as opposed to the coordinates within the page). For example, clicking in the top-left corner of the client area will always result in a mouse event with a clientX value of 0, regardless of whether the page is scrolled horizontally. Originally, this property was defined as a long integer.
It's more of a question really, but I don't know where to start with this one at all. I'm working on a site at the moment and we've cited the following sites as reference:
http://exhibitions.guggenheim.org/storylines/
http://www.apple.com/uk/start-something-new/
As you can see, both have the same effect and allow you to pan the 'canvas' within the viewport. I've search high and low but can't find any documentation or plugins for such a thing. The closest I found but it still doesn't allow you to pan with mouseMove is this: http://jmpressjs.github.io/jmpress.js/#/home
Like I say though, it's still quite far away from what I'm trying to achieve. Any thoughts, ideas, suggestions or plugins people might know of would be massively appreciated!
Pan canvas with mouse
You can pan the canvas with the ctx.translate(x,y) function, but this function is relative and can be tricky to use if you do not understand matrix math. Or with ctx.setTransform(1,0,0,1,x,y) where the last two numbers set the origin location on the canvas. This function is absolute so you do not need to track the current transformation matrix. The origin is the where coordinates 0,0 are.
Using setTransform
So if you set the the origin to
ctx.setTransform(1,0,0,1,canvas.width/2,canvas.height/2)
and then draw a circle at 0,0
ctx.beginPath();
ctx.arc(0,0,100,0,Math.PI*2);
ctx.fill();
it will appear in the center of the canvas as that is where the new origin is.
Implementing
Now all you need is to use the mouse to pan.
First create var to track the origin location
var originX = 0; // default to the top left of the canvas.
var originY = 0;
Depending on how you render the following will flag when to update the canvas transform
var panOnMouse = true; // if you are using requestAnimationFrame
// or another realtime rendering method this should
// be false
Then create a helper function to set the origin
function setCanvasOrigin(ctx){
ctx.setTransform(1,0,0,1,originX,originY);
}
The mouse
Now the mouse event listener and tracking the mouse movements First a object to hold mouse information.
var mouse = {
x : 0, // holds the current mouse location
y : 0,
lastX : null, // holds the previous mouse location for use when mouse down
lastY : null, // as this is unknown start with null
buttonDown : false, // true if mouse button down;
panButtonID : 1, // the id of the pan button 1 left 2 middle 3 right
}
Then create an event listener to get the mousemove, mousedown, and mouseup
function mouseEvent(event){
if(buttonDown){ // if mouse button is down save the last mouse pos;
mouse.lastX = mouse.x;
mouse.lastY = mouse.y;
}
mouse.x = event.offsetX;
mouse.y = event.offsetY;
if (mouse.x === undefined) { // for browsers that do not support offset
mouse.x = event.clientX;
mouse.y = event.clientY;
}
// now handle the mouse down
if (event.type === "mousedown" && event.which === mouse.panButtonID ) {
mouse.buttonDown = true; // flag the pan button is down;
mouse.lastX = mouse.x; // set the last pos to current
mouse.lastY = mouse.y;
}
// now do the pan is the mouse is down
//
if(mouse.buttonDown){
originX += mouse.x - mouse.lastX; // add the mouse movement to origin
originY += mouse.y - mouse.lastY;
if(panOnMouse ){
setCanvasOrigin(ctx);
}
}
// handle the mouse up only for the pan button
if (event.type === "mouseup" && event.which === mouse.panButtonID) {
mouse.buttonDown = false;
}
}
If you have panOnMouse as false then call setCanvasOrigin at the start of your main render loop.
All that is needed now is to add the mouse event listener to the canvas.
canvas.addEventListener("mousemove",mouseEvent);
canvas.addEventListener("mousedown",mouseEvent);
canvas.addEventListener("mouseup",mouseEvent);
Last notes
So now when the user clicks and drags with the correct mouse button the canvas origin will be dragged to where ever it is wanted. It can even be off screen. Just draw everything as you normally did.
To reset the pan just set the origin to zero
originX = 0; // default to the top left of the canvas.
originY = 0;
setCanvasOrigin(ctx); // set the transform
Because the origin has moved the mouse position on the canvas does not match the panned canvas coordinates. To get the position of the mouse over the panned canvas just subtract the origin from the mouse. You can add it to the end of the mouse event function
mouse.realX = mouse.x - originX; // get the mouse position relative to the
mouse.realY = mouse.y - originY; // panned origin
If the user moves off the canvas while panning you may lose the mouse up event and have the button stuck down. You can listen to mouseout and mouseover events to control what happen in those situations.
And that is how to pan the canvas with the mouse.
I am trying to create a canvas that allows me to draw on it rectangles using mouse events. Very similar to the way selection works in windows, I want to be able to click down anywhere on my page, drag left/right/up/down, then once I release, a rectangle is drawn with the starting coordinates (x1 and y1) on mousedown and the ending coordinates (x2, y2) on mouseup.
I've been trying to create eventListeners bound to my canvas that return the starting and ending coordinates on mousedown and mouseup respectively, but my variables stay undefined.
My canvas spans the entire length of my window so no need to take into account relative positioning. Also the solution has to be implemented using purely Javascript, no JQuery allowed.
Thank you for your help!
UPDATE
Ignore most of what is underneath, re-reading your question, it seems like you have the theory nailed. Your problem is most likely the mousedown and mouseup function parameters are missing. Try the following;
document.getElementsByTagName('canvas')[0].addEventListener('mousedown', function(e){
// I THINK IT'S THE e ON THE LINE ABOVE THIS THAT YOU'RE MISSING.
// YOU CAN THEN ACCESS THE POSITION OF THE MOUSE USING;
mouse.x = e.pageX;
mouse.Y = e.pageY;
})
I won't write the code for you, but I can give you theory.
Store your mouse x & y variables in an object such as mouse = {}.
Add an event listener to the canvas for mouse down (click) and store the e.pageX and e.pageY in mouse.firstX and mouse.firstY. Use something like:
document.getElementsByTagName('canvas')[0].addEventListener('mousedown', function(e){
mouse.firstX = e.pageX;
mouse.firstY = e.pageY;
})
Create a second event listener for the canvas for mouseup and store this set of e.pageX and e.pageY in mouse.secondX and mouse.secondY.
Calculate the difference between firstX and secondX, firstY and secondY to work out big your rectangle sound be.
var width = mouse.firstX + mouse.secondX // rect width
var height = mouse.firstY + mouse.secondY // rect height
Then, using these calculations, draw a rectangle on your canvas using firstX and firstY as the position parameters.
I hope this is relatively clear and helpful for you. If not, this might help;
http://simonsarris.com/blog/140-canvas-moving-selectable-shapes
I am trying to get the x and y of an html button to that of a mouseclick by the user, I am doing this as follows:
function buttonPressed(event, id){
var mainEvent = event ? event : window.event;
var mousex=event.clientX;
var mousey=mainEvent.screenY;
var y= $('#'+id).position();
var x= document.getElementById(id).offsetLeft;
console.log(y);
console.log(mousey);
This shows 2 different ways to get these value of both the button and the mouse (event.clientX,mainEvent.screenY,$('#'+id).position()(uses jquery),and offsetLeft).
However none of these techniques seem to work as I would like them to as the values do not line up ie when I click on the top left of the button the values are not the same or even similar. Additionally it seems like the difference changes, for example: if I have a button top left and one top right on the top left the values may differ by 100, whereas the bottom they will differ by -100. How can I acheive what I am wanting (to be able to compare the mousex and the button x)?
client X/Y Mouse pointer X/Y coordinate relative to window
offset X/Y Mouse pointer X/Y coordinate relative to element that fired the event
screen X/Y Relative to the top left of the physical screen/monitor
Thats why you are getting difference here
var mousex=event.clientX;
var mousey=mainEvent.screenY;
Use clientX for both
I'm designing user controls and I'm trying to code the controls for the mouse. This is what I came up with to get user input.
var mouseInput = new GLGE.MouseInput(window);
window.onmousemove = function(ev){
var dx = window.mouseX - prevMousePos.x;
var dy = window.mouseY - prevMousePos.y;
prevMousePos ={
x:window.mouseX,
y:window.mouseY
};
// I do movement calculations with dx and dy here
}
However what I came up with above isn't perfect because if the mouse reaches the end of the window it would not detect movement.
Is there a better way of detecting mouse movement? I'd rather not calculate it using its co-ordinates because using that method I'm unable to calculate distance moved when the mouse is at the edge of the screen.
PS: If anyone was wondering, what I'm designing is sorta like Google Streetview or a first person shooter. I just want the user to be able to move the mouse in one direction infinitely.
I mean, you're already using an onmuseover event handler (the most efficient way because Javascript is async). So you just compute distances from he previous, only when the user moves the mouse. If he doesn't further move the muse, the player just proceeds in the same direction prviously computed.
No, there is no method to handle mouse movements outside of the browser window.