移动设备上的 BXSlider 4 全屏:如何保持本机垂直页面滚动(向上、向下)但保持水平触摸功能(左、右)?
BXSlider 4 fullscreen on mobile devices: How to keep native vertical page scroll (up, down) but keep horizontal touch functionality (left,right)?
以下代码段应该可以很好地说明问题:
(function ($) {
$('.bxslider').each(function() {
var bxid = $(this).attr("data-bxid");
var bx = $(this).bxSlider({
auto: false,
autoStart: false
});
});
})(jQuery);
/* Styles */
#before, #after {
width:350px;
height:350px;
background-color:#ccf;
}
/* BXSlider */
.bx-wrapper {
position: relative;
margin-bottom: 60px;
padding: 0;
*zoom: 1;
-ms-touch-action: pan-y;
touch-action: pan-y;
}
.bx-wrapper img {
max-width: 100%;
display: block;
}
.bxslider {
background-color:#eee;
margin: 0;
padding: 0;
/*fix flickering when used background-image instead of <img> (on Chrome)*/
-webkit-perspective: 1000;
}
ul.bxslider {
list-style: none;
width:100%;
}
ul.bxslider li {
width:100%;
}
.bx-viewport {
/* fix other elements on the page moving (in Chrome) */
-webkit-transform: translateZ(0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.15/jquery.bxslider.min.js"></script>
<div id="before"></div>
<ul class="bxslider">
<li><p>If you touch me vertically ...<img src="https://via.placeholder.com/500x350"></li>
<li>... I want to scroll down normally ...<img src="https://via.placeholder.com/500x250"></li>
<li>... but nothing happens <img src="https://via.placeholder.com/500x450"></li>
</ul>
<div id="after"></div>
在浏览器的开发人员工具中 window 尝试在 运行 代码段中通过触摸向下滚动 - 这是不可能的。然而,这不是一个选项,因为全屏水平 bxSlider 访问者正在完全失去浏览网站的能力 - 不可接受!
bxSlider 提供以下设置:
touchEnabled:false
但这也不是一个选项,因为智能手机访问者确实应该能够用手指将幻灯片切换到 right/to 左侧。
因此我需要这样一种可能性:
- HORIZONTAL touch move: 平滑移动到滑块内的 next/previous slide。
- 垂直触摸移动:只需保持视口在浏览器中的正常滚动即可。
不幸的是,我还没有找到任何 bxslider 设置组合如何实现这一点。你知道这个的解决方案吗(最好不修改 bxslider 核心文件本身)?
我在 jquery.bxslider.js 中编辑了 onTouchStart
函数。
将下面的代码复制并替换为原始的onTouchStart功能代码(从1103行开始):
var onTouchStart = function(e) {
// watch only for left mouse, touch contact and pen contact
// touchstart event object doesn`t have button property
if (e.type !== 'touchstart' && e.button !== 0) {
return;
}
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){ } else { e.preventDefault(); }
});
//disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls
slider.controls.el.addClass('disabled');
if (slider.working) {
slider.controls.el.removeClass('disabled');
} else {
// record the original position when touch starts
slider.touch.originalPos = el.position();
var orig = e.originalEvent,
touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig];
var chromePointerEvents = typeof PointerEvent === 'function';
if (chromePointerEvents) {
if (orig.pointerId === undefined) {
return;
}
}
// record the starting touch x, y coordinates
slider.touch.start.x = touchPoints[0].pageX;
slider.touch.start.y = touchPoints[0].pageY;
if (slider.viewport.get(0).setPointerCapture) {
slider.pointerId = orig.pointerId;
slider.viewport.get(0).setPointerCapture(slider.pointerId);
}
// store original event data for click fixation
slider.originalClickTarget = orig.originalTarget || orig.target;
slider.originalClickButton = orig.button;
slider.originalClickButtons = orig.buttons;
slider.originalEventType = orig.type;
// at this moment we don`t know what it is click or swipe
slider.hasMove = false;
// on a "touchmove" event to the viewport
slider.viewport.on('touchmove MSPointerMove pointermove', onTouchMove);
// on a "touchend" event to the viewport
slider.viewport.on('touchend MSPointerUp pointerup', onTouchEnd);
slider.viewport.on('MSPointerCancel pointercancel', onPointerCancel);
}
};
编辑(Fiddle):https://jsfiddle.net/Blackbam/sk2ve907/2/
以下代码段应该可以很好地说明问题:
(function ($) {
$('.bxslider').each(function() {
var bxid = $(this).attr("data-bxid");
var bx = $(this).bxSlider({
auto: false,
autoStart: false
});
});
})(jQuery);
/* Styles */
#before, #after {
width:350px;
height:350px;
background-color:#ccf;
}
/* BXSlider */
.bx-wrapper {
position: relative;
margin-bottom: 60px;
padding: 0;
*zoom: 1;
-ms-touch-action: pan-y;
touch-action: pan-y;
}
.bx-wrapper img {
max-width: 100%;
display: block;
}
.bxslider {
background-color:#eee;
margin: 0;
padding: 0;
/*fix flickering when used background-image instead of <img> (on Chrome)*/
-webkit-perspective: 1000;
}
ul.bxslider {
list-style: none;
width:100%;
}
ul.bxslider li {
width:100%;
}
.bx-viewport {
/* fix other elements on the page moving (in Chrome) */
-webkit-transform: translateZ(0);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bxslider/4.2.15/jquery.bxslider.min.js"></script>
<div id="before"></div>
<ul class="bxslider">
<li><p>If you touch me vertically ...<img src="https://via.placeholder.com/500x350"></li>
<li>... I want to scroll down normally ...<img src="https://via.placeholder.com/500x250"></li>
<li>... but nothing happens <img src="https://via.placeholder.com/500x450"></li>
</ul>
<div id="after"></div>
在浏览器的开发人员工具中 window 尝试在 运行 代码段中通过触摸向下滚动 - 这是不可能的。然而,这不是一个选项,因为全屏水平 bxSlider 访问者正在完全失去浏览网站的能力 - 不可接受!
bxSlider 提供以下设置:
touchEnabled:false
但这也不是一个选项,因为智能手机访问者确实应该能够用手指将幻灯片切换到 right/to 左侧。
因此我需要这样一种可能性:
- HORIZONTAL touch move: 平滑移动到滑块内的 next/previous slide。
- 垂直触摸移动:只需保持视口在浏览器中的正常滚动即可。
不幸的是,我还没有找到任何 bxslider 设置组合如何实现这一点。你知道这个的解决方案吗(最好不修改 bxslider 核心文件本身)?
我在 jquery.bxslider.js 中编辑了 onTouchStart
函数。
将下面的代码复制并替换为原始的onTouchStart功能代码(从1103行开始):
var onTouchStart = function(e) {
// watch only for left mouse, touch contact and pen contact
// touchstart event object doesn`t have button property
if (e.type !== 'touchstart' && e.button !== 0) {
return;
}
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){ } else { e.preventDefault(); }
});
//disable slider controls while user is interacting with slides to avoid slider freeze that happens on touch devices when a slide swipe happens immediately after interacting with slider controls
slider.controls.el.addClass('disabled');
if (slider.working) {
slider.controls.el.removeClass('disabled');
} else {
// record the original position when touch starts
slider.touch.originalPos = el.position();
var orig = e.originalEvent,
touchPoints = (typeof orig.changedTouches !== 'undefined') ? orig.changedTouches : [orig];
var chromePointerEvents = typeof PointerEvent === 'function';
if (chromePointerEvents) {
if (orig.pointerId === undefined) {
return;
}
}
// record the starting touch x, y coordinates
slider.touch.start.x = touchPoints[0].pageX;
slider.touch.start.y = touchPoints[0].pageY;
if (slider.viewport.get(0).setPointerCapture) {
slider.pointerId = orig.pointerId;
slider.viewport.get(0).setPointerCapture(slider.pointerId);
}
// store original event data for click fixation
slider.originalClickTarget = orig.originalTarget || orig.target;
slider.originalClickButton = orig.button;
slider.originalClickButtons = orig.buttons;
slider.originalEventType = orig.type;
// at this moment we don`t know what it is click or swipe
slider.hasMove = false;
// on a "touchmove" event to the viewport
slider.viewport.on('touchmove MSPointerMove pointermove', onTouchMove);
// on a "touchend" event to the viewport
slider.viewport.on('touchend MSPointerUp pointerup', onTouchEnd);
slider.viewport.on('MSPointerCancel pointercancel', onPointerCancel);
}
};
编辑(Fiddle):https://jsfiddle.net/Blackbam/sk2ve907/2/