jQuery replacing mouse cursor - javascript

I'm trying to replace the mouse cursor with an image.
I have the following html:
<div id="content-bg">
<img src="path"/>
</div>
<div id="mouse"></div>
CSS:
#content-bg{
background:url(../img/frontend/content-bg.png) top left no-repeat;
width: 968px;
height: 552px;
position:relative;
}
#mouse {
cursor: none;
width: 75px;
height: 76px;
background: url("../img/frontend/cross.png") no-repeat center;
position: absolute;
display:none;
top: 0;
left: 0;
z-index: 10000;
}
javascript:
$(document).ready(function(){
$('#content-bg').mouseout(function(){
$('#mouse').hide();
$(this).css("cursor","none");
return false;
});
$('#content-bg').mouseenter(function(){
$('#mouse').show();
return false;
});
$('#content-bg').mousemove(function(e){
var x = e.clientX - $(document).scrollLeft() - 37.5;
var y = e.clientY + $(document).scrollTop() - 38;
$('#mouse').css('left', x).css('top',y);
});
});
The mouse image is on the right place but seems to be blinking and flashy. The transitions aren't as smooth as I wanted. Somehow it seems that the mouseout and mouseenter events are triggered every time I move the mouse inside the content-bg div.
Any idea how I can solve this?

As has been pointed out in comments, your mouseout occurs when your mouse suddenly hovers #mouse, as it appears.
You need to cancel out these events manually:
$('#content-bg').mouseout(function(e){
if($(e.relatedTarget).is('#mouse')) { return false; }
$('#mouse').hide();
$(this).css("cursor","none");
return false;
});
$('#content-bg').mouseenter(function(e){
if($(e.fromElement).is('#mouse')) { return false; }
$('#mouse').show();
return false;
});

Related

Javascript mousemove function to show element not working as expected

I am trying to to get a mousemove function to display a custom cursor element i created when the mouse is moved inside the specific div. The custom cursor is an absolute positioned div within the div i want it to appear in. The wierd thing i am seeing is i can see from the developer tools that it is infact working but the custom cursor doesnt actually show. If i however move the custom cursor div outside of the div i want it in and into the main body it displays fine.
I know this must be a simple error on my part but i cant see it! Appreciate any advice.
let customCursor = document.querySelector('.custom-cursor');
const section2 = document.querySelector('.section2');
section2.addEventListener('mousemove', function(e) {
customCursor.classList.add('active');
customCursor.setAttribute("style", "top:" + (e.pageY) + "px; left: " + e.pageX + "px;");
});
section2.addEventListener('mouseleave', function() {
customCursor.classList.remove('active');
});
.section {
position: relative;
}
.section1 {
height: 500px;
}
.section2 {
height: 500px;
}
.custom-cursor {
width: 50px;
height: 50px;
background: black;
border-radius: 50%;
display: none;
position: absolute;
}
.custom-cursor.active {
display: block;
}
<body>
<section class="section1 section">Section 1</section>
<section class="section2 section">Section 2
<div class="custom-cursor"></div>
</section>
</body>
Like #Titus comment, you can use CSS with cursor.
But if you implemeting it with JS that need to track position of your mouse relative to section2, you will need to subtract the section2 element offset left and top, then subtract half of the cursor width and height to center the cursor:
let customCursor = document.querySelector('.custom-cursor');
const section2 = document.querySelector('.section2');
section2.addEventListener('mousemove', function(e) {
customCursor.classList.add('active');
customCursor.setAttribute("style", "top:" + (e.pageY - section2.offsetTop - (customCursor.offsetWidth/2) ) + "px; left: " + (e.pageX - section2.offsetLeft - (customCursor.offsetHeight/2)) + "px;");
});
section2.addEventListener('mouseleave', function() {
customCursor.classList.remove('active');
});
.section {
position: relative;
}
.section1 {
height: 500px;
}
.section2 {
height: 500px;
}
.custom-cursor {
width: 50px;
height: 50px;
background: black;
border-radius: 50%;
display: none;
position: absolute;
}
.custom-cursor.active {
display: block;
}
<body>
<section class="section1 section">Section 1</section>
<section class="section2 section">Section 2
<div class="custom-cursor"></div>
</section>
</body>
position: absolute
is relative to the parent if the parent has
position:relative
so in order to have the correct position within your section2, you need to use e.layerY and e.layerX instead of e.pageY and e.pageX since those are based on the top left corner of your screen. e.layerY and e.layerX is relative to the container that the mouseevent is attached to.
Try this: https://jsfiddle.net/42kq1w8m/9/

Mouse move in a container with overflow JavaScript

I have a container of 200px that have a container itself with 400px height, I have a tracking mouse object that moves with it on mousemove event
when I'm moving the mouse in the not overflowed part, everything is fine, but when I move the scroll down the object do not track the mouse anymore
$(document).mousemove(function(e) {
$("#image").css({
left: e.pageX,
top: e.pageY
});
});
#image {
position: absolute;
}
.container {
height: 200px;
overflow: auto;
}
.image-container {
position: relative;
height: 400px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="image-container">
<img id="image" src="http://images.pictureshunt.com/pics/m/mouse-8557.JPG" />
</div>
</div>
There is JSFiddle link here too.
Because you're not taking account of the scrollTop property of .container when positioning the cursor element. Try this:
let container = $('.container'); //<-- get container
$(document).mousemove(e => {
$("#image").css({
left: e.pageX,
top: e.pageY + container[0].scrollTop //<-- add scroll top too
});
});
In the interests of efficiency, it would also be good to cache the reference to #image once rather than grab it afresh every time the event fires.
let
container = $('.container'),
image = $('#image')
;
$(document).mousemove(e => {
image.css({ ...

How to move an image/div from right to left continuously?

What I'd like to do is animate a small image as well as a div (or an image within a div) from the right to the left of the screen, repeating once the image/div leaves the screen.
I found an example online that moves an image/div from left to right, but not all the way to the other side of the screen, and I am struggling to make it from right to left.
Here's what I have been doing
function moveTruck() {
$("#ImageToMove").animate({
"margin-right": "5000px"
}, 3000, function () { $("#ImageToMove").css("margin-right", "10000"); moveTruck(); });
}
moveTruck();
Playing with the margin-right values. My CSS class is:
.HomeImageAnimate{
position:absolute;
margin-top:80px;
right:1000px;
}
Try setting , animating left property using values of window.innerWidth , container element width
(function fx(el) {
$(el).css("left", window.innerWidth)
.animate({
left: "-" + (window.innerWidth - $(el).width() * 2)
}, 3000, "linear", function() {
fx(this)
})
}($("div")))
body {
overflow: hidden;
}
div {
width: 50px;
height: 50px;
position: absolute;
}
img {
background: gold;
width: 50px;
height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<div>
<img />
</div>
Try this out, this truck div repeatedly goes from right to left.
HTML:
<div class="truck"></div>
CSS:
body{
background: green;
overflow: hidden;
}
.truck {
margin-top:20px;
width: 272px;
height: 174px;
cursor:pointer;
position: absolute;
margin-right: -150px;
z-index: 3;
background: red;
border-radius:4px;
width:200px;
height:50px;
}
JS:
$(function() {
var moveTruck = function(){
$(".truck").delay(2000).animate( {'right': '120%' }, 5000,'linear',function(){
$(this).css({'right': '-50px'});
moveTruck();
});
}
moveTruck();
})
CODEPEN DEMO
function move(){
width = $(window).width();
objectWidth = $('#demo').width();
margin = width + objectWidth + 'px';
restart = -100 - objectWidth + 'px';
$('#demo').animate({
'margin-left': margin
}, 3000, function(){
$('#demo').css('margin-left', restart);
move();
});
}
move();
Try this out, it calculates the exact width of object and window - should always work no matter the screen size. You were trying to use an absolute pixel value, won't always work.
https://jsfiddle.net/w9pgmm9d/3/

How can I apply the same jQuery hover animation to two divs of different height side-by-side?

I have a menu <div> with a shorter handle <div> to the right of it (see below). This loads off to the left of the screen minus a 5px sliver of the menu <div> and the whole handle <div>. I want the whole container to slide onto the screen when the mouse hovers either portion, and off the screen when it leaves both portions.
This works except when the mouse goes from the handle to the menu. There is a brief moment where the mouseleave from the handle and the mouseenter from the menu fire. I have tried to .stop(true) the current animation on the container, but there is still a hesitation in the animation.
#slideout-nav contains both elements (and transparent space below the handle, which I do not want to trigger the animation).
#slideout-menu-container is the left portion.
#slideout-handle is the right portion.
$('#slideout-menu-container').addClass('slideout-hover');
$('#slideout-handle').addClass('slideout-hover');
var slideIn = function () {
$('#slideout-nav').stop(true);
$('#slideout-nav').animate({
left: '0px'
});
};
var slideOut = function () {
$('#slideout-nav').stop(true);
$('#slideout-nav').animate({
left: distance * -1 + 'px'
});
};
$('.slideout-hover').hoverIntent(slideIn, slideOut);
Is there a more elegant way to accomplish this?
Update
HTML:
<div id="slideout-nav">
<div id="slideout-handle">+</div>
<div id="slideout-menu-container">
<ul>
<li><a>Home</a></li>
<li><a>Models</a></li>
</ul>
</div>
</div>
CSS:
#slideout-nav {
z-index: 99;
position: absolute;
top: 0;
width: 225px;
}
#slideout-handle {
float: right;
padding: 10px;
background: rgba(0, 0, 0, 0.8);
}
#slideout-menu-container {
overflow: hidden;
background: rgba(0, 0, 0, 0.8);
padding: 10px;
}
Ok, I think I got you problem. I made some changes in your css (maybe it just fits the jsFiddle needs) :
#slideout-nav {
z-index: 99;
position: absolute;
top: 0;
left: -200px; /* Here */
width: 225px;
}
And in the JS :
$('#slideout-menu-container').addClass('slideout-hover');
$('#slideout-handle').addClass('slideout-hover');
var isAnimated = false;
var mouserOverHandle = false;
var slideIn = function () {
if (!isAnimated) {
isAnimated = true;
$('#slideout-nav').animate({
left: '0px'
}, function () {isAnimated = false;});
}
};
var slideOut = function () {
setTimeout(function () {
if (!isAnimated && !mouseOverHandle) {
isAnimated = true;
$('#slideout-nav').animate({
left: '-200px'
}, function () {isAnimated = false;});
}
}, 10);
};
$('#slideout-handle').hover(function () {mouseOverHandle = true;}, function () {mouseOverHandle = false;});
$('.slideout-hover').hover(slideIn, slideOut);
I added a lock (isAnimated) to prevent the menu from sliding in other direction when it is already sliding.
And, the tricky part I think it can be improved, I added a timer to the slideOut function, because we have to know (when leaving the menu-container div) if we are over the handle or no. So the timer is just here to "wait" the event hover over the handle to be fired.
Without the timer (and the mouseOverHandle var) the menu slides out when your mouse goes over the handle from the menu-container. Feel free to remove it if it is not a matter for you.
See the jsFiddle here.
I came up with a solution to this based on an answer to another question.
I set the containing <div> to have a height and width of 0 with overflow: visible. Then I gave the containing <div> the hover event. This ensures that the event is only triggered when the mouse enters or leaves its children (my menu and handle <div>s).
Here is a JSFiddle for posterity.
HTML:
<div id="container">
<div id="menu">Menu</div>
<div id="handle">+</div>
</div>
JS:
var slideIn = function () {
$('#container').stop(true);
$('#container').animate({
left: '0px'
}, 'fast');
};
var slideOut = function () {
$('#container').stop(true);
$('#container').animate({
left: '-190px'
}, 'fast');
};
$('#container').hover(slideIn, slideOut);
CSS:
#container {
width:0;
height:0;
overflow:visible;
position:absolute;
left:-190px;
}
#handle {
padding:10px;
width:auto;
height:auto;
background: rgba(0, 0, 0, 0.8);
font-size:18px;
color:#FFF;
display:inline-block;
border-bottom-right-radius:3px;
}
#menu {
background: rgba(0, 0, 0, 0.8);
width:195px;
height:300px;
float:left;
display:inline-block;
border-bottom-right-radius:3px;
}

mousedown. propagation on siblings event.targets

I have 2 sibling-nodes with 'position absolute' which both handle mousedown event. How can I trigger the handler of 'div 1' when I am clicking on the transparent area of the 'div 2' (on the pic.)
If the overlapping elements are dynamic, I don't believe it is possible to accomplish this using regular event bubbling since the two overlapping elements in question are "siblings".
I had the same problem and I was able to solve it with more of a hitTest scenerio where I test if the user's mouse position is within the same area.
function _isMouseOverMe(obj){
var t = obj.offset().top;
var o = obj.offset().left;
var w = obj.width();
var h = obj.height();
if (e.pageX >= o+1 && e.pageX <= o+w){
if (e.pageY >= t+1 && e.pageY <= t+h){
return true;
}
}
return false
}
You'll want to use 3 event handlers, one for div1, one for div2, and one for contentArea. The contentArea handler should stop propagation so that the div2 handler is not called. The div2 handler should call the div1 handler:
function div1Click (e)
{
// do something
}
function div2Click (e)
{
div1Click.call(div1, e);
}
function contentAreaClick (e)
{
e = e || window.event;
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble = true;
// do something
}
div1.onclick = div1Click;
div2.onclick = div2Click;
contentArea.onclick = contentAreaClick;
What you were looking was CSS's pointer-events property. I didn't make a research to learn whether it was available at the times the question been asked, but that I faced the same thing I'm taking a liberty of covering it.
Here're your two DIVs:
<body>
<div class="inner div-1"></div>
<div class="inner div-2">
<div class="div-2__content-area"></div>
</div>
</body>
Styling:
.inner {
height: 10em;
position: absolute;
width: 15em;
}
.div-1 {
/* Intrinsic styling & initial positioning, can be arbitrary */
background: #ff0;
left: 50%;
top: 50%;
transform: translate(-75%, -75%);
}
.div-2 {
/* Intrinsic styling & initial positioning, can be arbitrary */
background: rgba(0, 255, 0, 0.25);
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* Centering content area */
align-items: center;
display: flex;
justify-content: center;
/* Key feature -- making visible part of transparent DIV insensitive to mouse (pointer) events), letting them fire on the underlying element */
pointer-events: none;
}
.div-2__content-area {
/* Styling content area */
background: #f00;
height: 75%;
width: 75%;
/* Reverting 'pointer-events' perception to regular */
pointer-events: auto;
}
Event listeners and displaying:
document.querySelector(".div-1").addEventListener("mousedown", (_) => {
alert("div 1");
});
document.querySelector(".div-2__content-area").addEventListener("mousedown", (_) => {
alert("Content area");
});
This all on codepen:
https://codepen.io/Caaat1/pen/RwZEJVP

Categories