Why positioning element next to mouse cursor is so "laggy"? - javascript

https://jsfiddle.net/m0zwwav4/
html:
<div id="container"></div>
<div id="tooltip">Tooltip!</div>
css:
#container {
width: 500px;
height: 500px;
border: solid 1px red;
}
#tooltip {
position: absolute;
}
js:
var container = document.getElementById('container')
var tooltip = document.getElementById('tooltip')
container.onmousemove = function(event) {
tooltip.style.left = (event.pageX + 20) + 'px'
tooltip.style.top = event.pageY + 'px'
}
When I move cursor inside red box, tooltip seems to be little bit laggy (there is a little delay) - testing in chrome on max os. Is there any trick to make it faster to make it look like moving exactly fast as mouse cursor?

You can do this without JavaScript.
Change the container's cursor to a URL, which is an image containing the tooltip text:
You can do this using a Data URI:
#container {
cursor: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEoAAAAZCAIAAAAZqC9/AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIPSURBVFhH5Zg7csIwEIZxzgKp0kCH6KCCg0BBAQV0KdOFwpTQ5QapcAUdLqFhUgB3cX5Ji2T5IRNjBsb5ZjLj1YqVPz1sT5wgCCrl5QV/jDHHcfb7vWwqE1wP7Ha7yWRSPkPSA+v1ejgclsxQ6wHf90u2hoYewBqWyTCqBx5l6A3wgHOcgUdxESToAYuhvIckWvMz9bkfNAVXD5WsB/6+hm+vVboqhoTVPB8PdHUlqXog0XCB7wDBqi/i/oriYNEVDfekOtqKobajK2fSpgfynMPzvCWmXRLdR/bsBb5yvaW4XPZCHc0VlbWQChU1K6bqdTod2X+z2TQaDWrNgo9TG/sUcfxxTe0vezYvqBEqiihUMKoHK7VW+JQRW4EjW7LwPuU4lx17chkPlx9iSu1Zgy7OgLH77duRuSfeiX4RKmjowQ1rRUEOvG+xn5g7pWNYHb2LEf2fU1b2Bpj7JeW7UzlhuqDWg9tsNsMcyMN2w9vP/ggt+gFrhfRwuuBWr9dleBuHo9psCU9ye7ZosFzNZjN8zEC73ZYt6iJO7MWgDpNupD4ytmfjBSmmcyUx+6iK5tnTJQKuFyennh7AQN3gVVldMNzdFIjqmYRuKVkPZBrG7oaIjBnJW7IJBbWgTY+5K13VHC+/3hOg9Gj946TqAYjhx8/qBrL1Ur9aAN4N6FHQ4/Qx/IP/lJWYUutVKr8O6jUK23d1QgAAAABJRU5ErkJggg==), auto;
}
Fiddle

Related

Mouse-Following Tooltip gets Farther Away the Smaller the Window

I've just revamped my tooltip code due to issues with the position altering depending on the size of it's parent (mostly due to using offsetX/Y instead of pageX/Y, but page was being weird, too). So I decided to just have one tooltip for each of my site's pages, parented to the main div, and just feed it different text depending on what the mouse is hovering over (I'll be dealing with the visibility part later).
And it's worked quite well so far, but the only issue is that, the smaller I make my window, the farther the tooltip is from my mouse, until it's not even in view anymore.
Here's the JavaScript coding I've done for it.
var body = document.getElementsByClassName("test");
var tooltip = document.getElementById("tooltip");
body[0].addEventListener("mousemove", tooltipMove)
function tooltipMove(event) {
var x = event.pageX;
var y = event.pageY;
tooltip.style.top = (y + -900) + "px";
tooltip.style.left = (x + -875) + "px";
}
The CSS coding for the tooltip:
.tooltip {
visibility: hidden;
width: 170px;
background-color: white;
background-image: url("images/tooltipbackground.png");
color: black;
text-align: center;
border-style: groove;
border-color: #f4bb4c #ffd966 #ffd966 #f4bb4c;
border-radius: 2px;
padding: 5px 5px;
position: absolute;
z-index: 1;
}
.notfound:hover .tooltip {
visibility: visible;
}
And the HTML:
<div class="test" style="top: 70px; position: relative; height: 100%; width: 100%;">
<h1>TEST</h1>
<img src="images/pagenotfound.png">
</div>
<div style="width: 1px; height: 1px; position: relative;">
<span class="tooltip" id="tooltip">testing</span>
</div>
I should mention the body's (which has the "notfound" class) height is 900px, and it's width 600px, in case that's one of the problems.
The 1 pixel div is just what I'm using to "host" the tooltip, not sure if it's causing any problems as well. I inspected the page in order to see it, and it never seemed to slide around with the window size.
Any sort of help would be greatly appreciated. I've tried to switch it from pageX/Y to clientX/Y, but it's the same issue. And using offset causes it's position to shift depending on what I'm hovering over, which is the reason I'm revamping the code in the first place.
I've also tried to change the tooltip's position from absolute to, well, anything else (after resizing it's parent so it doesn't get squashed), but that hasn't helped.
Another thing I should mention is that, for some reason, the shifting doesn't seem to happen in the Y axis, it's only when I squish the window horizontally that the tooltip shifts, at least from what I've noticed.
I had thought changing the tooltip's position to fixed had made it disappear, but I just couldn't see it due to the massive repositioning I had done to it. Once I deleted that it was visible and fine, and better yet, it stays in it's proper position no matter the screen size!
Also note: I had to change pageX/Y to clientX/Y, as using page made the tooltip shift vertically when squished.
<div style="height: 1px; width: 1px; position: relative;">
<span class="tooltip" id="tooltip" style="position: fixed;">Placeholder</span>
</div>
for (i = 0; i < tip.length; i++) {
tip[i].addEventListener("mousemove", tooltipMove)
tip[i].addEventListener("mouseleave", defaultVis)
}
function tooltipMove(event) {
var x = event.clientX;
var y = event.clientY;
tooltip.style.visibility = "visible";
tooltip.style.top = (y + -50) + "px";
tooltip.style.left = (x + -200) + "px";
}
function defaultVis() {
tooltip.style.visibility = "hidden";
}

How to link text to mouse pointer?

I'm trying to make text that follows my mouse pointer, but getting some troubles.
I'm using fullscreen div to take available space on page to make mouse event working for entire page.
Also using position: absolute to place one div on another. date-and-time is used to create text that follows the mouse.
I've tried almost anything I can but it didn't work and now I'm here.
html
<body>
<div id="fullscreen"></div>
<div id="date-and-time"></div>
<script src="./script.js"></script>
</body>
javascript
const dateAndTime = document.getElementById('date-and-time');
dateAndTime.innerText = new Date();
document.addEventListener("mousemove", function(e) {
dateAndTime.style.left = e.clientX;
dateAndTime.style.top = e.clientY;
});
css
div {
position: absolute;
}
#fullscreen {
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: yellow;
}
Problem is that text just ignores my mouse, but if I move pointer to left corner text gets moved to X=0 (maybe it's not actually but it worked that way before)
You are missing px for the postion values.
You are assigning the left and right position values to the node without px.
What happens when you move to left most position? Simple at that time the value will be 0. That will work without any unit.
div {
position: absolute;
}
#fullscreen {
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: yellow;
}
<body>
<div id="fullscreen"></div>
<div id="date-and-time"></div>
</body>
<script>
const dateAndTime = document.getElementById("date-and-time");
dateAndTime.innerText = new Date();
document.addEventListener("mousemove", function(e) {
dateAndTime.style.left = e.clientX + 'px';
dateAndTime.style.top = e.clientY + 'px';
});
</script>

Why does the circle in this code snippet lag behind the actual mouse cursor?

I am new to JavaScript and taking JavaScript Training course. The js code is supposed to render a circle at the mouse pointer location and listen for any changes.
const AREA = document.body;
const CIRCLE = document.querySelector('.circle');
function mouseCoordinates(e) {
var horizontalPosition = e.clientX - 26;
var verticalPosition= e.clientY - 26;
// Set horizontal and vertical position.
CIRCLE.style.left = horizontalPosition + 'px';
CIRCLE.style.top = verticalPosition + 'px';
}
AREA.addEventListener('mousemove', mouseCoordinates, false);
body {
width: 100vw;
height: 100vh;
}
.circle {
position: absolute;
top: 1px;
width: 50px;
height: 50px;
color: transparent;
border: 2px solid red;
border-radius: 50%;
}
<div class="circle"></div>
Initially the mouse pointer stays at the center of the circle, but when I am slightly increasing the speed of mouse movement the circle seems to "lag" behind.
Why does this happen?
Is this related to the performance of my system?
Isn't the listener supposed to run as and when the mouse moves and draw the circle exactly over the current position of the mouse?

How to move content along with window resize so that it appears in the same position?

I have a page with a grid containing three div elements. Each one of this div has the size of the viewport so at any time just one of the divs if visible and the other two are outside. So the grid is three times big the viewport.
Resizing the window will cause the divs, hence the grid, to resize as well.
The html is pretty simple:
<div class="container">
<div class="square square1">1</div>
<div class="square square2">2</div>
<div class="square square3">3</div>
</div>
Styled like this:
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
height: 100vh;
width: 300vw;
}
.square {
height: 100vh;
position: absolute;
width: 100vw;
}
.square1 {
background: red;
left: 0;
}
.square2 {
background: green;
left: 100vw;
}
.square3 {
background: yellow;
left: 200vw;
}
The initial position, set via javascript, is on the middle div.
What happens is that resizing the window makes the whole document to move proportionally with the resizing. So, if at some point I'm seeing just the second div, resizing the window will make the third to appear more and more.
I'm quite sure that with some javascript I could move the grid so that it appears fixed while resizing, but I can't figure out a formula.
I tried something like this:
var windowW = $(window).width();
$(window).resize(function() {
var newWidth = $(window).width();
var diff = windowW - newWidth;
var windowLeftPos = $(window).scrollLeft();
$(window).scrollLeft(windowLeftPos - diff / 2);
});
But it's just a blind guess. I tried other formulas with multiplication and division and scale factors, but nothing worked.
Any idea?
Here's a working example showing what I mean.
Initially you see just the green div. Resizing the window, on of the two other divs will appear, instead I would like to see only the green one.
Edit: the question similar to mine is very interesting but it seems to me also very different. The main huge difference is that I'm resizing and moving DOM elements that stay outside the viewport. Besides, the answers are pretty focused on the image/background aspect ratio, which is part of the question, but it's not the case for me. I don't have a problem resizing elements, just compensating the movement due to the resizing
Update: I edited the pen and I think I'm getting closer to the desired result: http://codepen.io/anon/pen/vGeRgJ
It seems to kind of work, but it doesn't especially when I'm closer to one of the extremes, like all on the left or on the right.
Here is an updated version for you, from where you can easily make your own adjustments.
Since jQuery doesn't throttle the resize event by default, I made this one in plain javascript.
To get rid of the vertical scroll, and I also added a getScrollbarSize function as a bonus :)
function getWidth() { return window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth; }
function getLeft() { return document.body.scrollLeft; }
function setLeft(v) { document.body.scrollLeft = v; }
function getScrollbarSize() {
var div, width;
div = document.createElement('div');
div.innerHTML = '<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>';
div = div.firstChild;
document.body.appendChild(div);
width = div.offsetWidth - div.clientWidth;
document.body.removeChild(div);
return width;
};
(function(t,w,l,l2) {
document.querySelector('.container').style.height = 'calc(100vh - ' + getScrollbarSize() + 'px)';
w = getWidth(), l = w, l2 = l / w, setLeft(w);
window.addEventListener("resize", function(e) {
if ( !t ) {
t = setTimeout(function() {
t = null;
resizeHandler(e);
}, 66); /* throttle timeout */
}
}, false);
function resizeHandler(e) {
w = getWidth();
l = getLeft();
setLeft(w * l2);
}
window.addEventListener("scroll", function(e) {
if ( !t ) {
l2 = getLeft() / w;
}
}, false);
}());
body {
margin: 0;
padding: 0;
}
.container {
position: relative;
height: 100vh;
width: 100vw;
}
.square {
height: 100%;
position: absolute;
width: 100vw;
}
.square1 {
background: red;
left: 0;
}
.square2 {
background: green;
left: 100%;
}
.square3 {
background: yellow;
left: 200%;
}
<div class="container">
<div class="square square1">1</div>
<div class="square square2">2</div>
<div class="square square3">3</div>
</div>

How to user controlled overlap images in JS

I'm desperately searching for solution for my client. I have graphic - something like that:
And I want to be able to take the line with circle in the center and drag it to right or left. And it will be hiding and unhiding my two full images. It's basically two images on the same place, just with another z-index I think.
I think it's possible to do it with JavaScript, but I don't know of any functions or methods for this option.
Here is my solution:
The HTML is pretty simple, just two divs for the images and one for the drag:
<div class="img" id="img1"></div>
<div class="img" id="img2"></div>
<div id="drag"></div>
For the CSS, the important part is to absolute position all the divs and give a background image.
As for the Javascript, with a little help from jQuery, we listen for the mouse events, make some calculations and adjust the CSS of the second image:
$('#drag').on('mousedown', function(e){
var $self = $(this),
dragPos = $self.position().left + $self.width()/2,
imgWidth = $('#img1').width();
$(document).on('mouseup', function(e){
$(document).off('mouseup').off('mousemove');
});
$(document).on('mousemove', function(me){
var mx = me.pageX - e.pageX + dragPos
$self.css({ left: mx });
$('#img2').css({
width: imgWidth - mx,
left: mx,
backgroundPosition: -mx + 'px 0px',
});
});
});
From there, I believe it's pretty easy to customize it and give it a unique look.
Hope this helps!
JsFiddle Demo
Something like this alphamask plugin may do the trick, though I'm not sure how simple it would be for you to implement in the manner of your slider example.
Actually quite simple. The first step is to make it work manually. I'd set it up as follows:
<div class="wrap" id="wrap1">
<div class="img-wrap img1"></div>
<div class="img-wrap img2"></div>
<div>
With CSS as follows:
.wrap {
position: relative;
width: 300px;
height: 300px;
}
.img-wrap {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
}
.img1 {
z-index: 1;
background: url(bg1.png) no-repeat 0px 0px;
}
.img2 {
z-index: 2;
background: url(bg1.png) no-repeat 0px 0px;
}
Now some JavaScript (with jQuery) to set a position (you can call this when you move a slider over the top later):
function setPosition(percentage){
// get the width of the container
var w = $('#wrap1').width();
// work out the width of left panel
var w1 = Math.floor(w * percentage);
// and the right panel
var w2 = w - w1;
// set the width of the right panel
// move it right by the width of the left panel
// and move the background back by the width of the left panel
$('#wrap1 .img2').css({
width: w2,
left: w1,
backgroundPosition: -w1 + 'px 0px',
});
}
You now just have to decide how to do the dragging. You could even just do it on mouseOver. Easy!

Categories

Resources