Làm cách nào để có được một phần tử để cuộn vào xem, sử dụng jQuery?


169

Tôi có một tài liệu HTML với hình ảnh ở định dạng lưới bằng cách sử dụng <ul><li><img.... Cửa sổ trình duyệt có cả cuộn dọc và cuộn ngang.

Câu hỏi: Khi tôi nhấp vào một hình ảnh <img>, làm thế nào để tôi có được toàn bộ tài liệu để cuộn đến một vị trí mà hình ảnh tôi vừa nhấp vào là top:20px; left:20px?

Tôi đã có một trình duyệt trên đây cho các bài đăng tương tự ... mặc dù tôi còn khá mới với JavaScript và muốn hiểu cách thức đạt được điều này cho bản thân mình.


Câu trả lời:


192

Vì bạn muốn biết nó hoạt động như thế nào, tôi sẽ giải thích từng bước một.

Trước tiên, bạn muốn liên kết một chức năng như trình xử lý nhấp chuột của hình ảnh:

$('#someImage').click(function () {
    // Code to do scrolling happens here
});

Điều đó sẽ áp dụng trình xử lý nhấp chuột cho một hình ảnh với id="someImage". Nếu bạn muốn làm điều này với tất cả các hình ảnh, thay thế '#someImage'bằng 'img'.

Bây giờ cho mã cuộn thực tế:

  1. Lấy phần bù hình ảnh (liên quan đến tài liệu):

    var offset = $(this).offset(); // Contains .top and .left
  2. Trừ 20 từ topleft:

    offset.left -= 20;
    offset.top -= 20;
  3. Bây giờ làm động các thuộc tính CSS cuộn trên và cuộn sang trái của <body><html>:

    $('html, body').animate({
        scrollTop: offset.top,
        scrollLeft: offset.left
    });

3
Điều này chỉ hoạt động cho bố trí đơn giản. Nó không xử lý tất cả các trường hợp theo cách mà .scrollIntoViewphương thức W3C thực hiện khi các phần tử được lồng trong nhiều thùng chứa tràn.
natevw

2
Tại sao phải phát minh lại bánh xe? Element.scrollIntoView(): developer.mozilla.org/en-US/docs/Web/API/Euity/scrollIntoView
Serge

@Serge vì đó là một bản nháp hoạt động chưa được triển khai trong tất cả các trình duyệt
John Smith

@JohnSmith vui lòng đọc chăm chú liên kết tôi đã đăng, phần "Tương thích trình duyệt", bạn sẽ thấy không có trình duyệt nào không hỗ trợscrollIntoView
Serge

@Serge Xin lỗi về điều đó, tôi đã không nhận ra, đó cũng là scrollIntoViewOption (một thứ không được hỗ trợ đủ rộng). Tôi đoán nó đủ tốt.
John Smith

377

Có một phương thức DOM được gọi scrollIntoView, được hỗ trợ bởi tất cả các trình duyệt chính, sẽ căn chỉnh một phần tử với đỉnh / bên trái của chế độ xem (hoặc càng gần càng tốt).

$("#myImage")[0].scrollIntoView();

Trên các trình duyệt được hỗ trợ, bạn có thể cung cấp các tùy chọn:

$("#myImage")[0].scrollIntoView({
    behavior: "smooth", // or "auto" or "instant"
    block: "start" // or "end"
});

Ngoài ra, nếu tất cả các thành phần có ID duy nhất, bạn chỉ có thể thay đổi thuộc hashtính của locationđối tượng để hỗ trợ nút quay lại / chuyển tiếp:

$(document).delegate("img", function (e) {
    if (e.target.id)
        window.location.hash = e.target.id;
});

Sau đó, chỉ cần điều chỉnh scrollTop/ scrollLeftthuộc tính theo -20:

document.body.scrollLeft -= 20;
document.body.scrollTop -= 20;

2
Cảm ơn bạn! 5 bài viết SO khác và bạn đóng đinh nó hoàn hảo. Trường hợp sử dụng của tôi là một thùng chứa trong hộp thoại bootstrap cần cuộn vào xem.
Stephen Patten

10
Như một lưu ý: $("#myImage")[0].scrollIntoView(false);sẽ căn chỉnh phần tử ở dưới cùng của cửa sổ.
Philipp

1
Coi chừng: hành vi "trơn tru" không được hỗ trợ rộng rãi và scrollIntoViewcó thể là một trải nghiệm khó hiểu cho người dùng mà không có một số loại hoạt hình.
Cody Duval

1
@JohnHenckel: điều đó không chính xác, ngay cả IE 5.5 cũng scrollIntoViewcó tham số boolean. Tôi sẽ thử và gửi yêu cầu kéo cho caniuse.com sau.
Andy E

1
Lưu ý: Sử dụng Chrome, tôi không thể cuộn <td>các yếu tố vào chế độ xem, thay vào đó phải cuộn cha mẹ của chúng ( <tr>) và nó hoạt động.
CrazyTim

13

Giải pháp đơn giản nhất tôi đã thấy

var offset = $("#target-element").offset();
$('html, body').animate({
    scrollTop: offset.top,
    scrollLeft: offset.left
}, 1000);

Hướng dẫn tại đây


Có nguy cơ làm cho nó ít đơn giản hơn, tôi cũng chỉnh sửa nó để hỗ trợ cuộn ngang.
jpaugh

7

Có các phương pháp để cuộn phần tử trực tiếp vào dạng xem, nhưng nếu bạn muốn cuộn đến một điểm tương đối từ một phần tử, bạn phải thực hiện thủ công:

Trong trình xử lý nhấp chuột, lấy vị trí của phần tử so với tài liệu, trừ 20và sử dụng window.scrollTo:

var pos = $(this).offset();
var top = pos.top - 20;
var left = pos.left - 20;
window.scrollTo((left < 0 ? 0 : left), (top < 0 ? 0 : top));

7

Hãy xem plugin jQuery.scrollTo . Đây là một bản demo .

Plugin này có rất nhiều tùy chọn vượt xa những gì scrollIntoView bản địa cung cấp cho bạn. Chẳng hạn, bạn có thể thiết lập cuộn để được trơn tru, và sau đó đặt một cuộc gọi lại khi quá trình cuộn kết thúc.

Bạn cũng có thể xem tất cả các trình cắm JQuery được gắn thẻ "cuộn" .


Tôi đã nhận được các vị trí / vị trí khác nhau trong mọi trình duyệt trong trường hợp của mình và plugin này đã giúp sửa nó cho tôi! cảm ơn!
Vòng nguyệt quế

4

Đây là một plugin jQuery nhanh để ánh xạ chức năng trình duyệt tích hợp độc đáo:

$.fn.ensureVisible = function () { $(this).each(function () { $(this)[0].scrollIntoView(); }); };

...

$('.my-elements').ensureVisible();

3

Sau khi dùng thử và lỗi tôi đã đưa ra chức năng này, cũng hoạt động với iframe.

function bringElIntoView(el) {    
    var elOffset = el.offset();
    var $window = $(window);
    var windowScrollBottom = $window.scrollTop() + $window.height();
    var scrollToPos = -1;
    if (elOffset.top < $window.scrollTop()) // element is hidden in the top
        scrollToPos = elOffset.top;
    else if (elOffset.top + el.height() > windowScrollBottom) // element is hidden in the bottom
        scrollToPos = $window.scrollTop() + (elOffset.top + el.height() - windowScrollBottom);
    if (scrollToPos !== -1)
        $('html, body').animate({ scrollTop: scrollToPos });
}

2

Chỉ là một mẹo. Chỉ hoạt động trên firefox

Element.scrollIntoView ();


4
Điều này đang làm việc cho tất cả các trình duyệt có tham số boolean hoặc không có tham số nào cả. Chỉ tham số đối tượng nâng cao hơn là ít được hỗ trợ.
Risord

theo developer.mozilla.org/en-US/docs/Web/API/Euity/scrollIntoView nói chung thiếu sự hỗ trợ trình duyệt cho việc này
lfender6445

Bây giờ chỉ đủ hỗ trợ Opera Mini: caniuse.com/#search=scrollIntoView
John Magnolia

Có một số polyfill rất nhẹ ngoài kia cho nó.
Martin James

1

Giao diện người dùng của tôi có một danh sách cuộn dọc của ngón tay cái trong một ngón tay cái Mục tiêu là làm cho ngón tay cái hiện tại ở ngay giữa thanh ngón tay cái. Tôi bắt đầu từ câu trả lời đã được phê duyệt, nhưng thấy rằng có một vài điều chỉnh để thực sự tập trung vào ngón tay cái hiện tại. Hy vọng điều này sẽ giúp người khác.

đánh dấu:

<ul id='thumbbar'>
    <li id='thumbbar-123'></li>
    <li id='thumbbar-124'></li>
    <li id='thumbbar-125'></li>
</ul>

jquery:

// scroll the current thumb bar thumb into view
heightbar   = $('#thumbbar').height();
heightthumb = $('#thumbbar-' + pageid).height();
offsetbar   = $('#thumbbar').scrollTop();


$('#thumbbar').animate({
    scrollTop: offsetthumb.top - heightbar / 2 - offsetbar - 20
});

0

2 bước đơn giản để cuộn xuống cuối hoặc cuối.

Bước 1: lấy toàn bộ chiều cao của div có thể cuộn (hội thoại).

Bước2: áp dụng scrollTop trên div (hội thoại) có thể cuộn đó bằng cách sử dụng giá trị thu được trong bước 1.

var fullHeight = $('#conversation')[0].scrollHeight;

$('#conversation').scrollTop(fullHeight);

Các bước trên phải được áp dụng cho mọi phụ lục trên div cuộc hội thoại.


0

Sau khi cố gắng tìm một giải pháp xử lý mọi tình huống (các tùy chọn để tạo hiệu ứng cuộn, đệm xung quanh đối tượng một khi nó cuộn vào chế độ xem, hoạt động ngay cả trong các trường hợp tối nghĩa như trong iframe), cuối cùng tôi đã viết ra giải pháp của riêng mình cho vấn đề này. Vì nó dường như hoạt động khi nhiều giải pháp khác thất bại, tôi nghĩ tôi muốn chia sẻ nó:

function scrollIntoViewIfNeeded($target, options) {

    var options = options ? options : {},
    $win = $($target[0].ownerDocument.defaultView), //get the window object of the $target, don't use "window" because the element could possibly be in a different iframe than the one calling the function
    $container = options.$container ? options.$container : $win,        
    padding = options.padding ? options.padding : 20,
    elemTop = $target.offset().top,
    elemHeight = $target.outerHeight(),
    containerTop = $container.scrollTop(),
    //Everything past this point is used only to get the container's visible height, which is needed to do this accurately
    containerHeight = $container.outerHeight(),
    winTop = $win.scrollTop(),
    winBot = winTop + $win.height(),
    containerVisibleTop = containerTop < winTop ? winTop : containerTop,
    containerVisibleBottom = containerTop + containerHeight > winBot ? winBot : containerTop + containerHeight,
    containerVisibleHeight = containerVisibleBottom - containerVisibleTop;

    if (elemTop < containerTop) {
        //scroll up
        if (options.instant) {
            $container.scrollTop(elemTop - padding);
        } else {
            $container.animate({scrollTop: elemTop - padding}, options.animationOptions);
        }
    } else if (elemTop + elemHeight > containerTop + containerVisibleHeight) {
        //scroll down
        if (options.instant) {
            $container.scrollTop(elemTop + elemHeight - containerVisibleHeight + padding);
        } else {
            $container.animate({scrollTop: elemTop + elemHeight - containerVisibleHeight + padding}, options.animationOptions);
        }
    }
}

$target là một đối tượng jQuery chứa đối tượng bạn muốn cuộn vào xem nếu cần.

options (tùy chọn) có thể chứa các tùy chọn sau được truyền trong một đối tượng:

options.$container- một đối tượng jQuery trỏ đến phần tử chứa của $ target (nói cách khác, phần tử trong dom với thanh cuộn). Mặc định cho cửa sổ chứa phần tử $ đích và đủ thông minh để chọn cửa sổ iframe. Hãy nhớ bao gồm $ trong tên thuộc tính.

options.padding- phần đệm theo pixel để thêm phía trên hoặc bên dưới đối tượng khi nó được cuộn vào dạng xem. Bằng cách này, nó không đúng với cạnh của cửa sổ. Mặc định là 20.

options.instant- nếu được đặt thành true, animate jQuery sẽ không được sử dụng và cuộn sẽ ngay lập tức bật đến đúng vị trí. Mặc định là sai.

options.animationOptions- bất kỳ tùy chọn jQuery nào bạn muốn chuyển đến hàm animate jQuery (xem http://api.jquery.com/animate/ ). Với điều này, bạn có thể thay đổi thời lượng của hình ảnh động hoặc thực hiện chức năng gọi lại khi cuộn hoàn tất. Điều này chỉ hoạt động nếu options.instantđược đặt thành false. Nếu bạn cần phải có một hình ảnh động tức thì nhưng với một cuộc gọi lại, hãy đặt options.animationOptions.duration = 0thay vì sử dụng options.instant = true.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.