At the moment I have some jQuery code telling a div called small-circle to follow my cursor around. I learnt how to achieve this from a post on stack overflow.
I modified the script very slightly to work with my own requirements. However there's is an issue when I add another big-circle to my container class. What seems to be happening is that the id of small-circle2 is not allowed to move around inside of the big-circle2 on the x axis. I'm thinking it has something to do with
var mouseXval = 0, mouseYval = 0, limitX = 120-30, limitY= 120-30;
limitX and limitY values might need to change because I am adding another div called big-circle2 to the mix. So I tried this approach by adding 60 to limitX = 120-60, limitY= 120-60; but the only that changed was the placement of the circle. small-circle2 was not following my cursor around on the x axis. Still only the y axis.
I'm thinking that the possible solution could be in the math that is going on inside of the limitX and limitY axises. Another problem could be trying to add multiple circles inside of the one container.
Here's the fiddle.
Thank you!
Thax to #blex I was able to see where I was off. As it turns out there was nothing wrong with the math in limitX and limitY and it was not a container issue. What was I thinking!
The problem was here inside of the pageOffset variable
// issue with selecting both classes
var pageOffset = $(".big-circle, .big-circle2").offset();
The issue here was in selecting both ".big-circle, .big-circle2" to trigger the offset()method. Instead of selecting each class and then applying offset() I should of used the this keyword to trigger any of the two circles I hovered on.
// use `this` to trigger the elements I hover on
var pageOffset = $(this).offset();
When the user moves the mouse over ".big-circle, .big-circle2" jQuery fires a callback function which is passed onto the mousemove event. As soon as our callback is fired jQuery sets the current scope to the DOM elements that initiated the event which in this case are .big-circle and .big-circle2. The cool part about all of this is that jQuery gives us access to the elements that initiated the mousemove event with the this keyword.
So we set var offsetPage = $(this).offset(); and our big-circle2 now has little circle that follows are cursor around.
// jQuery sets the scope of callback to `big-circle, big-circle2`
$(".big-circle, .big-circle2").mousemove(function(event){
// `this` accesses our elements
var pageOffset = $(this).offset();
});
Updated fiddle
Related
I have built a WordPress theme. I came across a website that created a div to follow the user's cursor. The div was enlarged smoothly when the user hovers over a button or a link.
I want to add this nice functionality as an optional feature.
I added a div to the web page, #ambition_cursor and added some basic styling. The div now shows like a blue circle. The circle has position fixed to the top left corner of the site. The position can be changed by adding a CSS translate property.
I managed to make it work with the following code:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
var ambition_cursor_x = e.clientX; // Get the horizontal coordinate
var ambition_cursor_y = e.clientY; // Get the vertical coordinate
var ambition_cursor_pos = `translate(${ambition_cursor_x}px, ${ambition_cursor_y}px)`;
ambition_cursor.style.transform = ambition_cursor_pos;
}
window.addEventListener('mousemove', ambition_mouse);
The big downside here is the lag (?). There's quite a big delay, especially when moving the mouse around very fast. You can try it out on this site. I also put the situation in a JSFiddle; although the delay doesn't really happen there.
I didn't apply yet much styling (the default cursor is visible, so you can get a better idea of the real position). I first want this to work better, before I spent much time on that.
How can I increase the speed of this, so that the div position follows the mouse more accurately? I'm a beginner, so I don't really know which JavaScript optimisations I should make.
Current code is JavaScript, but jQuery is also an option.
Many thanks in advance!
Update: example how it looks on my computer.
All elements on the page have a transition applied. Remove/override this style and the delay goes away (tested).
As an alternative to the great answer of Joseph Atkinson:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
ambition_cursor.style.left = e.clientX + 'px'; // Get the horizontal coordinate
ambition_cursor.style.top = e.clientY + 'px' ; // Get the vertical coordinate
}
window.addEventListener('mousemove', ambition_mouse);
See: https://levelup.gitconnected.com/use-javascript-to-make-an-element-follow-the-cursor-3872307778b4
I visited the site example, cracked open the dev console, and found throttled(20, ambition_mouse) It is not a performance issue, and the solution is to not throttle the events. It was too smooth to be a performance issue, which gave me the first clue it had to be an accidental/deliberate effect.
I'm making custom controls for html5 video. My problem is occurring when I click on the seek bar. The x coordinates are far off. As I understand, I need to account for all the margins and padding down to root element, i.e. myElement<parentOfMyElement<parenOfparentOfMyElement ... and so on. Every one of them has its own styling with padding and margins and whatnot. How to achieve that without going through entire dom tree backwards?
I tried:
if(e.target.id==="progress"){
parent = e.target;
let x = e.pageX - parent.offsetLeft;
console.log(x);
}
if(e.target.parentNode.id==="progress"){
parent = e.target.parentNode;
let x = e.pageX - parent.offsetLeft;
console.log(x);
}
and other variations. I basically need that when I click on the parent element, get x coord in that element, starting with zero when I click the far left, where the arrow on the image points.
PS: If it's fixed value that's being added up to x it wouldn't be a problem, but since resolution gets changed(resize, or in mobile rotate), x coord isn't fixed at any given time even when clicking at exact same spot due to previously mentioned.
Edit as per request:
<div id="progress" onClick={this.trackProgress} className="progress text-center">
<div id="progress-bar-num" className="progress-bar-num">{Math.round(this.state.width.toFixed(2))+"%"}</div>
<div id="progress-bar" onClick={this.trackProgress} className="progress-bar bg-success" style={{width: Math.round(this.state.width.toFixed(2))+"%"}}></div>
</div>
Don't let my markup confuse you, it is done in React. Effect would be the same if it's done in vanilla js.
Your problem is that you're handling the event in a parent of the status bar element, so .offsetX is relative to the x position of parent and not the status bar.
Put the event handler on the status bar element itself and the .offsetX property of the event will work as you expect.
Long title I know. Sorry.
I just want to know how I get the new position after a click event that removes an element. Essentially I have a bar that is removed once the user does a click. There are some buttons on my page that have a fixed position when the distance of the scroll is greater than the offset so it looks like they unhook.
I tried to do offset().top in a callback after a click event, but it just outputs the original offset value not the distance minus the element removed. This makes the buttons just look like they jump into the fixed position as it's not removing the clicked element's height from the offset.
var distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
$(".icon-cross").click(function(){
distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
});
Hope that makes sense. Some help on this would be great.
Thanks
Rob
You can use mouseup event instead of click as you want to know the new position after the click.
try the following code
var distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
$(".icon-cross").mouseup(function(){
distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
});
so you want to know the new top of your anchor after the bar is removed by a click. use a setTimeout in your click handler with 0 delay just to ensure that the bar is removed. the way you are doing does not guarantee that bar is already removed because the bar removal click handler may be executing after your position calculator handler. following will work if i correctly understood your question.
var distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
$(".icon-cross").click(function(){
setTimeout(function(){
distance = $('.anchor-con').offset().top;
alert($('.anchor-con').offset().top);
}, 0);
});
I have a small draggable division (black) and many nodes with different IDs beside it
I need a hovering effect when I drag the black element on the nodes. What I am doing in allowDrop function is:
var dragObj;
function drag(ev){
dragObj = ev;
}
function allowDrop(ev){
ev.preventDefault();
var Dragged = dragObj;
var Hovered = ev;
var leftIndent = Dragged.layerX;
var hoveredID = Hovered.target.id.toString().split('_');
var nodesOnLeft = Math.floor(leftIndent/12);
var startingNode = hoveredID[0]-nodesOnLeft;
for (i=1;i<=Math.floor(draggableElementLength/12);i++){
var toApplyCssID = startingNode.toString() + '_1';
var toApplyCss = document.getElementById(toApplyCssID);
$('#'+toApplyCssID).css('background-color','lightgreen');
}
}
basically I am using the layerX property to find out the distance between my mouse pointer and draggable division's border and adjusting that to calculate number of nodes where I have to apply new CSS and applying that by finding the ID of node.
This is working but its making the process very slow as it involves many calculations and its not the hover effect as its not going away when I am removing the draggable division.
Is there any other way to achieve this or do I need to make code changes in existing code.
thanks
Without the HTML and the rest of the script, I can only point you in the direction you should be taking in this kind of scenario:
Don't constantly repeat calculations (that do not change) in a loop, store them outside the function:
Use document.getElementById(toApplyCssID) for each node and store the
elements in an array
Get the distance from the mouse position to the required edge or
edges of the div (leftIndent) on initial drag/mousedown and store
that in a variable
Store Math.floor(draggableElementLength/12) in another variable (you
haven't shown where this originates, but it doesn't seem to change in
the function...)
Apply the CSS to the relavent elements (from the array of elements)
using the other stored values to select them
Remove the CSS on those that had it applied earlier
This may not be the ultimate solution, but these are some of the things you can look at to speed up what you (may) have currently.
I want a div to move when the mouse is within x distance from it.
$(document).mousemove(function(e) {
mX = e.pageX;
mY = e.pageY;
distance = calculateDistance(element, mX, mY);
if (distance<100) {
$(element).css("left", moveAcc + "px");
moveAcc = moveAcc + 1;
}
});
JSFiddle - You have to select jquery 1.11.0 library
But because the condition is inside the mousemove function, it can only move the element when the mouse is being moved too, as opposed to moving when mouse is within x distance.
For this I need sort of an update thingy, something to check if conditions are met every frame.
Example, in Pascal for my projects I'd put the whole code in between the repeat until ()
In ActionScript there's addEventListener(Event.ENTER_FRAME, function);
What can I use in Javascript? What other ways would you come up with? - I did found this Javascript Version of AS3 enterframe event but it is 4 years old, migh be different now.
Is it ok to put the code inside setInterval function?
You're looking for the requestAnimationFrame method.
What it does ? It'll execute the method passed on it call before the next frame get rendered. But beware, not all browsers support it, you can use a polyfill for it or just an setInterval
Example:
function checkDistance () {
\\ Do your job here
window.requestAnimationFrame(checkDistance);
}
window.requestAnimationFrame(checkDistance);
More info:
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
You have two ways to do that:
Add an event listener on the document object and measure the element positions and the mouse positions, then check if the current mouse position is between those positions. (This way not suggested if you have just one element)
Add an event listener on the element directly and check if the current mouse position is exactly the same position you want.
If you have a well written mouse event listener, then you don't need to update the function using interval.
I would try declaring your mouse X and Y variables outside the mousemove method, that way even when your mouse stops moving, the last position (current really) is still accessible..
var mX;
var mY;
$(document).mousemove( function(e) {
mX = e.pageX;
mY = e.pageY;
});
Then, you can have a second method on an interval that can check against the values in those variables, and move the box accordingly..
setInterval(function(){
// Code to calculate distance etc.
distance = calculateDistance(element, mX, mY);
if (distance<100) {
$(element).css("left", moveAcc + "px");
moveAcc = moveAcc + 1;
}
},100); // Whatever interval you see fit instead of 100ms