2

I have a rectangle I am trying to move using javascript. I can get it to move left and right using functions, but when I hold the mouse down it doesn't continue to move. Here is my html code:

<button onmousedown="moveLeft();" onmouseup="stopMove();">LEFT</button>
<button onmousedown="moveRight();" 
onmouseup="stopMove();">RIGHT</button><br><br>

Here is my javascript code (the conditional statements are just so the rectangle doesn't move off of the canvas):

function moveLeft () {
    xx-=20; 
    if (xx<0) { 
        xx=0;
    }
}

function moveRight() {
    xx+=20; 
    if (xx>400) { 
        xx=400;
    }
}

function stopMove () {
    xx+=0;
}
Amber
  • 25
  • 1
  • 1
  • 5
  • 1
    You need to use an interval – epascarello May 12 '17 at 13:23
  • You can register a global mousemove event listener. Or you can use one of the thousand libs out there, which are already optimized for most browsers. JQueryUI for example. – Mijago May 12 '17 at 13:28
  • Instead of jquery ui, which is not optimized for browsers, I would use velocity. – christo8989 May 12 '17 at 13:29
  • What is this project for? – christo8989 May 12 '17 at 13:36
  • Intro to programming – Amber May 12 '17 at 13:42
  • @Amber PLEASE beg your instructor to STOP teaching inline HTML event attributes (`onmouseover`, etc.) and instead to teach modern, standards-based programming. ;) – Scott Marcus May 12 '17 at 14:11
  • @ScottMarcus I wish I could! He is very old-school and wants things done his way. I've struggled a lot in this class because people I ask have these great ideas, but he will downgrade if it's not done how he wants it :( – Amber May 12 '17 at 14:48
  • @Amber That's really a shame. If you are paying for this class, I'd seriously address this with the department head because he isn't doing you any favors by teaching you outdated techniques. – Scott Marcus May 12 '17 at 15:36

2 Answers2

3

When you press a mouse button, the mousedown event will fire just once. It does not continuously fire while you have the button held down. What you'll need to do is use a timer to begin the movement and then, on mouseup, stop the timer.

Also, don't use inline HTML event handlers (onmouseover, onmouseout, etc.). Here's why.

Lastly, since your moveLeft and moveRight functions are essentially the same thing, they can be combined into one function that simply takes in an argument that determines the direction.

Here's a working example:

// Get references to the HTML elements you'll need to interact with:
var btnLeft = document.getElementById("btnLeft");
var btnRight = document.getElementById("btnRight");
var box = document.getElementById("box");

// Set up event handlers for the HTML elements in JavaScript, using modern
// standards, not in the HTML. Both the left and right buttons need to 
// call the same function, but with a different argument value. This is
// why the events are being bound to another function that wraps the actual
// call to the move function (so that an argument can be passed).
btnLeft.addEventListener("mousedown", function(){ move(-20); });
btnRight.addEventListener("mousedown", function(){ move(20); });
btnLeft.addEventListener("mouseup", stopMove);
btnRight.addEventListener("mouseup", stopMove);

// The counter needs to be accessible between calls to move
var xx = 0;

// We'll start an automatic timer, but we'll need to stop it later
// so we need a variable set up for that.
var timer = null;

// Only one function is needed to address the move operation
// The argument is what determines the direction
function move(amount) {

    // Stop any previous timers so that we don't get a runaway effect
    clearTimeout(timer);
    
    xx += amount; 
    
    // Check the new position to see if it is off the visible page
    if (xx < 0){
        xx = window.innerWidth;
    } else if(xx > window.innerWidth){
        xx = 0;
    }
    
    // Just displaying the current value
    box.textContent = xx;
    
    // Move the box to the new location
    box.style.left = xx + "px";
    
    // Run the timer after a 250 millisecond delay and have
    // it call this function again. Assign the variable to
    // the timer.
    timer = setTimeout(function() { move(amount) }, 250);  
}

function stopMove () {
    xx += 0;
    // Stop the timer
    clearTimeout(timer);
}
#box {
  background-color:blue;
  border:2px solid black;
  color:yellow;
  text-align:center;
  font-weight:bold;
  padding-top:.5em;
  margin-top:3em;
  
  /* Everything above is just for display and not actually needed.
     But in order to move the box and to be able to have a consistent
     size for it, the following is required: */
  position:absolute;
  height:50px;
  width:50px;
}
<button id="btnLeft">LEFT</button>
<button id="btnRight">RIGHT</button>
    
<div id="box"></div>
Community
  • 1
  • 1
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
2

Since the mouse evet does not fire while it is down, you need to fire the event manually until you detect the other event. So to do this, you need to either use setInterval or setTimeout

var moveTimer,
    xx = 200;

function move (dir) {
    xx+=20*dir; 
    if (xx<0) { 
        xx=0;
    } else if (xx>400) {
       xx=400
    }
    stopMove()
    moveTimer = window.setTimeout(move.bind(this,dir), 100)
    document.getElementById("out").value = xx;
}

function stopMove () {
    if(moveTimer) window.clearTimeout(moveTimer);
    moveTimer = null
}

window.addEventListener("mouseup", stopMove)
<button onmousedown="move(-1);">LEFT</button>
<button onmousedown="move(1);">RIGHT</button>

<input type="number" id="out"/>
epascarello
  • 204,599
  • 20
  • 195
  • 236