简体   繁体   中英

JavaScript cannot get onmousemove script to work as intended

I have a function to follow the object after the mouse, and I want to be able to stop and start following at will, without hiding the object.

It almost works as I wanted, and is following the mouse indeed, but I cannot make it move initial position without actually moving the mouse.

EG When I trigger the function, the object is still somewhere in another place, until I move the mouse, but what I'm trying to do is to move it the initial position first, before attaching the mousemove event.

Here is how I want to trigger the function:

showtrail();

function showtrail(shit){
//this is how I tried to set the initial position first, but this get me an error:..
//followmouse(); 
document.onmousemove=followmouse; //and this is how I attach the event.
}

This is a part of the actual function to move the object, but, I can't get the coordinates if I try to initilize/imitate the first movement.

    function followmouse(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
if (typeof e != "undefined"){  //This- if triggered by mousemove, and it works
xcoord+=e.pageX
ycoord+=e.pageY
}
else {   //this was meant for the initial call, but... for some reason
xcoord+=document.body.scrollLeft+event.clientX // it triggers an error,
ycoord+=document.body.scrollTop+event.clientY // saying event.clientX undefined.
}
}

So the event.clientX never seems to work, and I cannot figure out how to get the actual mouse position otherwise..

Please guide..

event.clientX and event.clientY are wrong. They should be e.clientX and e.clientY

A more elegant cross browser way to get xcoord and ycoord in followmouse(e) is:

xcoord = e.pageX||(e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft));
ycoord = e.pageY||(e.clientY+(document.body.scrollTop||document.documentElement.scrollTop));

Now if I'm getting it right, the object that follows is expected to have an initial absolute position and displayed as a block, meaning that you have initial x and y (left and top). Therefore by using a global bool var for currently following or not you're done.

<style>
...
#trail {position:absolute;left:0;top:0;display:none}
...
</style>

<script>
var following = false;
...
function followmouse(e){
   if (!following){
       document.getElementById('trail').style.display='none';
       return;
   }
   ...
   document.getElementById('trail').style.display='block';
}
</script>

By changing display you have the option to move your #trail to its initial position and then follow the mouse, and the option to avoid the move and let it follow the mouse from its latest following position.

EDIT 1:

For this very purpose, I recommend using of requestAnimationFrame API, not classic DOM events. said API is more efficient for creating animations and pausing them.

take a look at this too: requestAnimationFrame for smart animating


This is sad, but true that you can not get mouse's initial position before moving mouse on a webpage. I mean you can't calibrate your object before mousemove event. this is what I will do in a similar project:

<!DOCTYPE html>
<html>
    <head>
        <title>Title</title>
        <script type="text/javascript">
            var targetID = 'mydiv'; // div that is to follow the mouse
            var pauseFollowing = false;
            // (must be position:absolute)
            var offX = 15;          // X offset from mouse position
            var offY = 15;          // Y offset from mouse position

            function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ?  document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
            function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}

            function follow(evt) {
                if(pauseFollowing) {
                    //or do something else at pause
                    return false;
                }
                var obj = document.getElementById(targetID).style;
                obj.visibility = 'visible';
                obj.left = (parseInt(mouseX(evt))+offX) + 'px';
                obj.top = (parseInt(mouseY(evt))+offY) + 'px';
            }

            function toggleFollow() {
                pauseFollowing = !pauseFollowing;
            }

            window.onload = function() {
                window.onclick = toggleFollow;
                document.onmousemove = follow;
            }
        </script>
    </head>
    <body>
        <div id="mydiv" style="visibility: hidden; top:0; left:0 ;width: 100px; height: 100px; background: #ff0; position: absolute;"></div>
    </body>
</html>

Alright that's how I done it. The best Idea was to always capture a move to set position in a global var. Now I have an option to display it fixed at any specific place (if I pass coords to showtrail) or to actually follow the mouse; I also added an event listener, so if the mouse gets outside the window while following- it will be hidden. So far it works exactly as I wanted:

var trailimage=["scripts/loading_mouse.gif", 24, 24] //image path, plus width and height
var offsetfrommouse=[2,10] //image x,y offsets from cursor position in pixels. Enter 0,0 for no offset
var global_coord=[0,0]
var follow=false;

if (document.getElementById || document.all)
document.write('<div id="trailimageid" style="z-index: 10;position:absolute;display:none;left:0px;top:0px;width:1px;height:1px"><img src="'+trailimage[0]+'" border="0" width="'+trailimage[1]+'px" height="'+trailimage[2]+'px"></div>')

function gettrailobj(){
if (document.getElementById)
return document.getElementById("trailimageid").style
else if (document.all)
return document.all.trailimagid.style
}

function hidett(){  gettrailobj().display="none";   }
function showtt(){  gettrailobj().display="block";  }

function truebody(){    return (document.body||document.documentElement);   }

function showtrail(shit){
    if (typeof shit == "undefined"){    //Follow Mouse
        follow=true;
        setmousepos(global_coord[0],global_coord[1]);
    }
    else {              //Set fixed in specific place
        follow=false;
        showtt()
        gettrailobj().left=shit.left+6+"px"
        gettrailobj().top=shit.top-5+"px"
    }
}

function hidetrail(){
    hidett()
    follow=false;
}

function setcoord(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
var xxcoord = e.pageX||(e.clientX+truebody().scrollLeft);
var yycoord = e.pageY||(e.clientY+truebody().scrollTop);
if (typeof xxcoord != "undefined"&&typeof yycoord != "undefined"){
    xcoord+=xxcoord;
    ycoord+=yycoord;
    global_coord=[xcoord,ycoord];
    if (follow) setmousepos(xcoord,ycoord);
}}

function setmousepos(xcoord,ycoord){
    var docwidth=truebody().scrollLeft+truebody().clientWidth   
    var docheight=Math.max(truebody().scrollHeight, truebody().clientHeight)
    if ((xcoord+trailimage[1]+3>docwidth || ycoord+trailimage[2]> docheight ||!follow)){
        hidett()
    }
    else{
        showtt();
        gettrailobj().left=xcoord+"px"
        gettrailobj().top=ycoord+"px"
    }
}

window.addEventListener("mouseout",
    function(e){
        mouseX = e.pageX;
        mouseY = e.pageY;
        if ((mouseY >= 0 && mouseY <= window.innerHeight)
        && (mouseX >= 0 && mouseX <= window.innerWidth)){
            return false;
        }else{
            if (follow) hidett()
        }
    },
    false);

document.onmousemove=setcoord;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM