JavaScript 应用程序:尝试使 "wheel" 事件侦听器不连续失败
JavaScript application: trying to make the "wheel" event listener discontinuous fails
我正在 Bootstrap 4 和 JavaScript 中开发一个小型 "Picture browser" 应用程序。
如下所示,有一个 "Prev" 和一个 "Next" 按钮可以帮助浏览图片。
我一直在努力寻找一种可靠的方法来使 鼠标滚动 的功能与这些按钮相同。向下滚动 相当于单击 "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()
功能确实有效,但过渡太...连续。我希望它与按钮触发的转换相同。
我错过了什么?
这里有几种解决方法:
-- 防止scroll滚动多张图片,可以使用这个函数:
// 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
以便它采用滚动图像的方向。 (示例:布尔值:true = 下一个,false = 上一个)
--要恢复滚动的方向,参考这个答案:
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>
我正在 Bootstrap 4 和 JavaScript 中开发一个小型 "Picture browser" 应用程序。
如下所示,有一个 "Prev" 和一个 "Next" 按钮可以帮助浏览图片。
我一直在努力寻找一种可靠的方法来使 鼠标滚动 的功能与这些按钮相同。向下滚动 相当于单击 "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()
功能确实有效,但过渡太...连续。我希望它与按钮触发的转换相同。
我错过了什么?
这里有几种解决方法:
-- 防止scroll滚动多张图片,可以使用这个函数:
// 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
以便它采用滚动图像的方向。 (示例:布尔值:true = 下一个,false = 上一个)
--要恢复滚动的方向,参考这个答案:
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>