2009-09-06 43 views
16

Hiện tại chương trình của tôi đang ở vị trí mà cả hai đều lắng nghe người dùng cuộn một phần tử nhất định, đồng thời, tự động cuộn phần tử này. (Không phải là một chuyển động dần dần, đẹp mà là một bước nhảy liền. Nó có ý nghĩa trong ngữ cảnh, tôi thề.)Thực hiện các thay đổi "scrollLeft"/"scrollTop" không kích hoạt trình xử lý sự kiện cuộn

Có cách nào để sự kiện cuộn không kích hoạt nếu việc cuộn được thực hiện bằng cách thiết lập scrollLeft hoặc scrollTop? Ý tưởng đầu tiên của tôi là một chuyển đổi cơ bản, như:

ignoreScrollEvents = true; 
element.scrollLeft = x; 
ignoreScrollEvents = false; 

function onScroll() { 
    if(ignoreScrollEvents) return false; 
} 

nhưng vì các sự kiện không kích hoạt ngay lập tức (oops, duhh), đó không phải là giải pháp khả thi. Tôi có thể thử loại câu trả lời nào khác? Tôi cũng đang sử dụng jQuery, nếu điều đó giúp ích gì.

Trả lời

17

phương pháp chung chung dễ nhất ? Chỉ cần đặt lại cờ trong trình xử lý sự kiện. Trước tiên, bạn sẽ muốn kiểm tra xem liệu bạn có thực sự thay đổi giá trị hay không, vì nếu không một sự kiện sẽ không được kích hoạt - như là Rodrigo notes, thực hành tốt ở đây là xác định yếu tố này thành các hàm "setter":

function setScrollLeft(x) 
{ 
    if (element.scrollLeft != x) 
    { 
    ignoreScrollEvents = true; 
    element.scrollLeft = x; 
    } 
} 

... 

function onScroll() 
{ 
    var ignore = ignoreScrollEvents; 
    ignoreScrollEvents = false; 

    if (ignore) return false; 

    ... 
} 

Nhưng, tùy theo nhu cầu của bạn, bạn có thể đã lưu trữ vị trí cuộn ở đâu đó; nếu có, chỉ cần cập nhật và kiểm tra xem đó là cờ của bạn. Một cái gì đó như:

element.scrollLeft = currentScrollLeft = x; 

... 

function onScroll() 
{ 
    // retrieve element, etc... 

    if (element.scrollLeft == currentScrollLeft) return false; 

    ... 
} 
+0

Trong mã của tôi, tôi nhấn một vấn đề: đôi khi nó xảy ra, ví dụ, scrollLeft đã là 0, sau đó mã của tôi cũng đặt thành 0. Vì vậy, không có sự kiện cuộn nào được kích hoạt và cuộn người dùng tiếp theo bị bỏ qua. (Mà chỉ thực sự là một vấn đề nếu họ di chuyển với Home, End, vv) Nhưng điều này chắc chắn là một giải pháp gần - và tôi biết tôi đã thiếu một cái gì đó ngu ngốc trong việc thực hiện giả. Cảm ơn! – Matchu

+0

Tôi tự hỏi về điều đó ... Đặt cược tốt nhất của bạn sau đó, là kiểm tra xem bạn có thay đổi giá trị trước khi thiết lập cờ không - không đặt nó nếu bạn không.Bạn có thể đã có mã này yếu tố ra thành một chức năng riêng biệt, nhưng nếu không, sau đó làm như vậy sẽ làm cho dễ dàng hơn - xem câu trả lời của Rodrigo cho một ví dụ về điều này. – Shog9

1

Bạn có thể constantly check nếu scroll position thay đổi ...

+0

Đó không phải là một giải pháp khá, nhưng nếu bạn đang nói rằng các sự kiện không kích hoạt ngay lập tức ... – marcgg

+0

Khi tôi nói sự kiện không kích hoạt ngay lập tức, tôi có nghĩa là nói chung. Nếu tôi chạy 3 dòng đầu tiên đó, tất cả đều đến và đi vào thời điểm sự kiện cuộn được kích hoạt, vì đó chỉ là cách Javascript hoạt động. – Matchu

+0

Giải pháp này đẹp hơn giải pháp được chấp nhận, tôi nghĩ vậy. Giải pháp được chấp nhận muốn bạn tạo một biến toàn cục và sẽ phá vỡ ngay khi bạn muốn hai trình xử lý 'onScroll'. Tuy nhiên, giải pháp này không cung cấp một UX linh hoạt, vì vậy nó thực sự là những tảng đá và những nơi khó khăn xung quanh. – jcarpenter2

0

Bạn có thể thử lưu trữ đầu bù đắp các yếu tố của bạn và phù hợp với nó chống lại scrollTop khi bạn bước bên OnScroll:

function onScroll(){ 
    var scrollTop = (document.documentElement.scrollTop || document.body.scrollTop), 
    offsetTop = $('selector').offset().top; 
    if(offsetTop > scrollTop){ 
     //user has not scrolled to element so do auto scrolling 
    } 
} 
2

Làm thế nào về một setter?

var _preventEvent = false; // set global flag 
 

 
function setScrollTop(amount) { 
 
    _preventEvent = true; // set flag 
 
    document.documentElement.scrollTop = amount * Math.random(); 
 
} 
 

 
function setScrollLeft(amount) { 
 
    _preventEvent = true; // set flag 
 
    document.documentElement.scrollLeft = amount * Math.random(); 
 
} 
 

 
// scroll event listener 
 
window.onscroll = function() { 
 
    console.clear(); 
 
    
 
    if (_preventEvent) { 
 
    _preventEvent = false; // reset flag 
 
    return; 
 
    } 
 
    
 
    console.log('normal scroll'); 
 
}
html{ height:500%; width:500%; } 
 
button{ position:fixed; } 
 
button + button{ top:50px; }
<button onclick=setScrollTop(1000)>Random scrollTop</button> 
 
<button onclick=setScrollLeft(1000)>Random scrollLeft</button>

0

Được rồi, giải pháp cuối cùng của tôi, xây dựng tắt của Shog9 (không mã thực của tôi, nhưng cách tiếp cận của tôi):

var oldScrollLeft = element.scrollLeft; 
element.scrollLeft = x; 
if(element.scrollLeft != oldScrollLeft) { 
    ignoreScrollEvents = true; 
} 

function onScroll() { 
    if(!ignoreScrollEvents) performGreatActions(); 
    ignoreScrollEvents = false; 
} 

Các câu lệnh if chỉ đặt lờ cờ khi giá trị scrollLeft thực sự kết thúc thay đổi, vì vậy các trường hợp như cài đặt từ 0 đến 0 không đặt cờ không chính xác.

Cảm ơn, tất cả!

+0

để câu trả lời đúng là? – Rodrigo

+0

Không chắc chắn. Giao thức ở đây là gì? Nếu tôi sử dụng một phần của câu trả lời thì hãy xây dựng nó để đạt được câu trả lời đầy đủ, tôi có đánh dấu câu trả lời của tôi hay câu trả lời khác không? – Matchu

+0

Câu trả lời được chấp nhận đã được chỉnh sửa để bao gồm cảnh báo này, vì vậy nó bây giờ phù hợp với câu trả lời này :) Cool! – Matchu

Các vấn đề liên quan