Move browser with mouse - javascript

I am looking to try and do something like this where the content is off the screen and when you move the mouse the browser follows it around. I was thinking it would be similar to this where the edge of the screen animates when the mouse moves.
It looks like in the original example they use JS to change the transform: matrix. On the second link the screen is animated using greensock and the following code to change the CSS:
// Mouse move tilt effect
$(document).mousemove(function(event){
// Detect mouse position
var xPos = (event.clientX/$(window).width())-0.5;
var yPos = (event.clientY/$(window).height())-0.5;
// Tilt the hero container
TweenLite.to($hero, 0.6, {rotationY:5*xPos, rotationX:5*yPos, ease:Power1.easeOut, transformPerspective:900, transformOrigin:"center"});
// Update text on the page with the current mouse position
$(".bottom strong").text(event.pageX + ", " + event.pageY);
});
Is it possible to do something similar to do what I need?

Based on how I understood your intentions basically what you need to do is.
Create a div container which has width and height greater than window size and fill it up with content
Create div container which has width and height equal to window and overflow: hidden and contains the container in 1.
Center container in 1 in 2 with transform: translateX(-25%) translateX(-25%); and transition: transform 1s;
After that
Detected mouse position
Calculate distance from center of window
And based on that add or remove up to 25% to the translateX and translateY value
EDIT:
document.querySelector('body').style.transition = 'transform 1s';
window.addEventListener('mousemove', event => {
const absMaxX = window.innerWidth / 2;
const absMaxY = window.innerHeight / 2;
const maxDistance = Math.sqrt(Math.pow(absMaxX, 2) + Math.pow(absMaxY, 2));
const mouseX = event.clientX;
const mouseY = event.clientY;
const directionX = mouseX - absMaxX >= 0 ? 1 : -1;
const directionY = mouseY - absMaxY >= 0 ? 1 : -1;
const distance = Math.sqrt(Math.pow(mouseX - absMaxX, 2) + Math.pow(mouseY - absMaxY, 2))
const translation = distance / maxDistance * 100;
document.querySelector('body').style.transform =
`translateX(${directionX * translation}px) translateY(${directionY * translation}px)`
});

Related

How can I maintain accurate rectangle hover detection after scaling a canvas?

I am writing an application that draws rectangles on a HTML canvas using the fillRect function. I currently track the movement of the mouse and detect when the mouse pointer hovers over a rectangle to highlight it:
This is how I am currently detecting collision which works great.
//boxes2 is my array of rectangles
var l = boxes2.length;
for (var i = l - 1; i >= 0; i--) {
if (mouseX >= boxes2[i].x && mouseX <= (boxes2[i].x + boxes2[i].w ) &&
mouseY >= boxes2[i].y && mouseY <= (boxes2[i].y + boxes2[i].h )) {
selectedBoxNum = i;
}
}
My problem is that this hover detection no longer works well after zooming in/out as the actual bounds of the rectangles desync from their values in my rectangle array.
var currentZoomValue = 1;
function myOnMouseWheel(event) {
event.preventDefault();
// Normalize wheel to +1 or -1.
var wheel = event.wheelDelta / 120;
if (wheel == 1) {
zoom = 1.1;
}
else {
zoom = .9;
}
currentZoomValue = currentZoomValue * zoom
canvas.style.transform = "scale(" + currentZoomValue + ")";
}
What I have tried:
Scaling the values in the array as I zoom in/out so that the rectangle bounds will stay in sync
This will not work for me because the scale function is stretching my canvas to make the rectangles look bigger. If I also actually make them bigger, they will be doubly enlarged and outpace the zoom of my canvas background.
Compensating my hover detection based upon my current zoom level
I have tried something like:
if (mouseX >= boxes2[i].x && mouseX <= (boxes2[i].x + (boxes2[i].w * currentZoomValue) ) &&
mouseY >= boxes2[i].y && mouseY <= (boxes2[i].y + (boxes2[i].h * currentZoomValue) )) {
selectedBoxNum = i;
}
My attempts at this do not work because while the rectangle height and width do scale in an easily predictable way, the x,y coordinates do not. When zooming in, the rectangles will radiate out from the center so some rectangles will gain x value and other lose based upon their position. I also considered maintaining a second rectangle array that I could use just for hover detection but decided against it for this reason.
A good solution would be to actually scale the rectangle's sizes to give the illusion of zooming, but the rectangles positions on the background image is important, and this technique will not affect the background.
Since there is no standard way of knowing page zoom level, I would suggest catching the click event with an absolutely-positioned div.
You can get the offset of your canvas element with the getBoundingClientRect() method.
Then, the code would look something like this:
boxes2.forEach(function(box, i) {
cx.fillRect(box.x, box.y, box.w, box.h);
/* We create an empty div */
var div = document.createElement("div");
/* We get the position of the canvas */
var rect = canvas.getBoundingClientRect();
div.style.position = "absolute";
div.style.left = (rect.left + box.x) + "px"; //Don't forget the pixels!!!
div.style.top = (rect.top + box.y) + "px";
div.style.width = box.w + "px";
div.style.height = box.h + "px";
/* For demonstration purposes we display a border */
div.style.border = "1px dashed black"
div.onclick = function() {/* Your event handler */}
document.body.appendChild(div);
});
Here's a live demonstration. At least in my browser, regions stay consistent even if I zoom in and out the page.

How to position the center of a div to the center of the mouse cursor on mouse movement with JS?

I'm trying to position the center of a div element to the center of the mouse cursor, that will follow along its movements.
Already I came up with the code below, but the problem with this one is, that the following div is not positioned at the center of my cursor, but with some offset off the cursor.
WORKFLOW
The basic idea behind my code is, when the mouse enters the .post-entry div element, the .pointer within the current item should be displayed and follow the cursor of the mouse. When the mouse leaves the div it should be hidden.
CODE
HTML post item:
<article class="col-md-4 col-sm-6 post-entry">
<a href="#" title="">
<figure class="post-thumb">
<img src="http://placehold.it/300x300" alt="">
<div class="pointer" style="background: red;"></div>
</figure><!-- End figure.post-thumb -->
</a>
</article><!-- End article.col-md-4 post-entry -->
JS:
$('.entry .post-entry').each(function() {
$(this).on("mouseenter", mouseEnter);
$(this).on("mousemove", mouseMove);
$(this).on("mouseleave", mouseLeave);
});
function mouseEnter(event) {
console.log('enter');
var target = $(this);
var dot = target.find('.pointer');
var mX = (event.clientX);
var mY = (event.clientY);
set(
dot, {
x: mX,
y: mY,
force3D: !0
}
);
};
function mouseMove(event) {
console.log('move');
var target = $(this);
var dot = target.find('.pointer');
// var offset = target.offset();
// var width = target.width();
// var height = target.height();
// var top = offset.top;
// var left = offset.left;
var mX = (event.clientX);
var mY = (event.clientY);
$(dot).css('-webkit-transform', 'translate3d(' + mX + 'px, ' + mY + 'px, 0)');
};
function mouseLeave(event) {
console.log('leave');
var target = $(this);
var dot = target.find('.pointer');
$(dot).css('-webkit-transform', 'translate3d(0, 0, 0) scale(0, 0)');
};
function onClick(event) {
event.preventDefault();
console.log('click');
};
function set(el, obj) {
var dot = $(el).css('-webkit-transform', 'translate3d(' + obj.x + 'px, ' + obj.y + 'px, 0px)');
return dot;
};
PROBLEM / DEMO
As mentioned before, the span is following the mouse cursor, only the span is not positioned to the center of the cursor. It will be offset the mouse. See live demo here
I tried already something like this for the mX and mY variables, but with no succes:
var mX = (event.clientX - $(this).offset().left) / $(this).width() * $(this).width() - .125 * $(this).width();
var mY = (event.clientY - $(this).offsetTop) / $(this).height() * $(this).height() - .125 * $(this).width();
Also the answer from #hiEven doesn't work and will let me with the same issue:
transform: calc(mX - 50%, mY - 50%)
I know I should do something with dividing the .pointer by half, but how I should implement that in the code is a big question mark for me.
UPDATE
I created two new Codepen projects:
Use without images: http://codepen.io/anon/pen/GqGOLv. When you hover over the first item you will see that the brown pointer is correctly following your mouse cursor - what I am looking for. But when hovering over the second one, you will see the red pointer, only when you are at the very left side of the item.
When I use images: http://codepen.io/anon/pen/QExOkx. The problem by this example is that when you at the very top of the first column, you will see the brown pointer. When hover at the top left corner of the second item you will see a little piece of the red pointer, the same as the example without images.
Both pointer should follow the mouse cursor correctly. And I am searching for a solution that works with the use of an image.
Beside these two examples, when I add to the first one, an extra margin-left to the first item, the brown pointer will not be in the center of the mouse cursor, only when it's set to margin-left zero.
So I don't know what's missing and why it only works with the first example (without images) and only for the first item?
Try the code below
<html>
<head>
<style>
#mouse_div{
position: absolute;
background-color: black;
}
</style>
<script>
var div_width = 100;
var div_height = 100;
var div_x, div_y;
function mouse_position(event){
var mouse_x = event.clientX;
var mouse_y = event.clientY;
document.getElementById("mouse_div").style.width = div_width + "px";
document.getElementById("mouse_div").style.height = div_height + "px";
div_x = mouse_x - (div_width / 2);
div_y = mouse_y - (div_height / 2);
document.getElementById("mouse_div").style.left = div_x + "px";
document.getElementById("mouse_div").style.top = div_y + "px";
}
</script>
</head>
<body onmousemove="mouse_position(event)" onload="mouse_position(event)">
<div id="mouse_div"></div>
</body>
</html>
This program gets the position of your mouse, the width, and the height of the div. Then, it takes the x and subtracts the div's width divided by two from it (this centres the div's x position on your mouse). The program then does the same thing for the mouse y. Once all of the variables are defined, I use JavaScript to access the CSS of the div to place the div where it needs to be.
Note: you must make sure that the position of the div is set to absolute or the program will not work.
I assume you want the circle being center of your mouse, right?
try do this
transform: `translate(calc(${mx}px - 50%), calc(${my}px - 50%))
here is the demo
Based on my latest update, I did not conform to the correct formula that is needed to center the element .pointer to the mouse.
In order to use the following calculation within mouseMove:
var mX = (event.clientX);
var mY = (event.clientY);
Should be changed to this:
var height = dot.height();
var width = dot.width();
var offset = target.offset();
var w = target.width();
var h = target.height();
var top = offset.top;
var left = offset.left;
var mX = (event.clientX - left) - width / 2 - 15; // 15 = padding
var mY = (event.clientY - top) - height / 2;
So this formule is considering that the following DOM element .pointer will follow the mouse movements of the user. I don't know exactly why this working, but the offset from the previous item will be decreased from the current clientX coordinates, so the position of the second item is reset to zero, so the pointer will start at the left side of each item.
Here is a working demo of above code: http://codepen.io/anon/pen/AXdxZO?editors=0110

Flip animation based on scroll position

This is a follow-on from this question: Animation based on scroll position
The goal is to loop through each element, and change it's rotation and perspective based on the users scroll position. I guess from an organic UX viewpoint, you'd want the top of the browser window to 'squash' the topmost item, and smoothy flip the element down.
Here's a screenshot for guidance:
Here is a Fiddle: https://jsfiddle.net/nfquerido/0zpc2a76/
And the loop function:
var _items = function () {
forEach(items, function (item) {
var scrollTop = _scrollTop(),
elementTop = item.offsetTop,
documentHeight = _getDocumentHeight(),
// Transform the item based on scroll
rotationFactor = Math.max(0, scrollTop - elementTop),
perspectiveFactor = Math.max(0, scrollTop - elementTop),
rotation = (rotationFactor / (documentHeight - windowHeight) * 90),
perspective = (perspectiveFactor / (documentHeight - windowHeight) * 2000),
transform = 'perspective(' + perspective + ') rotateX(' + rotation + 'deg)';
// Elements off the top edge.
if(scrollTop > elementTop) {
item.classList.add('scrolling');
item.style.webkitTransform = transform;
} else {
item.classList.remove('scrolling');
item.style.webkitTransform = null; // Reset the transform
}
});
};
I updated your fiddle: https://jsfiddle.net/0zpc2a76/1/
If I understand your question correctly, I think you are trying to get the blue boxes to "fold over" as if they are being pushed down by the top of the viewport. For that, your calculations seem to be wrong, so I updated some of the variable assignments:
rotation = (rotationFactor / (item.offsetHeight) * 90),
perspective = 2000 - (perspectiveFactor / (item.offsetHeight) * 2000),

Animation based on scroll position

So, I'm trying to animate elements (sequentially and independently) based on their scroll position.
The goal is to loop through each element, and change it's rotation based on the users scroll position. Right now, the rotations on each item are always the same. How can this be achieved?
Here is a Fiddle: https://jsfiddle.net/nfquerido/wy84pLud/
And this is the loop function:
var _items = function () {
forEach(items, function(item) {
var scrollTop = _scrollTop(),
elementTop = item.offsetTop,
documentHeight = _getDocumentHeight(),
elementHeight = _getElementHeight(item),
// Transform the item based on scroll
rotation = (scrollTop / (documentHeight - windowHeight) * 360),
transform = 'rotate(' + rotation + 'deg)';
// Elements off the top edge.
if (scrollTop > elementTop) {
item.classList.add('scrolling');
item.style.webkitTransform = transform;
} else {
item.classList.remove('scrolling');
item.style.webkitTransform = null; // Reset the transform
}
});
};
I'd appreciate vanilla JavaScript suggestions only please!
I think this is the fix you're looking for:
I added this right above your assignment of the rotation var:
// Transform the item based on scroll
rotationFactor = Math.max(0, scrollTop - elementTop),
rotation = ( rotationFactor / (documentHeight - windowHeight) * 360),
After replacing this they each get their relative offset rotation :)
The error is that the only changing/affecting variable to the rotation was your scrollTop, while that is only on a document-level.
To effect on an element-level we also want to include that difference :)

Equation for image mouseover pan?

i have a simple jQ script:
a set width/height container
a landscape img (can be bigger or
smaller than container)
when a user mouses over the image, it pans
(no click/drag) until it reaches the end
The equation to move the img to the left is this:
-1(relative mouse-position)*(img width)/(container width)
This works fine, but it leaves a space one the mouse reaches the end of the img.
Fiddle
$("figure img").mousemove( function (e) {
var a = $(this).closest("figure"),
b = $(this).width(),
c = a.width(),
d = (e.clientX - a.offset().left);
$(this).css({
left: -1*(d*b/c)
}, 100);
});
can someone help? I want the img to be completely aligned to the right of the container once the mouse reaches the end.
The correct formula is: -1 * (d/c) * (b - c)
Or, more clearly: -1 * (mouseX / figureWidth) * (imgWidth - figureWidth)
(mouseX / figureWidth) represents the percent of the width of the figure that the mouse is positioned at. It will be a number between 0 and 1.
(imgWidth - figureWidth) represents the biggest X value you want to use to position the image at the opposite side.
Multiplying the percent by the total range of movement gives you the movement amount for the current mouse position!
Updated Fiddle
I suggest using more descriptive variable names such as figureWidth, imgWidth, mouseX etc. Not only will it be easier for you to understand, but it will be easier for people to answer.
This should work: http://jsfiddle.net/0zd5t1wf/4/
i just get the limit value for the left propriety of image (the image width - the figure box)
$("figure img").each( function () {
if($(this).width() >= ($(this).height() * 2.5)) {
$(this)
.attr("class", "panorama")
.mousemove( function (e) {
var a = $(this).closest("figure"),
b = $(this).width(),
c = a.width(),
d = (e.clientX - a.offset().left),
newLeft = -1*(d*b/c),
limitValue = parseInt($(this).width()) - parseInt($("figure").width());
if ( newLeft < 0 && (newLeft *-1) < limitValue ){
$(this).css({
left: newLeft
}, 100);
}
$("#hello").html('why');
});
}
});

Categories

Resources