peachananr / onepage-scroll

Create an Apple-like one page scroller website (iPhone 5S website) with One Page Scroll plugin
http://peachananr.github.io/onepage-scroll/Demo/demo.html
9.54k stars 2.07k forks source link

Scrolling on touch devices #96

Open Anselmv opened 10 years ago

Anselmv commented 10 years ago

There seems to be a problem when using the plugin on ipad. It scrolls multiple sections at a time. Well i think i might have found the source of this problem.

This code:

el.swipeEvents().bind("swipeDown",  function(event){ 
  if (!$("body").hasClass("disabled-onepage-scroll") && !$("body").hasClass("scrolling")){ event.preventDefault();
  el.moveUp();}
}).bind("swipeUp", function(event){ 
  if (!$("body").hasClass("disabled-onepage-scroll")&& !$("body").hasClass("scrolling")){ event.preventDefault();

  el.moveDown(); }
});

is written twice. So when swiping it gets executed multiple times.

once in this function: function init_scroll ()

and once in this function: function responsive()

removing the code from function responsive() solves the problem.

this is my first bug report/ fix on git so if something is not clear please tell me ;-)

apsolut commented 10 years ago

i noticed it on project, skiping of pages after @PWesterdale fix for toush, bottom of page #81 , and after reading your post its working now, dont have nice scroll from page to page on ios7 but all pages are working..

also i noticed this is in codes, but it look like on demo page all is working: http://www.thepetedesign.com/demos/onepage_scroll_demo.html

Anselmv commented 10 years ago

hey apsolut,

for that nice scrolling effect on ios 7 try replacing the function function touchstart(event) { }

function touchstart(event) { $this.unbind('touchmove', touchmove); var touches = event.originalEvent.touches; var touchedObject = touches[0].target; if (touchedObject.nodeName=='A' || touchedObject.nodeName == 'LABEL' || touchedObject.nodeName == 'SPAN'){ $(touchedObject).click(); return 1; } if(!( typeof($._data(touchedObject, "events")) !== 'undefined' && $._data(touchedObject, "events").click != null || touchedObject.nodeName == 'A' || touchedObject.nodeName == 'LABEL' || touchedObject.nodeName == 'SPAN' )){ startX = touches[0].pageX; startY = touches[0].pageY; $this.bind('touchmove', touchmove); } event.preventDefault(); }

apsolut commented 10 years ago

damn how i love you now. :+1: i need to whitelist more a elements but scroll is working awesome man... need to whitelist

<div class> <li class> <a href="#"> </div></li></a> 

its strange, i can click on slider next,prev, buttons in navigation, but cant fire click with jq on li a inside class...

PWesterdale commented 10 years ago

Good work guys, I actually ended up porting hammer.js into my scroller to make the slider events smoother and more responsive across other devices.

Anselmv commented 10 years ago

hammer.js seems to be a more robust solution then the currently implemented swipe events.

I have detected one more problem withe the code i posted here yesterday. it breaks on mobile when you use the mobile fallback.

Problem is event.preventDefault(); in function touchstart(event) {} we don't need to execute this when using the mobile fallback.

this fixes it

function touchstart(event) {

  var touches = event.originalEvent.touches;
  var touchedObject = touches[0].target;
  if (touchedObject.nodeName=='A' || touchedObject.nodeName == 'LABEL' || touchedObject.nodeName == 'SPAN'){
      $(touchedObject).click();
      return 1;
  }
  if(!(
        typeof($._data(touchedObject, "events")) !== 'undefined' 
        && $._data(touchedObject, "events").click != null
        || touchedObject.nodeName == 'A' || touchedObject.nodeName == 'LABEL' || touchedObject.nodeName == 'SPAN'
    )){
    startX = touches[0].pageX;
    startY = touches[0].pageY;
    $this.bind('touchmove', touchmove);
  }
   if(!$("body").hasClass("disabled-onepage-scroll")) {
  event.preventDefault();
  }
}

Great improvements so far, how do we get these to be revised/implemented ;-)

apsolut commented 10 years ago

still searching, but : if(!$("body").hasClass("disabled-onepage-scroll")) { event.preventDefault(); } get fired on ipad, and i can scroll nicely but cant fire anything inside

, even alert, if i remove or try to add IF statemen to stop it on A.. , then i have bad page transition page by page... on desktop and android all fine.. just ipad.. also if i use default jquery.onepage-scroll.js i can fire click and all is working, but bad scroll situation on ipad - page by page..

Svecc commented 10 years ago

Hi guys!

I’d like to fix this problem in my own project as well, but I’m more like a designer kind a guy, so unfortunately I don’t know what are you talking about exactly. :( If you have a working demo, could you be so kind and send it to me? schv3ts@yahoo.com

Thank you in advance!

apsolut commented 10 years ago

@PWesterdale I included hammer for jquery also using default jquery.onepage-scroll.js, in footer added document.ontouchstart = function(e){ if(e.target.nodeName != 'A' && e.target.nodeName != 'LI'){ e.preventDefault(); e.stopImmediatePropagation(); }} all jquery .click functions to on.click touch, $('#allusers li a').on("click touchstart", function(event){ alert("Your book is overdue."); }); and it look like all is working, i can fire click , and i have normal scroll on ipad and android... tested android 3>, ipad ios7, gallaxy s3...

@Anselmv @Svecc

PWesterdale commented 10 years ago

Spot on Apsolut - I think its the best way and it seems to solve a lot of the issues, I would share my code but I have really altered it and have included another plugin to handle horizontal sliding. It is on my list to re-write something like this, but in the mean time I may go over it again and make some pull requests.

simonwebdesign commented 10 years ago

What's the status on these fixes? Thanks!

apsolut commented 10 years ago

not shure about updates on onepage-scroll, but with hammer.js all working nice and smooth.. for ipad i removed document.ontouchstart...

lezwon commented 10 years ago

can anyone please upload the fixed js file. im having a lot of trouble fixing the touch scroll issue. my site : colossus.pixub.com

atomicreach commented 10 years ago

how do you implement hammer.js to fix this issue?

atomicreach commented 10 years ago

@apsolut hey man, can you give little bit more detailed instruction on how to fix this issue. Thanks

apsolut commented 10 years ago

not shure did i edit onepagescroll.js but just include onepagescroll.js and after that include hammer js: http://pastebin.com/wv0bzQ7T

and for click events use: $('#divID').on("click touchstart", function(event){ }

see also: https://github.com/peachananr/onepage-scroll/issues/81

flatcapco commented 10 years ago

@apsolut sorry to drag up an old thread - your pastebin is dead and I'm struggling with getting this playing well on ipad retina. Please can you share your advice again. Thanks

apsolut commented 10 years ago

@latwelve i updated pastebin - its just hammer for jquery. try it, if its not working i will try to remember all the steps :) because in the end i disabled that on ipad so user can see bottom of next page (client wish) dont ask :+1:

flatcapco commented 10 years ago

Thanks @apsolut I've got it working without using hammer.js so far but the only issue I see is that when going from slider to resp mode to slider the slide jesture stops working (all the buttons are fine binded as they are) - http://la12.co.uk/dev/test/

$('button.nextslide').on("click touchstart", function(event){ $(".main").moveDown(); }); $('button.top').on("click touchstart", function(event){ $(".main").moveTo(1); });

Do you think it's worth trying to make my version without hammer.js work or should I use hammer to over come this?

At the limit of my jquery depth :)

*edit I think now only the elements on the page are allowing the slide changing and not the full screen such as the background when dragged leaves you on the same slide.

apsolut commented 10 years ago

@latwelve can you just include hammer.js for jquery (you can copy-paste) from that pastebin i posted.. and next and prev click will work for you...

flatcapco commented 10 years ago

I tried that - sorry I should have mentioned - it didn't make any difference though as the clicks already work - it's just the slide gestures that get confused after going from normal to resp to normal it forgets how to slide. - And as mentioned it seems to only slide over the elements not the whole screen

apsolut commented 10 years ago

can you try to use easing: "linear", other dev is using ipad so i cant now, but on dekstop Chrome,Safari - resizing is working... So your problem is Portrait - Landscape ortientation rite ? you can maybe reintalize onepagescroll with resize()

and check this one: #109

yourownmood commented 9 years ago

After having the same issue's scrolling multiple pages (firing the swipe-event multiple times) I found the creator of the swipeEvents function who have made a update availbke which prevents duplicate event firing ;) https://github.com/eikes/jquery.swipe-events.js/blob/master/js/jquery.swipe-events.js

My swipeEvents function now looks like:

$.fn.swipeEvents = function() {
    return this.each(function() {

      var startX,
          startY,
          $this = $(this);

      $this.bind('touchstart', touchstart);

      function touchstart(event) {
        var touches = event.originalEvent.touches;
        if (touches && touches.length) {
          startX = touches[0].pageX;
          startY = touches[0].pageY;
          $this.bind('touchmove', touchmove);
          $this.bind('touchend', touchend);
        }
        event.preventDefault();
      }

      function touchmove(event) {
        var touches = event.originalEvent.touches;
        if (touches && touches.length) {
          var deltaX = startX - touches[0].pageX;
          var deltaY = startY - touches[0].pageY;

          if (deltaX >= 50) {
            $this.trigger("swipeLeft");
          }
          if (deltaX <= -50) {
            $this.trigger("swipeRight");
          }
          if (deltaY >= 50) {
            $this.trigger("swipeUp");
          }
          if (deltaY <= -50) {
            $this.trigger("swipeDown");
          }
          if (Math.abs(deltaX) >= 50 || Math.abs(deltaY) >= 50) {
            $this.unbind('touchmove', touchmove);
            $this.unbind('touchend', touchend);
          }
        }
        event.preventDefault();
      }

      function touchend(event) {
        $this.unbind('touchmove', touchmove);
        event.preventDefault();
      }

    });
  };
devmaaa commented 5 years ago

not shure did i edit onepagescroll.js but just include onepagescroll.js and after that include hammer js: http://pastebin.com/wv0bzQ7T

and for click events use: $('#divID').on("click touchstart", function(event){ }

see also:

81

i hade this problem can enebody help me still not working i include https://cdn.jsdelivr.net/npm/jquery-hammerjs@2.0.0/jquery.hammer.min.js but in iphones same problem in scroll

ezgif com-video-to-gif

devmaaa commented 5 years ago

Hahaaaaaaaaaaaaa Guuuuuuuuuuys I SOLVE THEMMMM this is 100 % working on iphones and ipads , this is the working code without hummer.js yourownmood your code is working but you have bugs , on page when user clicks on tags , such a , input or button its now wokring so this is working code for tags , a , span , button, textarea, input if you want you can add your tag in touchedObject.nodeName = "Your Tag" so This is working code


$.fn.swipeEvents = function() { return this.each(function() {

        var startX,
            startY,
            $this = $(this);

        $this.bind('touchstart', touchstart);
        function touchstart(event) {

            var touches = event.originalEvent.touches;
            var touchedObject = touches[0].target;
            if (touchedObject.nodeName=='A' ||
             touchedObject.nodeName == 'LABEL' || 
             touchedObject.nodeName == 'SPAN' || 
             touchedObject.nodeName == 'INPUT' ||
             touchedObject.nodeName == 'TEXTAREA' || 
             touchedObject.nodeName == 'BUTTON' 

             ){
                $(touchedObject).click();
                return 1;
            }
            if(!(
                  typeof($._data(touchedObject, "events")) !== 'undefined' 
                  && $._data(touchedObject, "events").click != null
                  || touchedObject.nodeName == 'A' || 
                  touchedObject.nodeName == 'LABEL' || 
                  touchedObject.nodeName == 'SPAN' || 
                  touchedObject.nodeName == 'INPUT' || 
                  touchedObject.nodeName == 'TEXTAREA' ||
                  touchedObject.nodeName == 'BUTTON'
              )){
              startX = touches[0].pageX;
              startY = touches[0].pageY;
              $this.bind('touchmove', touchmove);
            }
             if(!$("body").hasClass("disabled-onepage-scroll")) {
                event.preventDefault();
            }
          }

          function touchmove(event) {
            var touches = event.originalEvent.touches;
            if (touches && touches.length) {
              var deltaX = startX - touches[0].pageX;
              var deltaY = startY - touches[0].pageY;
              event.preventDefault();
              if (deltaX >= 50) {
                $this.trigger("swipeLeft");
              }
              if (deltaX <= -50) {
                $this.trigger("swipeRight");
              }
              if (deltaY >= 50) {
                $this.trigger("swipeUp");
              }
              if (deltaY <= -50) {
                $this.trigger("swipeDown");
              }
              if (Math.abs(deltaX) >= 50 || Math.abs(deltaY) >= 50) {
                $this.unbind('touchmove', touchmove);
              }
            }
          }

        function touchend(event) {
         $this.unbind('touchmove', touchmove);
         event.preventDefault();
      }

    });
};

Also i Delete This Code on function responsive() el.swipeEvents().bind("swipeDown", function(event){ if (!$("body").hasClass("disabled-onepage-scroll") && !$("body").hasClass("scrolling")){ event.preventDefault(); el.moveUp();} }).bind("swipeUp", function(event){ if (!$("body").hasClass("disabled-onepage-scroll")&& !$("body").hasClass("scrolling")){ event.preventDefault();

el.moveDown(); } });

You can see the Result on Iphone 8 Elements is clicable and also good touch event without white lines ezgif com-crop