代码之家  ›  专栏  ›  技术社区  ›  Razvan Zamfir

javascript应用程序:试图使“wheel”事件侦听器不连续失败

  •  0
  • Razvan Zamfir  · 技术社区  · 7 年前

    我正在用bootstrap 4和javascript开发一个小的“图片浏览器”应用程序。

    如下图所示,有一个“prev”和一个“next”按钮帮助浏览图片。

    我想找个可靠的方法 鼠标滚动 功能与这些按钮相同。滚动 向下 相当于点击“下一步”按钮。滚动 向上的 相当于点击“prev”按钮。

    var picArr = $('#pictures_list li');
    // The index of the last element of the array is "maxIndex"
    var maxIndex = picArr.length - 1;
    // Initialize counter
    var counter = 0;
    var updateCounter = function(btn) {
      var direction = $(btn).data("direction")
      if (direction === "left") {
        if (counter > 0) {
          counter--;
        } else {
          counter = maxIndex;
        }
      } else {
        if (counter < maxIndex) {
          counter++;
        } else {
          counter = 0;
        }
      }
    }
    
    var showCount = function(container_id) {
      var pageCount = counter + 1;
      document.getElementById(container_id).innerHTML = "Picture " + pageCount + " of " + picArr.length;
    }
    
    var showSlide = function() {
      var mTop = (200 * counter) * (-1) + 'px';
      $('#pictures_list').animate({
        'marginTop': mTop
      }, 400);
    }
    
    showCount('show_count');
    
    $('#controls button').on('click', function() {
      updateCounter(this);
      showSlide();
      showCount('show_count');
    });
    
    document.getElementById("picture_frame").addEventListener("wheel", function() {
      updateCounter(this);
      showSlide();
      showCount('show_count')
    });
    #picture_frame {
      width: 200px;
      height: 200px;
      margin: 5px auto;
      border: 1px solid #ccc;
      border-radius: 2px;
      overflow: hidden;
    }
    
    .controls>div {
      display: inline-block;
    }
    
    #picture_frame {
      height: 200px;
      overflow: hidden;
    }
    
    #pictures_list {
      flex-flow: row wrap;
      align-items: stretch;
      width: 200px;
    }
    
    #pictures_list li {
      display: flex;
      height: 200px;
      flex: 1 100%;
    }
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="container">
      <div id="picture_frame">
        <ul id="pictures_list" class="list-unstyled d-flex">
          <li><img src="https://picsum.photos/200/200
    " alt="First picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=east
    " alt="Second picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=west
    " alt="Third picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=north
    " alt="Fourth picture"></li>
        </ul>
      </div>
      <div class="text-center mb-2">
        <span class="badge badge-primary" id="show_count"></span>
      </div>
      <div class="controls text-center">
        <div class="btn-group" id="controls">
          <button type="button" class="btn btn-primary btn-sm" data-direction="left">Prev</button>
          <button type="button" class="btn btn-primary btn-sm" data-direction="right">Next</button>
        </div>
      </div>
    </div>

    发射 showSlide() 鼠标滚轮上的功能确实起作用,但过渡也会… 连续的 .我希望它与按钮触发的转换相同。

    我错过了什么?

    1 回复  |  直到 7 年前
        1
  •  0
  •   Alex83690    7 年前

    以下是几种解决方案:

    --要防止滚动滚动多个图像,可以使用以下功能:

    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    function debounce(func, wait, immediate) {
        var timeout;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) func.apply(context, args);
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) func.apply(context, args);
        };
    };
    

    参见 https://davidwalsh.name/javascript-debounce-function

    --您应该更改函数的参数 updateCounter 这样它就可以向滚动图像的方向移动。(示例:布尔值:真=下一个,假=上一个)

    --要恢复滚动方向,请参阅以下答案: https://stackoverflow.com/a/45719399/4864628

    var picArr = $('#pictures_list li');
    // The index of the last element of the array is "maxIndex"
    var maxIndex = picArr.length - 1;
    // Initialize counter
    var counter = 0;
    var updateCounter = function(direction) {
      if (direction) {
        if (counter > 0) {
          counter--;
        } else {
          counter = maxIndex;
        }
      } else {
        if (counter < maxIndex) {
          counter++;
        } else {
          counter = 0;
        }
      }
    }
    
    var showCount = function(container_id) {
      var pageCount = counter + 1;
      document.getElementById(container_id).innerHTML = "Picture " + pageCount + " of " + picArr.length;
    }
    
    var showSlide = function() {
      var mTop = (200 * counter) * (-1) + 'px';
      $('#pictures_list').animate({
        'marginTop': mTop
      }, 400);
    }
    
    // Returns a function, that, as long as it continues to be invoked, will not
        // be triggered. The function will be called after it stops being called for
        // N milliseconds. If `immediate` is passed, trigger the function on the
        // leading edge, instead of the trailing.
        function debounce(func, wait, immediate) {
        	var timeout;
        	return function() {
        		var context = this, args = arguments;
        		var later = function() {
        			timeout = null;
        			if (!immediate) func.apply(context, args);
        		};
        		var callNow = immediate && !timeout;
        		clearTimeout(timeout);
        		timeout = setTimeout(later, wait);
        		if (callNow) func.apply(context, args);
        	};
        };
        
    showCount('show_count');
    
    $('#controls button').on('click', function() {
      updateCounter($(this).attr('data-direction') == 'left');
      showSlide();
      showCount('show_count');
    });
    
    var pictureFrame = document.getElementById("picture_frame");
    var onScroll = debounce(function(direction) {
      updateCounter(direction);
      showSlide();
      showCount('show_count')
    }, 100, true);
    
    pictureFrame.addEventListener("wheel", function(e) {
      e.preventDefault();
      var delta;
      if (event.wheelDelta){
          delta = event.wheelDelta;
      }else{
          delta = -1 * event.deltaY;
      }
      
      onScroll(delta >= 0);
    });
    #picture_frame {
      width: 200px;
      height: 200px;
      margin: 5px auto;
      border: 1px solid #ccc;
      border-radius: 2px;
      overflow: hidden;
    }
    
    .controls>div {
      display: inline-block;
    }
    
    #picture_frame {
      height: 200px;
      overflow: hidden;
    }
    
    #pictures_list {
      flex-flow: row wrap;
      align-items: stretch;
      width: 200px;
    }
    
    #pictures_list li {
      display: flex;
      height: 200px;
      flex: 1 100%;
    }
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="container">
      <div id="picture_frame">
        <ul id="pictures_list" class="list-unstyled d-flex">
          <li><img src="https://picsum.photos/200/200
    " alt="First picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=east
    " alt="Second picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=west
    " alt="Third picture"></li>
          <li><img src="https://picsum.photos/200/200?gravity=north
    " alt="Fourth picture"></li>
        </ul>
      </div>
      <div class="text-center mb-2">
        <span class="badge badge-primary" id="show_count"></span>
      </div>
      <div class="controls text-center">
        <div class="btn-group" id="controls">
          <button type="button" class="btn btn-primary btn-sm" data-direction="left">Prev</button>
          <button type="button" class="btn btn-primary btn-sm" data-direction="right">Next</button>
        </div>
      </div>
    </div>