2012-04-27 13 views
27

यह:आईओएस वेब ऐप्स में रबड़ बैंड को कैसे अक्षम करें?

$('body').on('touchmove', function(e) { e.preventDefault(); }); 

काम करता है, लेकिन पूरे पृष्ठ है, जो आदर्श से दूर है भर में स्क्रॉल को निष्क्रिय कर देगा।

यह: जिन पेजों पर एक स्क्रॉल क्षेत्र है पर

$('*').on('touchstart', function(e){ 
    var element = $(this).get(0); 

    if (element.scrollTop <= 0)           element.scrollTop = 1; 
    if (element.scrollTop + element.offsetHeight >= element.scrollHeight) element.scrollTop = element.scrollHeight - element.offsetHeight - 1; 
}); 

काम करता है। हालांकि जब स्क्रॉल करने के लिए कुछ भी नहीं है तो यह फिर से रबड़ बैंड दिखाएगा।

तो मेरे सवाल:

कैसे आप रबर बैंड प्रभाव निष्क्रिय कर सकते हैं और अभी भी -webkit-overflow-scrolling क्षेत्रों स्क्रॉल रहते हैं?

[अपडेट]

बेस्ट समाधान

अक्षम इस तरह के एक टैब बार या एक नेविगेशन पट्टी के रूप में सभी गैर स्क्रॉल तत्वों पर स्क्रॉल।

anElement.addEventListener('touchmove', function(event){ event.preventDefault() }; 

स्क्रॉल करने योग्य तत्वों जैसे मुख्य सामग्री जैसे स्क्रॉल हैंडलर संलग्न करें।

anElement.addEventListener('touchstart', function(event){ 
     if(this.scrollTop === 0) { 
      this.scrollTop += 1; 
     } else if(this.scrollTop + this.offsetHeight >= this.scrollHeight) { 
      this.scrollTop -= 1; 
     } 
} 
+1

मैं बिल्कुल वैसा ही सवाल है से div आप को रोकने के लिए चाहते हैं के लिए एक -webkit-overflow-scrolling: auto; जोड़ने! –

+0

मैं भी इसका उत्तर ढूंढ रहा हूं। डेस्कटॉप सफारी पर यह 'बॉडी {ओवरफ्लो: छुपा हुआ सेट करने में मदद करता है; ऊंचाई: 100%;} 'लेकिन यह आईओएस पर काम नहीं करता है। – Pascal

+1

जिज्ञासा से बाहर, आप इसे क्यों अक्षम करना चाहते हैं? – Fresheyeball

उत्तर

8

दुर्भाग्य से वहाँ एक 'जादुई गोली' रबर बैंड के रूप में इस के लिए ठीक मोबाइल सफारी पर स्क्रॉल इनबिल्ट ब्राउज़र के ही 'विशेषता है नहीं है। ब्राउज़र द्वारा प्रदान की गई किसी भी डिफ़ॉल्ट स्क्रॉलिंग तंत्र का उपयोग करके, आप कुछ डिग्री तक रबड़-बैंड स्क्रॉलिंग के साथ समाप्त हो जाएंगे।

दो तरीके मैं इस से निपटने के लिए सुझाव है कि कर रहे हैं:

विधि 1

</body> तत्व पर touchmove घटना से आबद्ध करें और touchmove घटना का लक्ष्य तो देखें कि क्या आप यह चाहते को देखने के लिए या आग नहीं करने के लिए इतना चाहते:

एचटीएमएल

<div class="scroll"> 
    <p>...</p> 
    <p>...</p> 
</div> 

जे एस

$('body').on('touchmove', function(e) { 
    // this is the node the touchmove event fired on 
    // in this example it would be the </p> element 
    target = e.target; 

    // we need to find the parent container 
    // we get it like so; assumes div as parent 
    parent = $(e.target).closest('div'); 

    // check if the parent is a scroll window by class // 
    if ($(parent).hasClass('scroll')){ 
     // ignore as we want the scroll to happen 
    } else { 
     e.preventDefault(); 
    } 
}); 

JSFiddle Example Here

इस विधि ब्राउज़र की डिफ़ॉल्ट स्क्रॉल का उपयोग करता है, लेकिन यह दोष यह है आप अभी भी रबर बैंड स्क्रॉल करना होगा कि है जब शीर्ष या स्क्रॉल के तल पर </div>

विधि 2

</body> तत्व की touchmove घटना से आबद्ध होने से पहले के रूप में है, लेकिन इस मामले में हम सभीtouchmove घटनाओं को रोकने और, स्क्रॉल संभाल इसलिए की तरह करने के लिए उत्कृष्ट iScroll 4 प्लगइन पर भरोसा करते हैं:

एचटीएमएल

<div id="wrapper"> 
    <div id="scroller"> 
     <p>...</p> 
     <p>...</p> 
    </div> 
</div> 

जे एस

$(document).ready(function(){ 
    // prevent all scroll // 
    $('body').on('touchmove', function(e) { 
     e.preventDefault(); 
    }); 

    // apply iscroll to scrolling element 
    // requires use of id 
    var newscroll = new iScroll('wrapper'); 
});​​ 

JSFiddle Example Here

यह मेरा पसंदीदा तरीका सभी रबर बैंड स्क्रॉल और एक अच्छा स्क्रॉल क्षेत्र प्रदान करता है यह ब्लॉक के रूप है, लेकिन यह एक प्लगइन के उपयोग पर निर्भर करता है।

मुझे आशा है कि इस मदद करता है

+0

धन्यवाद, समाधान 1 इस मुद्दे से संबंधित हमारी समस्या के लिए काम किया! – dansv130

+0

लक्ष्य = e.target का उपयोग नहीं किया जा रहा है। –

30

एक एसपीए जहां <body> रबर बैंडिंग अनुभव से विकर्षित गया था के साथ हाल ही में एक ही मुद्दे में Ran, लेकिन मैं उप-क्षेत्रों में स्क्रॉल की जरूरत है। डीक्वार्ड के सुझावों के लिए बहुत धन्यवाद, क्योंकि विधि 1 ने मेरे लिए सबसे अच्छा काम किया है।

// Prevent rubber-banding of the body, but allow for scrolling elements 
$('body').on('touchmove', function (e) { 
    var searchTerms = '.scroll, .scroll-y, .scroll-x', 
     $target = $(e.target), 
     parents = $target.parents(searchTerms); 

    if (parents.length || $target.hasClass(searchTerms)) { 
     // ignore as we want the scroll to happen 
     // (This is where we may need to check if at limit) 
    } else { 
     e.preventDefault(); 
    } 
}); 

और: यहाँ उनके सुझाव है कि मैं काम के लिए एक परियोजना में लागू की मेरी छोटी विस्तार है कि किसी भी तत्व (न केवल divs) उस पर एक .scroll वर्ग है कि खोजने के लिए सभी तरह से पेड़ पर दिखता है

body { 
    height: 100%; 
    overflow: hidden; 
} 
.scroll, .scroll-y, .scroll-x { 
    -webkit-overflow-scrolling: touch; 
} 
.scroll > *, .scroll-y > *, .scroll-x > * { 
    -webkit-transform : translateZ(0); 
} 
.scroll { overflow: auto; } 
.scroll-y { overflow-y: auto; } 
.scroll-x { overflow-x: auto; } 

आप केवल एक पुस्तकालय (jQuery या Zepto) की जरूरत है और आप गति और शरीर पर कोई रबर बैंडिंग के साथ देशी स्क्रॉल मिलती है: यहाँ की तरह क्या सीएसएस दिखता है। साथ ही, मैंने स्क्रॉलिंग के दौरान गायब होने वाले तत्वों के साथ कुछ मुद्दों को ठीक करने के लिए translateZ जोड़ा है और इसका उपयोग GPU accelerate your elements पर किया जा सकता है।

लेकिन (और यह एक बड़ा है लेकिन), जैसा कि डीक्वार्ड पॉइंट आउट होता है, पूरे पृष्ठ रबड़ बैंड जब स्क्रॉल तत्व इसकी सीमा पर होता है और आगे स्क्रॉल करने का प्रयास करता है। निजी तौर पर, मैं इसे एक विफलता मानता हूं इसलिए मैं इस पर काम करना जारी रखता हूं, बस इसे समझने की कोशिश करने में पिच करना चाहता था। ओपी के कोड की लाइनों के साथ एक चेक जोड़ना जवाब हो सकता है, लेकिन मैंने कोशिश नहीं की है।

अद्यतन (10/7/12):

काम के बहुत सारे के बाद, मैं निम्नलिखित कोड iOS6 में पूरी तरह से काम कर मिल गया है (और कुछ में परीक्षण नहीं किया)। शरीर पर कोई रबड़-बैंडिंग नहीं, स्क्रॉल क्षेत्र की सीमा पर कोई और समस्या नहीं है, और इसमें मूल स्क्रॉलिंग प्रदर्शन है। जाहिर है यह मूल रूप से बहुत अधिक कोड है, लेकिन मुझे लगता है कि यह ओपी के लक्ष्यों के निकट व्यवहार करेगा।

(function registerScrolling($) { 
    var prevTouchPosition = {}, 
     scrollYClass = 'scroll-y', 
     scrollXClass = 'scroll-x', 
     searchTerms = '.' + scrollYClass + ', .' + scrollXClass; 

    $('body').on('touchstart', function (e) { 
     var $scroll = $(e.target).closest(searchTerms), 
      targetTouch = e.originalEvent.targetTouches[0]; 

     // Store previous touch position if within a scroll element 
     prevTouchPosition = $scroll.length ? { x: targetTouch.pageX, y: targetTouch.pageY } : {}; 
    }); 

$('body').on('touchmove', function (e) { 
    var $scroll = $(e.target).closest(searchTerms), 
     targetTouch = e.originalEvent.targetTouches[0]; 

    if (prevTouchPosition && $scroll.length) { 
     // Set move helper and update previous touch position 
     var move = { 
      x: targetTouch.pageX - prevTouchPosition.x, 
      y: targetTouch.pageY - prevTouchPosition.y 
     }; 
     prevTouchPosition = { x: targetTouch.pageX, y: targetTouch.pageY }; 

     // Check for scroll-y or scroll-x classes 
     if ($scroll.hasClass(scrollYClass)) { 
      var scrollHeight = $scroll[0].scrollHeight, 
       outerHeight = $scroll.outerHeight(), 

       atUpperLimit = ($scroll.scrollTop() === 0), 
       atLowerLimit = (scrollHeight - $scroll.scrollTop() === outerHeight); 

      if (scrollHeight > outerHeight) { 
       // If at either limit move 1px away to allow normal scroll behavior on future moves, 
       // but stop propagation on this move to remove limit behavior bubbling up to body 
       if (move.y > 0 && atUpperLimit) { 
        $scroll.scrollTop(1); 
        e.stopPropagation(); 
       } else if (move.y < 0 && atLowerLimit) { 
        $scroll.scrollTop($scroll.scrollTop() - 1); 
        e.stopPropagation(); 
       } 

       // If only moving right or left, prevent bad scroll. 
       if(Math.abs(move.x) > 0 && Math.abs(move.y) < 3){ 
        e.preventDefault() 
       } 

       // Normal scrolling behavior passes through 
      } else { 
       // No scrolling/adjustment when there is nothing to scroll 
       e.preventDefault(); 
      } 
     } else if ($scroll.hasClass(scrollXClass)) { 
      var scrollWidth = $scroll[0].scrollWidth, 
       outerWidth = $scroll.outerWidth(), 

       atLeftLimit = $scroll.scrollLeft() === 0, 
       atRightLimit = scrollWidth - $scroll.scrollLeft() === outerWidth; 

      if (scrollWidth > outerWidth) { 
       if (move.x > 0 && atLeftLimit) { 
        $scroll.scrollLeft(1); 
        e.stopPropagation(); 
       } else if (move.x < 0 && atRightLimit) { 
        $scroll.scrollLeft($scroll.scrollLeft() - 1); 
        e.stopPropagation(); 
       } 
       // If only moving up or down, prevent bad scroll. 
       if(Math.abs(move.y) > 0 && Math.abs(move.x) < 3){ 
        e.preventDefault(); 
       } 

       // Normal scrolling behavior passes through 
      } else { 
       // No scrolling/adjustment when there is nothing to scroll 
       e.preventDefault(); 
      } 
     } 
    } else { 
     // Prevent scrolling on non-scrolling elements 
     e.preventDefault(); 
    } 
}); 
})(jQuery); 
+1

मैंने शायद इस समस्या पर लगभग दो महीने बिताए लेकिन एक पूरी तरह से खराब मार्ग चला गया। YTMND। – RandallB

+0

रुको! मैंने बहुत जल्द बात की। यदि आप स्क्रॉल-एक्स तत्व पर अपनी उंगली को ऊपर खींचने का प्रयास करते हैं, तो यह अभी भी रबरबैंड दुखी होगा। :( – RandallB

+0

एक संपादन सबमिट करें। इसे आज़माने के लिए स्वतंत्र महसूस करें। – RandallB

1

मैंने अपनी राय में, इस समस्या के लिए सबसे अच्छा समाधान लिखा था। यह सामान्य रूप से स्क्रॉलिंग को अक्षम कर देगा जब तक कि तत्व में वाई स्क्रॉलिंग न हो।

/******************************************************************************** 
* Disable rubber band (c)2013 - Mark van Wijnen | www.CrystalMinds.nl 
********************************************************************************/ 
$(function(){ 
    var scrollY = 0; 

    $(document).on('touchstart', function(e){ 
     scrollY = e.originalEvent.touches.item(0).clientY; 
    }); 

    $(document).on('touchmove', function(e){ 
     var scrollPos  = e.target.scrollTop; 
     var scrollDelta  = scrollY - e.originalEvent.touches.item(0).clientY; 
     var scrollBottom = scrollPos + $(e.target).height(); 
     scrollY    = e.originalEvent.touches.item(0).clientY; 

     if ($(e.target).css('overflow-y') != 'scroll' || (scrollDelta < 0 && scrollPos == 0) || (scrollDelta > 0 && scrollBottom == e.target.scrollHeight)) 
      e.preventDefault(); 
    }); 
}); 
+0

hi @mark, यदि आप एक आईफोन वेब ऐप के लिए एचटीएमएल 5 परामर्श में रुचि रखते हैं, तो क्या आप पैनाबी डॉट कॉम पर ईमेलिंग जानकारी को ध्यान में रखेंगे? धन्यवाद! एक सुझाव: कुछ "स्क्रॉल" के बजाय मान के रूप में "ऑटो" निर्दिष्ट कर सकते हैं। – Crashalot

+0

क्या टचमोव में स्क्रॉलवाई को अपडेट करना आवश्यक है? सिर्फ मूल टैप के मुकाबले तुलना करना दिशा निर्देश देना चाहिए, है ना? – Crashalot

+0

यह कुछ समय हो गया है क्योंकि मैंने कोड लिखा था, लेकिन मुझे लगता है कि मैं scrollDelta प्रॉपर्टी के लिए स्क्रॉल वाई अपडेट कर रहा हूं। जब आप स्क्रॉल करने योग्य क्षेत्र में स्क्रॉल करते हैं, जबकि आप पहले से ही शीर्ष पर होते हैं तो बाउंसिंग भी होती है, और इससे यह रोकता है। – Mark

1

@ मार्क के उत्तर के आधार पर, हम इस विकल्प के साथ आए, जो काम करता है। स्क्रॉल करने योग्य वस्तुओं के वर्ग नामों के साथ .page_list को बदलें।

var INITIAL_Y = 0; // Tracks initial Y position, needed to kill Safari bounce effect 

function kill_safari_bounce() { 
    $(document).on('touchstart', function(e){ 
     INITIAL_Y = e.originalEvent.touches[0].clientY; 
    }); 

    $(document).on('touchmove', function(e) { 
     // Get scrollable ancestor if one exists 
     var scrollable_ancestor = $(e.target).closest('.page_list')[0]; 

     // Nothing scrollable? Block move. 
     if (!scrollable_ancestor) { 
      e.preventDefault(); 
      return; 
     } 

     // If here, prevent move if at scrollable boundaries. 
     var scroll_delta = INITIAL_Y - e.originalEvent.touches[0].clientY; 
     var scroll_pos = scrollable_ancestor.scrollTop;   
     var at_bottom = (scroll_pos + $(scrollable_ancestor).height()) == scrollable_ancestor.scrollHeight; 

     if ((scroll_delta < 0 && scroll_pos == 0) || 
      (scroll_delta > 0 && at_bottom)){ 
      e.preventDefault(); 
     }  
    }); 
} 
+0

धन्यवाद, काम करता है (अब भी) आईओएस 7.1 में पूरी तरह से –

+0

@Crashalot आप एक काम बेला कर सकते हैं, मैं इस काम करने के लिए, मैं कुछ कमी किया जाना चाहिए नहीं मिल सकता है। धन्यवाद –

2

यहां एक समाधान है जो jQuery और हैमर.जेएस (jQuery-कार्यान्वयन) का उपयोग करता है। यह दो पुस्तकालय है, लेकिन यदि आप मोबाइल पर काम कर रहे हैं, तो संभावना है कि आप हैमर को वैसे भी शामिल करना चाहेंगे।

प्रत्येक ड्रैग-इवेंट के लिए जो शीर्ष पर बुलबुले होते हैं (इसलिए गैर-स्क्रॉलिंग ड्रैग-इंटरैक्शन स्टॉपप्रॉपैगेशन का उपयोग कर सकते हैं) हैंडलर चेक करता है कि यह क्लास = स्क्रॉलिंग के साथ किसी भी तत्व के माध्यम से बुलबुला हुआ है, यदि हां, तो क्या उपयोगकर्ता भीतर स्क्रॉल कर रहा है उस स्क्रॉलकंटर की अनुमति सीमाएं और केवल तब ही यह मूल स्क्रॉलिंग की अनुमति देती है।

$("body").hammer().on('drag swipe', function(e){ 

    var scrollTarget = $(e.gesture.target).closest(".scrollable"); 
    if(scrollTarget.length) 
    { 
     var scrollTopMax = scrollTarget[0].scrollHeight - scrollTarget.outerHeight(); 
     if(scrollTopMax > 0){ 
      var scrollTop = scrollTarget.scrollTop(); 
      if(scrollTop > 0 && scrollTop < scrollTopMax){ 
       //console.log("scrolling in the middle"); 
      } 
      else if(scrollTop <= 0 && e.gesture.deltaY < 0){ 
       //console.log("scrolling from top"); 
      } 
      else if(scrollTop >= scrollTopMax && e.gesture.deltaY > 0){ 
       //console.log("scrolling from bottom"); 
      } 
      else{ 
       //console.log("trying to scroll out of boundaries"); 
       e.gesture.preventDefault(); 
      } 
     } 
     else{ 
      //console.log("content to short to scroll"); 
      e.gesture.preventDefault(); 
     } 
    } 
    else{ 
     //console.log("no containing element with class=scrollable"); 
     e.gesture.preventDefault(); 
    } 
}); 

चुटकी आदि के माध्यम से ड्रैग को मारने के लिए; यदि आपके विचार उपयोगकर्ता के स्केलेबल

$("body").hammer().on('doubletap rotate pinch', function(e){ 
    e.gesture.preventDefault(); 
}); 

iOS7/सफारी, Android4.3/वेबव्यू और Android4.3/firefoxMobile25 और एकमात्र समाधान है कि नहीं तोड़ा पर परीक्षण किया गया है ज़ूम करने की अनुमति के रूप में आवश्यक भाग जाते हैं।

+0

इस काम को करने के लिए सीएसएस 'टच-एक्शन' पर कौन सी सेटिंग्स की आवश्यकता है? – Aides

+0

उत्तर काफी हद तक टच-एक्शन की भविष्यवाणी करता है, इसलिए ऑटो; लेकिन उम्मीद है कि अब तक बेहतर समाधान उपलब्ध हैं। – Tobl

+0

असल में समस्या अभी भी मौजूद है और समाधान अभी भी समस्याग्रस्त हैं। समस्या के कुछ गहन विश्लेषण और कुछ संक्षेप में समाधान दृष्टिकोण पर [मेरी एसओ पोस्ट] (http://stackoverflow.com/questions/37586286/prevent-overflow-rubberband-scrolling-on-ios) देखें। अंत में मेरे मामले में चाल क्या थी [iNoBounce] (https://github.com/lazd/iNoBounce)। – Aides

0

अंततः मैंने कुछ तरीकों को मिश्रित किया और ये कोड कार्य संस्करण हैं। लेकिन आप hammer.js

सीएसएस

.scrollable{ 
    overflow:auto;overflow-x:hidden;-webkit-overflow-scrolling:touch; 
    *{-webkit-transform:translate3d(0,0,0);} 
} 

JAVASCRIPT

$(document).on("touchmove",function(e){ 
    e.preventDefault(); 
}); 
$("body").on("touchstart",".scrollable",function(e){ 
    if(e.currentTarget.scrollTop===0){ 
     e.currentTarget.scrollTop = 1; 
    }else if(e.currentTarget.scrollHeight === e.currentTarget.scrollTop + e.currentTarget.offsetHeight){ 
     e.currentTarget.scrollTop-=1; 
    } 
}); 
$("body").on("touchmove",".scrollable",function(e){ 
    e.stopPropagation(); 
}); 

$("body").hammer().on("pinch",function(e){ 
    e.gesture.preventDefault(); 
}); 
-1

शामिल करना चाहिए बस उछल

+0

चिकनी स्क्रॉलिंग के किसी भी रूप को भी मारता है। –

संबंधित मुद्दे