Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. JavaScript
Code

Tạo Carousel hoàn hảo, Phần 3

by
Difficulty:AdvancedLength:LongLanguages:
This post is part of a series called Create the Perfect Carousel.
Create the Perfect Carousel, Part 2

Vietnamese (Tiếng Việt) translation by Andrea Ho (you can also view the original English article)

Đây là phần thứ ba và là phần cuối cùng của loạt bài hướng dẫn Tạo Carousel hoàn hảo của chúng tôi. Trong phần 1, chúng tôi đã đánh giá carousel trên Netflix và Amazon, hai trong số các carousel được sử dụng nhiều nhất trên thế giới. Chúng tôi thiết lập carousel của chúng tôi và triển khai phần cuộn cảm ứng.

Sau đó, trong phần 2, chúng tôi đã thêm phần cuộn chuột ngang, phân trang và thông báo tiến trình. Boom.

Bây giờ, trong phần cuối cùng, chúng ta sẽ xem xét thế giới âm u và bị quên lãng của bàn phím. Chúng tôi sẽ điều chỉnh code để định kích cỡ carousel khi viewport thay đổi kích thước.

Bạn có thể tiếp tục ở nơi chúng tôi đã thực hiện ở CodePen này.

Keyboard Accessibilty

Đúng là đa số người dùng không dùng điều hướng bằng bàn phím, thật đáng buồn khi chúng tôi thỉnh thoảng lãng quên người dùng của mình. Ở một số quốc gia, một website không thể truy cập có thể là bất hợp pháp. Nhưng tệ hơn, đó là một việc làm dại dột.

Tin tốt là điều này dễ thực hiện! Trên thực tế, trình duyệt thực hiện phần lớn công việc cho chúng tôi. Một cách nghiêm túc: thử tabbing qua carousel chúng tôi đã xây dựng. Bởi vì chúng tôi đã sử dụng markup có ngữ nghĩa, có thể bạn làm rồi!

Ngoại trừ, bạn sẽ nhận thấy, các nút điều hướng của chúng tôi biến mất. Điều này là do trình duyệt không cho phép tập trung vào một phần tử nằm bên ngoài viewport của chúng tôi. Vì vậy, mặc dù chúng tôi có overflow: hidden, chúng tôi không thể cuộn trang theo chiều ngang; nếu không, trang sẽ thực sự cuộn để hiển thị phần tử có trọng tâm.

Điều này là ổn, và nó sẽ đủ điều kiện, theo ý kiến ​​của tôi, như

Băng chuyền của Netflix cũng hoạt động theo cách này. Nhưng vì phần lớn tiêu đề của họ bị tải chậm và chúng cũng có thể truy cập bằng bàn phím thụ động (có nghĩa là họ không viết bất kỳ mã nào để xử lý), chúng tôi không thể chọn bất kỳ tiêu đề nào ngoài số đã được tải. Nó cũng trông khủng khiếp:

Keyboard Accessibility

Chúng ta có thể làm tốt hơn.

Xử lý sự kiện focus

Để làm điều này, chúng ta sẽ lắng nghe sự kiện focus được kích hoạt vào bất kỳ mục nào trong carousel. Khi một mục vào trọng tâm, chúng ta sẽ truy vấn vị trí của nó. Sau đó, chúng tôi sẽ kiểm tra điều đó với sliderXsliderVisibleWidth để xem mục đó có nằm trong cửa sổ hiển thị hay không. Nếu không, chúng tôi sẽ phân trang nó bằng cách sử dụng cùng mã mà chúng tôi đã viết trong phần 2.

Ở cuối hàm carousel, thêm trình xử lý sự kiện này:

Bạn sẽ nhận thấy chúng tôi đã cung cấp thông số thứ ba, true. Thay vì thêm một event listener vào từng mục, chúng tôi có thể sử dụng event delegation để nghe các sự kiện trên với chỉ một phần tử, là phần tử cao cấp trực tiếp của nó. Sự kiện tập trung không bong bóng, vì vậy sự thật là nói cho người nghe sự kiện lắng nghe cho giai đoạn chụp, giai đoạn mà sự kiện cháy trên mọi phần tử từ cửa sổ đến mục tiêu (trong trường hợp này, mục nhận được tiêu điểm).

Phía trên khối trình phát sự kiện ngày càng tăng của chúng tôi, hãy thêm hàm onFocus:

Chúng tôi sẽ làm việc trong chức năng này cho phần còn lại của phần này.

Chúng ta cần đo độ lệch bên trái và bên phải của mặt hàng và kiểm tra xem một trong hai điểm nằm ngoài khu vực có thể xem hiện tại hay không.

Mục được cung cấp bởi tham số đích của sự kiện và chúng ta có thể đo nó bằng getBoundingClientRect:

trái và phải liên quan đến khung nhìn, không phải là thanh trượt. Vì vậy, chúng tôi cần phải có được bù đắp bên trái của băng chuyền để tính toán điều đó. Trong ví dụ của chúng tôi, điều này sẽ là 0, nhưng để làm cho băng chuyền trở nên mạnh mẽ, nó nên chiếm vị trí được đặt ở bất kỳ đâu.

Bây giờ, chúng ta có thể thực hiện kiểm tra đơn giản để xem liệu mục có nằm ngoài vùng hiển thị của thanh trượt và được phân trang theo hướng đó hay không:

Bây giờ, khi chúng tôi tab xung quanh, băng chuyền tự tin nằm xung quanh với trọng tâm bàn phím của chúng tôi! Chỉ cần một vài dòng mã để hiển thị nhiều tình yêu hơn cho người dùng của chúng tôi.

Remeasure Carousel

Bạn có thể đã nhận thấy khi bạn làm theo hướng dẫn này nếu bạn thay đổi kích thước chế độ xem trình duyệt của mình, băng chuyền không phân trang đúng cách nữa. Điều này là do chúng tôi đo chiều rộng của nó tương ứng với khu vực hiển thị của nó chỉ một lần, tại thời điểm khởi tạo.

Để đảm bảo băng chuyền của chúng tôi hoạt động chính xác, chúng tôi cần phải thay thế một số mã đo lường của chúng tôi bằng trình xử lý sự kiện mới kích hoạt khi cửa sổ đổi kích thước.

Bây giờ, gần đầu của hàm băng chuyền của bạn, ngay sau dòng mà chúng ta xác định progressBar, chúng ta muốn thay thế ba phép đo const bằng let, bởi vì chúng ta sẽ thay đổi chúng khi khung nhìn thay đổi:

Sau đó, chúng ta có thể di chuyển logic mà trước đây đã tính toán các giá trị này thành một hàm measureCarousel mới:

Chúng tôi muốn ngay lập tức gọi chức năng này vì vậy chúng tôi vẫn thiết lập các giá trị này khi khởi tạo. Trên dòng tiếp theo, gọi measureCarousel:

Băng chuyền phải hoạt động chính xác như trước. Để cập nhật kích thước cửa sổ, chúng tôi chỉ cần thêm trình xử lý sự kiện này vào cuối chức năng băng chuyền của chúng tôi:

Bây giờ, nếu bạn thay đổi kích thước băng chuyền và thử phân trang, nó sẽ tiếp tục hoạt động như mong đợi.

Lưu ý về hiệu suất

Điều đáng xem xét là trong thế giới thực, bạn có thể có nhiều băng chuyền trên cùng một trang, nhân tác động hiệu suất của mã đo lường này với số tiền đó.

Như chúng tôi đã thảo luận ngắn gọn trong phần 2, việc thực hiện các phép tính nặng thường xuyên hơn bạn phải là không khôn ngoan. Với các sự kiện con trỏ và cuộn, chúng tôi đã nói bạn muốn thực hiện một lần trên mỗi khung hình để giúp duy trì 60 khung hình / giây. Thay đổi kích thước các sự kiện có một chút khác biệt ở chỗ toàn bộ tài liệu sẽ được chỉnh lại, có thể là thời điểm tốn nhiều thời gian nhất cho tài nguyên mà trang web sẽ gặp phải.

Chúng tôi không cần phải khắc phục băng chuyền cho đến khi người dùng đã hoàn tất thay đổi kích thước cửa sổ, bởi vì họ sẽ không tương tác với nó trong thời gian chờ đợi. Chúng ta có thể bọc hàm measureCarousel của chúng ta trong một hàm đặc biệt gọi là debounce.

Một chức năng debounce về cơ bản nói:

Chạm hoàn thiện

Cho đến nay, chúng tôi đã tạo ra một băng chuyền khá tốt. Nó có thể truy cập, nó hoạt hình độc đáo, nó hoạt động trên cảm ứng và chuột, và nó cung cấp rất nhiều tính linh hoạt thiết kế trong một cách băng chuyền tự nhiên cuộn không cho phép.

Nhưng đây không phải là

Chúng ta sẽ thêm hai tương tác bằng cách sử dụng lò xo. Một cho liên lạc, và một cho pagination. Cả hai đều sẽ cho người dùng biết, theo cách vui vẻ và vui tươi, rằng họ đã đến cuối băng chuyền.

Chạm vào mùa xuân

Trước tiên, hãy thêm một kiểu kéo theo kiểu iOS khi người dùng cố gắng cuộn thanh trượt qua các ranh giới của nó. Hiện tại, chúng tôi đang giới hạn cuộn cảm ứng bằng cách sử dụng kẹpXOffset. Thay vào đó, hãy thay thế điều này bằng một số mã áp dụng một kéo khi bù trừ được tính toán nằm ngoài ranh giới của nó.

Đầu tiên, chúng ta cần nhập mùa xuân của mình. Có một biến được gọi là nonlinearSpring áp dụng một lực tăng theo cấp số nhân so với số chúng ta cung cấp cho nó, đối với một nguồn gốc. Điều đó có nghĩa là chúng tôi càng kéo thanh trượt càng nhiều thì thanh trượt càng kéo mạnh. Chúng ta có thể nhập nó như sau:

Trong hàm defineDragDirection, chúng ta có mã này:

Ngay phía trên nó, hãy tạo hai lò xo của chúng ta, một cho mỗi giới hạn cuộn của băng chuyền:

Quyết định giá trị cho độ co giãn là một vấn đề của việc chơi xung quanh và nhìn thấy những gì cảm thấy đúng. Số lượng quá thấp và mùa xuân cảm thấy quá cứng. Quá cao và bạn sẽ không nhận thấy kéo của nó, hoặc tệ hơn, nó sẽ đẩy thanh trượt xa hơn nữa từ ngón tay của người dùng!

Bây giờ chúng ta chỉ cần viết một hàm đơn giản sẽ áp dụng một trong các lò xo này nếu giá trị được cung cấp nằm ngoài phạm vi cho phép:

Chúng ta có thể thay thế clampXOffset trong đoạn mã trên bằng applySpring. Bây giờ, nếu bạn kéo thanh trượt qua ranh giới của nó, nó sẽ kéo trở lại!

Tuy nhiên, khi chúng ta buông bỏ mùa xuân, nó sắp xếp lại một cách bất ngờ. Chúng tôi muốn sửa đổi chức năng stopTouchScroll của chúng tôi, hiện đang xử lý đà di chuyển, để kiểm tra xem thanh trượt vẫn nằm ngoài phạm vi được phép và, nếu có, hãy áp dụng một lò xo với hành động vật lý thay thế.

Vật lý mùa xuân

Các hành động vật lý có khả năng mô hình lò xo, quá. Chúng ta chỉ cần cung cấp nó với mùa xuân và tài sản.

Trong stopTouchScroll, di chuyển khởi tạo vật lý cuộn hiện có thành một đoạn logic để đảm bảo rằng chúng ta nằm trong giới hạn cuộn:

Trong mệnh đề đầu tiên của câu lệnh if, chúng ta biết rằng thanh trượt nằm ngoài giới hạn cuộn, vì vậy chúng ta có thể thêm mùa xuân của mình:

Chúng tôi muốn tạo ra một mùa xuân mà cảm thấy linh hoạt và đáp ứng. Tôi đã chọn một giá trị mùa xuân tương đối cao để có một

Như một chút bài tập về nhà, hãy thử thay thế kẹpXOffset trong chức năng đầu ra của vật lý cuộn bằng chức năng kích hoạt một lò xo tương tự khi độ lệch x đạt đến ranh giới của nó. Thay vì dừng đột ngột hiện tại, hãy thử làm cho nó bị trả lại nhẹ nhàng vào cuối.

Pagination Spring

Người dùng cảm ứng luôn nhận được sự tốt đẹp mùa xuân, đúng không? Hãy chia sẻ tình yêu đó với người dùng máy tính để bàn bằng cách phát hiện khi băng chuyền đang ở giới hạn cuộn của nó và có một cú kéo chỉ để hiển thị rõ ràng và tự tin cho người dùng rằng họ đang ở cuối.

Đầu tiên, chúng tôi muốn vô hiệu hóa các nút pagination khi đạt đến giới hạn. Trước tiên, hãy thêm quy tắc CSS để tạo kiểu cho các nút để cho biết rằng chúng đã bị tắt. Trong quy tắc nút, hãy thêm:

Chúng tôi đang sử dụng một lớp ở đây thay vì thuộc tính bị vô hiệu hóa ngữ nghĩa hơn vì chúng tôi vẫn muốn nắm bắt các sự kiện nhấp chuột, trong đó, như tên của nó, bị vô hiệu hóa sẽ chặn.

Thêm lớp bị vô hiệu này vào nút Trước đó, vì mỗi băng chuyền bắt đầu cuộc sống với độ lệch 0:

Hướng về phía trên cùng của băng chuyền, tạo một hàm mới có tên là checkNavButtonStatus. Chúng tôi muốn chức năng này chỉ đơn giản là kiểm tra giá trị được cung cấp với minXOffset và maxXOffset và thiết lập các nút bị vô hiệu hóa cho phù hợp:

Nó sẽ được hấp dẫn để gọi điều này mỗi khi sliderX thay đổi. Nếu chúng tôi đã làm, các nút sẽ bắt đầu nhấp nháy bất cứ khi nào một lò xo dao động quanh biên giới cuộn. Nó cũng sẽ dẫn đến hành vi kỳ lạ nếu một trong các nút được nhấn trong một trong những hình ảnh động mùa xuân. Các

Vì vậy, chúng ta cần phải chọn lọc hơn về thời điểm gọi hàm này. Có vẻ hợp lý khi gọi nó:

Trên dòng cuối cùng của onWheel, thêm checkNavButtonStatus (newX) ;.

Trên dòng cuối cùng của goto, thêm checkNavButtonStatus (targetX) ;.

Và cuối cùng, vào cuối của defineDragDirection, và trong mệnh đề cuộn động lượng (mã bên trong cái khác) của stopTouchScroll, hãy thay thế:

Với:

Bây giờ tất cả những gì còn lại là sửa đổi gotoPrev và gotoNext để kiểm tra classList của nút kích hoạt của chúng cho bị vô hiệu hóa và chỉ phân trang nếu nó vắng mặt:

Hàm notifyEnd chỉ là một lò xo vật lý khác, và nó trông giống như sau:

Có một trò chơi với điều đó, và một lần nữa, tinh chỉnh các params vật lý theo ý thích của bạn.

Chỉ còn lại một lỗi nhỏ. Khi thanh trượt vượt quá ranh giới ngoài cùng bên trái, thanh tiến trình đang được đảo ngược. Chúng tôi có thể nhanh chóng khắc phục điều đó bằng cách thay thế:

Với:

Chúng tôi có thể ngăn chặn nó khỏi nảy theo cách khác, nhưng cá nhân tôi nghĩ rằng nó khá mát mẻ mà nó phản ánh phong trào mùa xuân. Nó chỉ trông kỳ lạ khi nó lóe lên trong.

Clean Up After Yourself

Với các ứng dụng một trang, các trang web kéo dài lâu hơn trong phiên của người dùng. Thông thường, ngay cả khi Chúng tôi không thể dựa vào một phương tiện sạch mỗi lần người dùng nhấp vào liên kết và điều đó có nghĩa là chúng tôi phải dọn dẹp sau khi chính mình để ngăn người xem sự kiện kích hoạt các phần tử đã chết.

Trong React, mã này được đặt trong phương thức componentWillLeave. Vue sử dụng beforeDestroy. Đây là một thực thi JS thuần túy, nhưng chúng ta vẫn có thể cung cấp một phương thức tiêu diệt sẽ hoạt động bình đẳng trong cả hai khung công tác.

Cho đến nay, chức năng băng chuyền của chúng tôi đã không trả lại bất cứ điều gì. Hãy thay đổi điều đó.

Đầu tiên, thay đổi dòng cuối cùng, dòng gọi là băng chuyền, thành:

Chúng ta sẽ quay trở lại chỉ một điều từ băng chuyền, một chức năng ngăn cản tất cả những người nghe sự kiện của chúng ta. Vào cuối của hàm băng chuyền, hãy viết:

Bây giờ, nếu bạn gọi destroyCarousel và cố gắng chơi với carousel, không có gì xảy ra! Nó gần như một chút buồn khi thấy nó như thế này.

Và đó là điều đó

Whew. Đó là rất nhiều! Chúng ta đã đi được bao xa. Bạn có thể xem sản phẩm đã hoàn thành tại CodePen này. Trong phần cuối cùng này, chúng tôi đã thêm khả năng truy cập bàn phím, làm lại băng chuyền khi chế độ xem thay đổi, một số bổ sung thú vị với vật lý mùa xuân và bước đột phá nhưng cần thiết để xé tất cả lại.

Tôi hy vọng bạn thích hướng dẫn này nhiều như tôi thích viết nó. Tôi rất muốn nghe suy nghĩ của bạn về các cách thức khác để chúng tôi có thể cải thiện khả năng tiếp cận hoặc thêm nhiều chút thú vị.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.