JavaScript - Make window scrollbar follow mouse - javascript

How can I make the windows scrollbar's Y coordinate be the same as the mouse Y coordinate, how
can I make the scrollbar follow the mouse?

The most compute efficient using way of doing this utilizing DOM-L3:
//HTML BLOCK
<canvas onmousemove="TrackMouse(event)"></canvas>
//JS BLOCK
function TrackMouse(e){
window.scrollBy(e.webkitMovementX, e.webkitMovementY);
}

Here is a jQuery-free solution:
var height = document.documentElement.scrollHeight;
function scroll(event){
var y = event.clientY;
var yPercentage = y/screen.height;
window.scrollTo(0,yPercentage*height);
}
window.onmousemove = scroll;
In action: http://jsfiddle.net/xF2vs/3/
On a real page, if your mouse is at the bottom of the screen, the page will be scrolled entirely to the bottom. For some reason in jsfiddle it doesn't quite make it.
What it is doing is finding how far down your mouse is on the screen and scrolling the document down that same percent.

Sharing my modified version Nile's reply to get a version that scrolls both X and Y.
var height = document.documentElement.scrollHeight;
var width = document.documentElement.scrollWidth;
function scroll(event) {
var y = event.clientY;
var x = event.clientX;
var yPercentage = y / screen.height;
var xPercentage = x / screen.width;
window.scrollTo(xPercentage * width, yPercentage * height);
}
window.onmousemove = scroll;
To scroll just the width, but not the height (as Murplyx requested a year ago) use the following:
var width = document.documentElement.scrollWidth;
function scroll(event) {
var x = event.clientX;
var xPercentage = x / screen.width;
window.scrollTo(xPercentage * width, 0);
}
window.onmousemove = scroll;
Thank you Nile for the start!

Related

Fabric JS getContext('2d') not matching getImageData color

Website: http://minimedit.com/
Currently implementing an eye dropper. It works fine in my normal resolution of 1080p, but when testing on a higher or lower resolution it doesn't work.
This is the basics of the code:
var ctx = canvas.getContext("2d");
canvas.on('mouse:down', function(e) {
var newColor = dropColor(e, ctx);
}
function dropColor(e, ctx) {
var mouse = canvas.getPointer(e.e),
x = parseInt(mouse.x),
y = parseInt(mouse.y),
px = ctx.getImageData(x, y, 1, 1).data;
return rgb2hex('rgba('+px+')');
}
When I first initiate the canvas I have it resize to fit resolution:
setResolution(16/9);
function setResolution(ratio) {
var conWidth = ($(".c-container").css('width')).replace(/\D/g,'');
var conHeight = ($(".c-container").css('height')).replace(/\D/g,'');
var tempWidth = 0;
var tempHeight = 0;
tempHeight = conWidth / ratio;
tempWidth = conHeight * ratio;
if (tempHeight > conHeight) {
canvas.setWidth(tempWidth);
canvas.setHeight(conHeight);
} else {
canvas.setWidth(conWidth);
canvas.setHeight(tempHeight);
}
}
The x and y mouse coordinates work fine when zoomed in, but they don't line up with the returned image data. It seems as though the ctx isn't changing it's width and height and scaling along with the actual canvas size.
The canvas element is showing the correct width and height before using getContext as well.
Any ideas on a solution?
Feel free to check out the full scripts on the live website at: http://minimedit.com/
Try "fabric.devicePixelRatio" for calculating actual position, for example:
x = parseInt(mouse.x) * fabric.devicePixelRatio

Canvas click events screwed up when browser window shrinks/moves

I've been playing around with creating a hexagonal grid in HTML5 Canvas. I have a basic grid, where if you click a hex it will highlight the hex (demo here: http://cfiresim.com/hex-map-game-reboot/test.html)
In javascript, I am defining the canvas as such (some parts omitted for brevity):
var hex = {};
hex.canvas = document.getElementById("HexCanvas");
hex.ctx = null;
console.log("Initializing new game...");
this.radius = 20;
this.side = Math.round((3 / 2) * this.radius);
this.height = Math.round(Math.sqrt(3) * this.radius);
this.width = Math.round(2 * this.radius);
//Set Size of main div to size of canvas
$('#primary-panel').css('height', (hex.height * hex.rows)+hex.height*2);
hex.canvas.style.width='100%';
hex.canvas.style.height='100%';
hex.canvas.width = hex.canvas.offsetWidth;
hex.canvas.height = hex.canvas.offsetHeight;
//Set click eventlistener for canvas
this.canvas.addEventListener("mousedown", this.clickEvent.bind(this), false);
this.ctx = this.canvas.getContext('2d');
All of the code can be found here: https://github.com/boknows/hex-map-game-reboot
My primary question is: Is there a specific way to prevent the click events from getting all screwy when the canvas is resized via the browser? For example, if you shrink the browser to be just bigger than the grid, clicks dont register in the right place. Am I missing some feature of canvas? Maybe getSelectedTile() is not being defined correctly?
Edit: It seems like this primarily happens when the browser scrolls a little, and thus moves the grid off screen. The clicks then register with a weird offset, which I'm guessing is equal to the distance the screen scrolled. Advice?
You must take into a position of a page scroll.
In HexagonGrid.js, instead of this:
hex.clickEvent = function(e) {
var mouseX = e.pageX;
var mouseY = e.pageY;
Do this:
hex.clickEvent = function(e) {
var mouseX = e.pageX - window.pageXOffset;
var mouseY = e.pageY - window.pageYOffset;

Why are the rectangles I am creating on this canvas not getting put in the right spot?

I am trying to create a simple page where you click and can create rectangles on a canvas. It takes the user's mouse clicks as input, and then creates a rectangle from the x and y of the click. However, it places the rectangle off to the side by some amount, and I am not sure why.
Fiddle: https://jsfiddle.net/2717s53h/
HTML
<canvas id="cnv"></canvas>
CSS
#cnv{
width:99vw;
height:98vh;
background-color:#faefbd;
}
JAVASCRIPT
$(function () {
var canvas = $('#cnv');
var canvObj = document.getElementById('cnv');
var ctx = canvObj.getContext('2d');
var point1 = {};
var point2 = {};
canvas.click(function (e) {
console.log(e);
var x = e.pageX;
var y = e.pageY;
console.log(x);
console.log(y);
if (Object.keys(point1).length == 0)
{
point1.x = x;
point1.y = y;
}
else if (Object.keys(point2).length == 0)
{
point2.x = x;
point2.y = y;
console.log(point1);
console.log(point2);
var width = point2.x - point1.x;
var height = point2.y - point1.y;
width = width < 0 ? width * -1 : width;
height = height < 0 ? height * -1 : height;
ctx.fillRect(x, y, 10, 10);
point1 = {};
point2 = {};
}
});
});
There is a difference between the CSS height/ width and the HTML canvas attributes height and width: the former defines the space the canvas occupies in the page; the latter defines the rendering surface. In concreto, suppose you have the following canvas:
<canvas height="400" width="600"></canvas>
with a viewport of a 1200x800 size and the canvas' CSS is set to width: 100%; height: 100%;, then your canvas will be rendered as stretched out twice as big and blurry in both height and width (like in your fiddle; clearly those rectangles are bigger than 10px). As a consequence, the page coordinates are not in sync with the canvas' coordinates.
As per the specification, your fiddle's canvas rendering surface is 300x150 because you didn't specify the width/height attributes:
The width attribute defaults to 300, and the height attribute defaults to 150.
See a slightly 'corrected' version of your fiddle.
As a result my advice (as a non-expert on HTML-canvas) would be to always specify those 2 attributes and not to mess with different rendering surface vs. display dimensions (certainly not relative ones like vw, vh, %, em, ...) if you don't want unpredictable results; although some SO users have been looking for a solution.

How to center a new div based on mouse cursor

Hi I am trying to place a div in the center of my mouse course when I click a link
I have something like
<a id='btn' href='#' ><img src='test.png' /></a>
I want to see the new div overlay on my test.png and I want my mouse curse be the center vertically and horizontally of the new div.
My js
var contentDiv = document.createElement('div');
var img = document.createElement('img');
contentDiv.setAttribute('class','test1');
img.src='newimg.png';
contentDiv.appendChild(img);
$("#btn").on('click', function(e){
$('body').append(contentDiv)
var w = $(contentDiv).width()/2
var h = $(contentDiv).height()/2
var x = e.pageX - h //- $(this).offset().left;
var y = e.pageY - w //- $(this).offset().top;
$(contentDiv).css({top: y, left: x, 'transform': 'scale(.2)'})
e.preventDefault();
})
My code won't put my mouse cursor as the center of the new div. Can anyone help me about it? Thanks so much!
Try
var x = e.pageX - w
var y = e.pageY - h
Example
That's the jQuery way to get the mouse position (e.pageX), so you could also do:
var x = e.clientX - w;
var y = e.clientY - h;
Example
That's the pure-JS way.
Your problem was you were subtracting height from x and width from y, while it should be the other way around. Remember, x is left and right, y is up and down. In computer science, up decreases y, and down increases y, right increases x, left decreases x.
Don't get them mixed up.

Mouse on left of screen move image to left, same when mouse on right of screen

I'm trying to get an image that is around 1920x1200px to pan around on a 800x600px browser window.
So if my mouse is on the top-left of the browser window the image is alined so it's top-left margins are on the top-left of the browser window. The same goes for the bottum-right.
So if the mouse is in the centre of the screen the image should be centered too.
Im not sure what calculations are needed as my math is a bit rusty.
Currently I'm using a bit of javascript that just moves the image using CSS's top/left properties but without much success as it's just moving the picture around from it's top/left corner.
I'v also set the image's position to absolute in css.
function updateImgPosition( e )
{
var avatar = document.getElementById("avatar");
// Width
var windowWidth = window.innerWidth;
var mouseWidthLocation = e.x;
var percentOfWidth = (100 / windowWidth) * mouseWidthLocation;
// Height
var windowHeight = window.innerHeight;
var mouseHeightLocation = e.y;
var percentOfHeight = (100 / windowHeight) * mouseHeightLocation;
avatar.style.top = percentOfHeight + "%";
avatar.style.left = percentOfWidth + "%";
}
document.onmousemove = updateImgPosition;
This is a demo of what I have: http://jsfiddle.net/uQAmQ/1/
Fiddle: http://jsfiddle.net/uQAmQ/2/
You should not "pan" on an absolutely positioned element, because the window's width and height keep changing according to the image. A smoother solution involves using a background image. See the middle of my answer for the used logic.
Consider this JavaScript (read comments; HTML + CSS at fiddle):
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var avatar = document.getElementById("avatar");
var avatarWidth = avatar.width;
var avatarHeight = avatar.height;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
/* Logic: Move */
var ratioY = (avatarHeight - windowHeight) / windowHeight;
var ratioX = (avatarWidth - windowWidth) / windowWidth;
function updateImgPosition( e ) {
var mouseY = e.pageX; //e.pageX, NOT e.x
var mouseX = e.pageY;
var imgTop = ratioY*(-mouseY);
var imgLeft = ratioX*(-mouseX);
document.body.style.backgroundPosition = imgLeft + "px " + imgTop + "px";
}
/* Add event to WINDOW, NOT "document"! */
window.onmousemove = updateImgPosition;
})();
The logic behind it:
Relative units cannot be used, because the image size is specified in absolute units.
The offsets should change according to a specific ratio, which is similar to: image size divided by window size.However, this ratio is not complete: The image would disappear at the bottom/left corner of the window. To fix this, substract the window's size from the image's size. The result can be found in the code at variable ratioX and ratioY.
The previous code had to be loaded at the window.onload event, because the image's size was dynamically calculated. For this reason, a HTML element was also included in the body.
The same code can be written much smaller and efficient, by specifying the size of the background in the code. See this improved code. Fiddle: http://jsfiddle.net/uQAmQ/3/
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var avatarWidth = 1690;
var avatarHeight = 1069;
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
/* Logic: Move */
var ratioY = (avatarHeight - windowHeight) / windowHeight;
var ratioX = (avatarWidth - windowWidth) / windowWidth;
function updateImgPosition( e ) {
var mouseX = e.pageX; //e.pageX, NOT e.x
var mouseY = e.pageY;
var imgTop = ratioY*(-mouseY);
var imgLeft = ratioX*(-mouseX);
document.body.style.backgroundPosition = imgLeft + "px " + imgTop + "px";
}
/* Add event to WINDOW, NOT "document"! */
window.onmousemove = updateImgPosition;
})();
If you don't mind a decreased code readability, the following code is the best solution, Fiddle: http://jsfiddle.net/uQAmQ/4/:
(function(){ //Anonymous function wrapper for private variables
/* Static variables: Get the true width and height of the image*/
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var ratioY = (windowHeight - 1069) / windowHeight;
var ratioX = (windowWidth - 1690) / windowWidth;
window.onmousemove = function( e ) {
document.body.style.backgroundPosition = ratioX * e.pageX + "px " + ratioY * e.pageY + "px";
}
})();

Categories

Resources