简体   繁体   中英

press and hold button emulate scroll

I have a function bound on button "onmousedown", which emulates scrolling through a div. problem arises with multiple fast clicks and press and hold for too long.

for example, if the user scrolls to the bottom of the div, and quickly clicks multiple times on "down" button, the OL inside the div is jittering up and down very fast (faster than 33ms which is the fastest scroll speed possible). I believe that it creates multiple timer objects which each scroll the div without clearing those objects?

another problem is that, if the button is held for too long and released, it acts like the button is still held down. (which scroll at the 33ms rate). Seems like it forgot to delete timer object once the mouse is lifted from the button

To solve the second problem, the user has to click the button once in the opposite direction of the scroll, and it becomes static again.

HTML 文档中的 div 示例

this is the div inside which needs to be scrolled

  function scrollButton(btn, start, speedUp, eDiv, upward) {
    var tempStart = start;

    var repeat = function () {
      //check for boundary conditions
      if (eDiv.scrollTop >= 0 && eDiv.scrollTop <= (eDiv.scrollHeight - eDiv.clientHeight)) {
        scrollErrorLog(eDiv, upward);
      }
      //fire scroll method and reduce time interval
      t = setTimeout(repeat, start);
      if (start > 60) {
        start = Math.round(start / speedUp);
      } else start = 33;
    }

    //bind functions to button events
    btn.onmousedown = function () {
      repeat();
    }
    btn.onmouseup = function () {
      clearTimeout(t);
      start = tempStart;
    }
    btn.onmouseout = function () {
      clearTimeout(t);
      start = tempStart;
    }
    btn.ontouchcancel = function () {
      clearTimeout(t);
      start = tempStart;
    }
    btn.ontouchend = function () {
      clearTimeout(t);
      start = tempStart;
    }
    btn.ontouchstart = function () {
      repeat();
    }
  }

  var scrollErrorLog = function (eDiv, upward) {
    //calculate maximum scroll height
    var maxScrollHeight = eDiv.scrollHeight - eDiv.clientHeight;
    //how much scroll in one button click iteration
    var jumpSize = 40;
    //going up or down?
    if (upward) {
      if (eDiv.scrollTop > 0) {
        scrollTimes--;
      }
    } else {
      if (eDiv.scrollTop < maxScrollHeight) {
        scrollTimes++;
      }
    }
    //scroll the div
    if (eDiv.scrollTop >= 0 && eDiv.scrollTop <= maxScrollHeight) {
      eDiv.scrollTop = scrollTimes * jumpSize;
    }
    // if out of bounds, return to start position and reset scrollTimes tracker variable
    if (eDiv.scrollTop < 0 || scrollTimes < 0) {
      eDiv.scrollTop = 0;
      scrollTimes = 1;
    } else if (eDiv.scrollTop > maxScrollHeight) {
      eDiv.scrollTop = maxScrollHeight;
      scrollTimes = maxScrollHeight / jumpSize;
    }
  }

EDIT: I used this question as a guideline: Need javascript code for button press and hold

EDIT #2: this needs to work mainly on touch. on button click it sometimes does this and sometimes doesn't. on touch panel it does those 2 errors constantly.

Solution until someone finds something more efficient.

Created new global variable compareScroll = 0; then just check if the compareScroll != scrollTimes before scrolling, and at the end of the function make compareScroll = scrollTimes

  //where we are currently
  var scrollTimes = 1;
  //check if scrolltimes is at the end
  var compareScroll = 0;

  var scrollErrorLog = function (eDiv, upward) {
    //calculate maximum scroll height
    var maxScrollHeight = eDiv.scrollHeight - eDiv.clientHeight;
    //how much scroll in one button click iteration
    var jumpSize = 40;
    //going up or down?
    if (upward) {
      if (eDiv.scrollTop > 0) {
        scrollTimes--;
      }
    } else {
      if (eDiv.scrollTop < maxScrollHeight) {
        scrollTimes++;
      }
    }
    //checking if we are not at the end of the DIV
    if (compareScroll != scrollTimes) {
      //scroll the div
      if (eDiv.scrollTop >= 0 && eDiv.scrollTop <= maxScrollHeight) {
        eDiv.scrollTop = scrollTimes * jumpSize;
      }
      compareScroll = scrollTimes;
    } else {
      //if we are at the end of the div reset everything
      clearTimeout(t);
      // if out of bounds, return to start position and reset scrollTimes tracker variable
      if (eDiv.scrollTop < 0 || scrollTimes < 0) {
        eDiv.scrollTop = 0;
        scrollTimes = 1;
      } else if (eDiv.scrollTop > maxScrollHeight) {
        eDiv.scrollTop = maxScrollHeight;
        scrollTimes = maxScrollHeight / jumpSize;
      }
    }
  }

EDIT: this still doesn't solve the problem of automatic scroll while not at the end still.

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