我正在使用JQuery Draggable函数和Touch Punch来生成可以通过单击和拖动滚动的水平滑块列表。它在触摸和点击设备上运行良好。我面临的问题是,如果我尝试在触摸设备中向上或向下滚动,它就无法正常工作。
我查看了SO并发现删除" event.preventDefault"从TouchPunch允许垂直滚动,这个修复的问题是,它只适用于某些设备,而不是全部。
我想知道是否有人有任何其他解决方案,或者生成同样适用于触摸和点击事件的相同水平滑块的替代方法。
以下是示例代码(JQuery Draggable):
$(function() {
var slides = $('#list1 ul').children().length;
var slideWidth = $('#list1').width();
var min = 0;
var max = -((slides - 1) * slideWidth);
$("#list1 ul").width(slides * slideWidth).draggable({
axis: 'x',
drag: function(event, ui) {
if (ui.position.left > min) ui.position.left = min;
if (ui.position.left < max) ui.position.left = max;
}
});
$("#list2 ul").width(slides * slideWidth).draggable({
axis: 'x',
drag: function(event, ui) {
if (ui.position.left > min) ui.position.left = min;
if (ui.position.left < max) ui.position.left = max;
}
});
});
&#13;
#list1 {
position: relative;
height: 16em;
width: 100%;
text-align: middle;
white-space: nowrap;
overflow-x: hidden;
overflow-y: hidden;
}
#list1 .floating-box {
margin: auto;
display: inline-block;
width: 15em;
height: 13.5em;
margin: 0.1em;
border: 0.2em solid black;
background-color: white;
}
#list2 {
position: relative;
height: 16em;
width: 100%;
text-align: middle;
white-space: nowrap;
overflow-x: hidden;
overflow-y: hidden;
}
#lis2 .floating-box {
margin: auto;
display: inline-block;
width: 15em;
height: 13.5em;
margin: 0.1em;
border: 0.2em solid black;
background-color: white;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="list1">
<ul>
<p>One</p>
<div class="floating-box">Floating box</div>
<div class="floating-box">Floating box</div>
<div class="floating-box">Floating box</div>
</ul>
</div>
<div id="list2">
<ul>
<p>Two</p>
<div class="floating-box">Floating box</div>
<div class="floating-box">Floating box</div>
<div class="floating-box">Floating box</div>
</ul>
</div>
&#13;
如果我触摸list1或list2 div并尝试向上或向下滚动,则它不会识别该移动。任何帮助或指示将不胜感激。
答案 0 :(得分:4)
修改强>
基于根据pageY
的{{1}}属性确定划线方向的想法。
从长远来看,我认为避免烦人的双击(见下面的第一个答案)是一个好主意。
它仍有妥协,但它更合理。
我做了很多事情......我得到的最好结果就是当我放弃模拟touchemove
上的滚动时。
以下是我现在使用三个触摸事件中的每一个的方法:
touchstart 获取初始变量,例如:window scrollTop和pageY。
touchmove 确定滑动方向并获取最后一页Y.
touchend 进行数学计算,以确定页面应该滚动。
为了可爱,我将结果值放在touchmove
中
令我惊喜的是,它确实非常顺利地补偿了页面仅在.animate()
上滚动的事实。
我认为很少有用户会注意到它;)。
自&#34; Touch-Punch&#34;默认情况下正在进行水平滑动,&#34;妥协&#34;只会影响垂直滚动。
这是代码:
并live link在启用touche的设备上试用它。
touchend
<小时/>
首先,Touch Punch网站声称它基本上是一个jQuery-UI hack 来处理实际上未被jQuery-UI处理的一些案例...... 并且可以找到Touch Punch失败的情况。
您的问题已向Touch Punch开发人员here报告
作为对(在我这里的话)的回答,他们说它不是真的错误或问题......
但用法&#34;冲突&#34;在两个不同的&#34;希望&#34;使用相同触摸事件的动作
有时滚动页面,有时拖动元素。
作为解决方案提示,他们发布了this Fiddle 它建议找到一种在需要时禁用可拖动的方法。
但在此解决方案中,可滚动部分在可拖动元素中
哪不是你的情况。
并且您几乎可以将所有移动屏幕空间用于可拖动元素,因此不会留下任何空间来触发$(function() {
var slides = $('#list1 ul').children().length;
var slideWidth = $('#list1').width();
var min = 0;
var max = -((slides - 1) * slideWidth);
$(".draggable").width(slides * slideWidth).draggable({
axis: 'x',
drag: function(event, ui) {
if (ui.position.left > min) ui.position.left = min;
if (ui.position.left < max) ui.position.left = max;
}
});
var startTouchX=0;
var startTouchY=0;
var actualPosX;
var actualPosY;
var eventCounter=0;
var directionDetermined=false;
var direction;
var thisTouchX;
var thisTouchY;
var lastTouchY;
$(document).on("touchstart", function(e) {
// Actual document position
actualPosX = $(document).scrollLeft();
actualPosY = $(document).scrollTop();
// StartTouches
startTouchX = parseInt(e.originalEvent.touches[0].pageX);
startTouchY = parseInt(e.originalEvent.touches[0].pageY);
});
$(document).on("touchmove", function(e) {
// Arbitrary considering ONLY the fourth event...
// Touchmove fires way too many times!
// We only need to determine the main direction ONCE.
// This prevents an "s" swipe from messing this code.
eventCounter++;
if(eventCounter==4 && !directionDetermined){
thisTouchX = parseInt(e.originalEvent.touches[0].pageX);
thisTouchY = parseInt(e.originalEvent.touches[0].pageY);
if ( (Math.abs(thisTouchX - startTouchX)) / Math.abs(thisTouchY - startTouchY) > 1){ //check swipe direction
// HORIZONTAL
$("#debug").html("HORIZONTAL");
directionDetermined=true;
// NO NEED here. This is re-enabled on touchend, if it has been disabled.
//$(".draggable").draggable('enable');
}
else{
// VERTICAL
$("#debug").html("VERTICAL");
directionDetermined=true;
direction="vertical";
$(".draggable").draggable('disable'); // Disable draggable.
}
}
// Getting all the Y touches...
// The "last" value will be used on touchend.
lastTouchY = parseInt(e.originalEvent.touches[0].pageY);
//$("#debug").html(lastTouchY);
});
$(document).on("touchend", function(e) {
if(direction=="vertical"){
//$("#debug").html(lastTouchY);
var thisMoveY = -parseInt(lastTouchY - startTouchY);
//$("#debug").html(thisMoveY);
var newPosY = (actualPosY + thisMoveY);
//$("#debug").html(actualPosX+ " " +newPosY);
//window.scrollTo(actualPosX, newPosY);
$("html,body").animate({ scrollTop: newPosY },400);
}
// Reset everything for a future swipe.
startTouchX=0;
startTouchY=0;
eventCounter=0;
directionDetermined=false;
direction="";
$("#debug").html("");
// Re-enable draggable.
$(".draggable").draggable('enable');
});
});
周围的空间。
所以...我有这个想法,我希望能有所帮助。
如果您找到一种优雅的方式告知您的用户&#34;双击&#34;该怎么办?改变运动方向。
在这里,我建议一个非常简单的双箭头&#34;显示运动方向。
也许你会找到更好的东西。
这肯定是一个有点妥协的用户体验,要求他们双击...
但如果您的布局真的需要它,也许它没问题。
所以在这里,我复制了你的initial issue 这是the fix that I suggest。
我只在三星Galaxy S3上试过它,但应该可以在每个触控设备上使用。
draggable("disable")
double arrow的一些额外CSS。
$(function() {
var slides = $('#list1 ul').children().length;
var slideWidth = $('#list1').width();
var min = 0;
var max = -((slides - 1) * slideWidth);
$(".draggable").width(slides * slideWidth).draggable({
axis: 'x',
drag: function(event, ui) {
if (ui.position.left > min) ui.position.left = min;
if (ui.position.left < max) ui.position.left = max;
}
});
// Flag
var draggableEnabled=true;
// Find the doubletap position (to show a nice double arrow)
var tapPosition=[];
$(document).on("touchstart",function(e){
tapPosition[0] = parseInt(e.touches[0].pageX) - $(document).scrollLeft() - ($("#arrows img").width()/2);
tapPosition[1] = parseInt(e.touches[0].pageY) - $(document).scrollTop() - ($("#arrows img").width()/2);
});
Hammer(document).on("doubletap", function() {
//alert("Double tap");
draggableEnabled = !draggableEnabled; // Toggle
if(!draggableEnabled){
$(".draggable").draggable('disable'); // Disables draggable (and touch Punch)
$("#arrows img").css({
"transform":"rotate(90deg)", // Nice vertical double arrow
"top":tapPosition[1],
left:tapPosition[0]
}).fadeIn(600, function(){
$(this).fadeOut(600);
});
}else{
$(".draggable").draggable('enable'); // Enables draggable (and touch Punch)
$("#arrows img").css({
"transform":"rotate(0deg)", // Nice horizontal double arrow
"top":tapPosition[1],
left:tapPosition[0]
}).fadeIn(600, function(){
$(this).fadeOut(600);
});
}
});
});
答案 1 :(得分:0)
这是我最接近它的,我想知道是否有人可以改进这段代码:
$(watchlist).on("touchstart", function(e) {
touchY = e.originalEvent.touches[0].pageY;
touchX = e.originalEvent.touches[0].pageX;
});
$(watchlist).on("touchmove", function(e) {
var fTouchY = e.originalEvent.touches[0].pageY;
var fTouchX = e.originalEvent.touches[0].pageX;
if ((Math.abs(fTouchX - touchX)) / Math.abs(fTouchY - touchY) > 1){ //check swipe direction
$("#watchlist ul").draggable( 'enable'); //if swipe is horizontal
}
else{
$("#watchlist ul").draggable( 'disable'); //if swipe is horizontal
}
});
此代码存在的问题是,只有在触摸移动完成后才停用可拖动功能。如果任何人都可以修改此代码,以便在条件满足期间停用可拖动功能,则在touchmove
期间,而不是之后,我会给予他们赏金。