Reputation: 351
I looked for many similar question but couldn't solve my issue. Here I have pasted only a single list item out of my code. I need to create a span
on mousemove
event over the list
item, and set its left-offset from its parent as the mouse moves. As I haven't ever tried any such thing, I experimented a lot with the code to get to this-
document.querySelector("li a").addEventListener("mousemove",(event)=> {
let span;
let alreadyHasSpan = event.target.hasChildNodes().length > 1; //default length=1
if(!alreadyHasSpan) {
span = $(`<span class="a-effect"></span>`);
span.appendTo(event.target);
}
let targetLeftPos = event.target.getBoundingClientRect().left;
span.css("left",`${event.clientX-targetLeftPos}px`);
$(this).mouseleave(function () {
span.remove();
});
}, false);
a {
position: relative;
}
.a-effect {
position: absolute; left: 0;
height: 100%;
width: 2%;
background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="nav-item active">
<a href="/" class="nav-link">Product</a>
</li>
On my browser, the span
moves but with trailing signs behind it-
Apart from the trailing signs, it oftens misses to show the span
. On this question's snippets, it's even worse to show the issue.
What's the issue and how could I fix it?
Upvotes: 0
Views: 1231
Reputation: 2357
As per your question, the issue is that you're adding a new span everytime the mouse moves. I am guessing you only want to add it when mouse enters, and remove it once the mouse leaves.
I have tried to keep your code as much as possible and change only what is causing your issue.
document.querySelector("li a").addEventListener("mouseenter", (event) => {
let span;
let alreadyHasSpan = event.target.childNodes.length > 1; //default length=1
if (!alreadyHasSpan) {
span = $(`<span class="a-effect"></span>`);
span.appendTo(event.target);
}
});
document.querySelector("li a").addEventListener("mousemove", (event) => {
let targetLeftPos = event.target.getBoundingClientRect().left;
if (event.target.childNodes.length > 1) {
let span = event.target.childNodes[1];
$(span).css("left", `${event.clientX-targetLeftPos}px`);
}
});
document.querySelector("li a").addEventListener("mouseleave", (event) => {
if (event.target.childNodes.length > 1) {
let span = event.target.childNodes[1];
span.remove();
}
});
a {
position: relative;
}
.a-effect {
position: absolute;
left: 0;
height: 100%;
width: 2%;
background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="nav-item active">
<a href="/" class="nav-link">Product</a>
</li>
Upvotes: 1
Reputation: 1721
I am not 100% sure where you want to place your span element but there are some problems in your code that i would correct first. The placement of the element is relatively easy to change then.
Firstly, you append the span element in a mousemove function and them check everytime that event triggers, if the span is already there. Change that to use the mouseenter
event for the span
creation.
Secondly, you add a new mouseleave handler for your link evetytime you move your mouse. Same as before, create that handler outside of your mousemove
event.
Regarding the position of your elememt, I am not sure where you expect it to appear/follow your mouse but you can easily adapt the offsetX
and offsetY
variables in my moveSpan()
function to adapt it to your needs.
Keep in mind when you are positioning the element, that the calculation is based off of the position of your a
element.
function moveSpan( e ) {
let $el = $(e.target);
let xPos = e.pageX;
let yPos = e.pageY;
let offsetX = $el.width() / 2;
let offsetY = $el.height() / 2;
let $span = $el.find('span');
$span.css({
'left': (xPos - offsetX) + 'px',
'top': (yPos - offsetY) + 'px'
});
}
$('li a').on('mouseenter', function( e ) {
let span = $('<span />').addClass('a-effect');
$(this).append( span );
moveSpan( e );
}).on('mousemove', function( e ) {
moveSpan( e );
}).on('mouseleave', function( e ) {
$(this).find('span').remove();
});
ul {
list-style-type: none;
}
a {
position: relative;
}
.a-effect {
position: absolute;
height: 100%;
width: 10px;
background: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul>
<li class="nav-item active">
<a href="/" class="nav-link">Product</a>
</li>
</ul>
Upvotes: 1