touchmove事件指示的自定义滑动事件

时间:2014-12-15 08:33:32

标签: javascript jquery html ios css

我正在尝试创建一种插件或事件,通过在ipad上滑动来转换(移动)元素。为此,我到目前为止使用了cocco的明亮工作小代码片段:

(function(D){
  var M=Math,abs=M.abs,max=M.max,
  ce,m,th=20,t,sx,sy,ex,ey,cx,cy,dx,dy,l,
  f={
    touchstart:function(e){
    t=e.touches[0];
    sx=t.pageX;
    sy=t.pageY
  },
  touchmove:function(e){
    m=1;
    t=e.touches[0];
    ex=t.pageX;
    ey=t.pageY
  },
  touchend:function(e){
    ce=D.createEvent("CustomEvent");
    ce.initCustomEvent(m?(
    max(dx=abs(cx=ex-sx),dy=abs(cy=ey-sy))>th?
    dx>dy?cx<0?'swl':'swr':cy<0?'swu':'swd':'fc'
    ):'fc',true,true,e.target);
    e.target.dispatchEvent(ce);
    m=0
  },
  touchcancel:function(e){
    m=0
  }
}
for(l in f)D.addEventListener(l,f[l],false)
})(document);

对于转换rico st.cruz'插件jquery-transit.js在我的网站上实现(当然还有jquery)

//用法(示例)

$("body").on( 'swu', function() {
    fullscreenSwipeUp = true;
    $("#Fullscreen").transition( { y: '-100%' }, 900, 'easeInSine' )
} );

到目前为止一切顺利。 现在我的想法是通过额外的触摸移动事件来指示可能的“向上滑动”,该事件在手指敲击的同时移动元素。我成功地添加了以下js:

// js以更酷的方式集成的部分

var startY;

window.addEventListener( 'touchstart', function(e) {
  e.preventDefault();   
  startY = e.targetTouches[0].pageY;
}, false );

window.addEventListener( 'touchmove', function(e) {
  e.preventDefault();
  // check if transition is going on and animations are ready
  if ( !fullscreenSwipeUp ) { // find better solution f.e. to dispatch event on fullscreen transition?

    var diffY = e.changedTouches[0].pageY - startY;

    // fullscreen transition
    if ( diffY <= 0 ) {
        $("#Fullscreen").css( { y: diffY } );
    } else {
        // snap to clean starting value at bottom
        $("#Fullscreen").css( { y: 0 } );
    };
    // do something else to indicate that swipe will be concluded when finger leaves
    // min value based on variable th from custom swipe event
    if ( diffY < -20 ) {
        // indicate that swipe will be concluded
    } else {
        // indicate that swipe will not conclude
    };

  };        
}, false );

// fullscreen fall back to bottom if swipe not concluded
window.addEventListener( 'touchend', function(e) {
  e.preventDefault();   
  if ( !fullscreenSwipeUp ) {
    // fall back to starting values / dequeue for smoother transition on second time
    $("#Fullscreen").dequeue().transition( { y: 0 }, 150, 'easeInSine' );      
  };
}, false ); 

现在我也看到,在这段代码中,各个部分相互重叠,作为来自基本自定义事件和我的东西的双触摸移动事件。如果有人可以让我知道如何整合这两个代码,那将会非常棒。或者也许这样的东西存在?我找不到合适的东西。

感谢您的帮助!

PS我试图在这里创建一个小提琴:http://jsfiddle.net/Garavani/9zosg3bx/1/ 但遗憾的是,我太愚蠢了,无法使用所有外部脚本: - (

的jquery-transit.js: http://ricostacruz.com/jquery.transit/

修改

所以我按以下方式更改了代码。 我想我在原始滑动事件(其中也包含触摸移动事件)和我想要对元素做的事情之间感到困惑。 虽然可能还是一团糟,但它仍有效。 我必须设置一种标志来检查是否执行滑动以暂时禁用触摸移动事件。有没有更好的方法呢?谢谢你的耐心等待!

var startY;
var swipeY = false; // for condition if condition for swipe is fullfilled
var swiped = false; // for check if swipe has been executed

window.addEventListener( 'touchstart', function(e) {
    e.preventDefault(); 
    startY = e.targetTouches[0].pageY;
}, false );

window.addEventListener( 'touchmove', function(e) {
    e.preventDefault();
    // check if swipe already executed
    if ( !swiped ) { // find better solution f.e. to dispatch event when swiped?

        var diffY = e.changedTouches[0].pageY - startY;

        // check for final swipe condition
        if ( diffY < -30 ) {
            swipeY = true;
            // do something with an element to indicate swipe will be executed
        } else {
            swipeY = false;
            // do something with an element to indicate swipe will NOT be executed
        };
    };      
}, false );

window.addEventListener( 'touchend', function(e) {
    e.preventDefault(); 
    if ( swipeY ) {
        swiped = true;
        // trigger the swipe action
    } else {
        // let the element fall back to original state     
    };
}, false ); 

编辑2:

var startY;
var swipeY = false;
var swiped = false;
var wh = $(window).height();

// fullscreen move on touchmove
function fm(e) {

    e.preventDefault();
    // check if transition is going on and animations are ready
    if ( !swiped && ready ) { // !swiped is necessary, also / why?

        var diffY = e.changedTouches[0].pageY - startY;
        var scaleY = diffY/wh;
        // calculate transition intermediate values
        var osh = 0.91 - ( 0.09 * scaleY );
        var ofsc = 0.86 - ( 0.14 * scaleY );
        // fullscreen transition
        if ( diffY <= 0 ) {
            tfs(osh,[1,-scaleY],ofsc,diffY,0) // an extra module that does the animation with the calculated values
        } else {
            // snap to clean starting values at bottom
            tfs(0.91,[1,0],0.86,0,0)
        };
        // rotate arrow to indicate surpassing minimum touch move leading to swipe
        if ( diffY < -30 ) {
            swipeY = true;
            $arrowDown.addClass('rotation');
        } else {
            swipeY = false;
            $arrowDown.removeClass('rotation');
        };
    };
};
// fullscreen swipe
function fs(e) {

    e.preventDefault();
    window.removeEventListener( 'touchmove', fm, false );
    if ( !swiped ) { // this is necessary, also / why?          
        if ( swipeY ) {         
            $arrowbottomField.trigger('touchstart'); // trigger the full swipe (also available as element direct touch (on touch swiped is set to true in touchstart event handler, also)
            window.removeEventListener( 'touchend', fs, false );
        } else {
            // fall back of animation to starting values
            tfs(0.91,[1,0],0.86,0,0);      
        };
    };
};

window.addEventListener( 'touchstart', function(e) {
    e.preventDefault(); 
    startY = e.targetTouches[0].pageY;  

    window.addEventListener( 'touchmove', fm, false );      
}, false );

window.addEventListener( 'touchend', fs, false );

解释(尽我所能) 再次感谢Cocco的耐心等待。 与此同时,我再次修改了代码。 它的工作原理:-)我知道你眼中会一团糟。

在我的网站上(假设也可以在ipad上工作,但不仅仅是),你可以触摸一个字段,全屏向上移动覆盖整个窗口(类似于www.chanel.com - &gt;“更多” )。 此外,它(在ipad上)可以在整个身体上滑动以做同样的事情。

固定相:

阶段1)用户点击和滑动(保持手指开启)全屏div跟随他的手指。

Phase_1

暂停2)如果到达滑动的某个距离(仍然用手指打开),一个小箭头也会转动以指示:如果您现在离开,将执行滑动

Phase_2

暂停3)仍然用手指在距离上变得小于完成滑动的箭头,箭头转回来

Phase_3

阶段4)用手指离开已经覆盖的距离决定全屏是完全向上移动还是向下降(如果距离不够)

Phase_4a Phase_4b

对于小箭头来说,我可以使用类切换,因为你告诉我(比我做的更好!谢谢),但对于动画的其余部分,不是因为值强烈依赖于窗口大小。我的整个网站的想法是浏览器窗口可以有任何大小或关系,所有内容自我调整(包含任何时间的水平和垂直居中)

对于手机来说,一切都会彻底改变。

如果您想看看:www.stefanseifert.com(如果您想看到效果(在ipad上),您必须通过触摸预告片底部右下角的箭头跳过介绍)

我知道还有很多其他的东西都是最先进的编程技术(非常谨慎地说:-)但是在某种程度上它起作用。 而且我几个星期都不能雇佣程序员来重做一切。 ;-) 这是一种边做边学(因为你可以猜到我以前从未在我的生活中编程;-) 所以我非常感谢所有的信息,并帮助做更好的事情。

如果有人会通过这里,我肯定会得到一些投票:-) 谢谢Cocco 圣诞快乐!

1 个答案:

答案 0 :(得分:2)

该代码实际上是针对低CPU设备而设计的,性能很高。在touchmove中省略了复杂的计算。无论如何动画你的元素(在touchstart和touchend之间)一个简单的解决方案是使用css(而不是jquery或其他资源密集的插件)。

然后只是从逻辑上思考......你无法确定你在触摸开始滑动的方向......你可以在做一些数学后的touchend事件中做到这一点。或者,当touchmove破坏整个代码时,如上所述。

选项1(简单和高性能)

样本

http://jsfiddle.net/z7s8k9r4/

添加一些行......

(function(D){
 var M=Math,abs=M.abs,max=M.max,
 ce,m,th=20,t,sx,sy,ex,ey,cx,cy,dx,dy,l,
 T,  //<- THE TARGET
 f={
  touchstart:function(e){
    t=e.touches[0];
    sx=t.pageX;
    sy=t.pageY;
    T=e.target; T.classList.add('sw'); //<- ADD A CUSTOM CLASS FOR SWIPES
  },
  touchmove:function(e){
    m=1;
    t=e.touches[0];
    ex=t.pageX;
    ey=t.pageY
  },
  touchend:function(e){
    ce=D.createEvent("CustomEvent");
    ce.initCustomEvent(m?(
    max(dx=abs(cx=ex-sx),dy=abs(cy=ey-sy))>th?
    dx>dy?cx<0?'swl':'swr':cy<0?'swu':'swd':'fc'
    ):'fc',true,true,e.target);
    e.target.dispatchEvent(ce);
    m=0;
    T.classList.remove('sw');  //<- REMOVE THE CLASS
  },
  touchcancel:function(e){
    m=0
  }
 }
 for(l in f)D.addEventListener(l,f[l],false)
})(document);

现在定义css类

element.sw{
 background-color:yellow;
}

为元素上的移动设备使用正确的(HW)动画

element{
 background-color:green;
 -webkit-transition:background-color 200ms ease;
}

这是一个简单而肮脏的解决方案,它可行。保持简单。

该类仅适用于已定义的元素。 ;)

选项2

忘记上面的代码......

这是另一个&#34;表演者&#34;做一个&#34; snap&#34;动画使用&#34;弹跳&#34;。

代码有点复杂......并且使用鼠标..用触摸事件替换鼠标事件。

http://jsfiddle.net/xgkbjwxb/

并有更多数据点

http://jsfiddle.net/xgkbjwxb/1/

注意:请勿在移动设备中使用jquery或复杂的js插件。

<强>附加

由于在没有触摸界面的情况下在PC上工作确实存在问题,我添加了一些强制鼠标根据我的功能要求模拟触摸的行。

http://jsfiddle.net/agmyjwb0/

修改

这段代码应该做你想要的......

http://jsfiddle.net/xgkbjwxb/3/