Tổng quan cơ bản về cách tạo thành phần chuyển đổi thích ứng và dễ tiếp cận.
Trong bài đăng này, tôi muốn chia sẻ cách xây dựng các thành phần nút chuyển. Xem bản minh hoạ.
Nếu bạn thích xem video hơn, sau đây là phiên bản của bài đăng này trên YouTube:
Tổng quan
Nút chuyển hoạt động tương tự như hộp đánh dấu nhưng thể hiện rõ ràng trạng thái bật và tắt boolean.
Bản minh hoạ này sử dụng <input type="checkbox" role="switch">
cho phần lớn
, có lợi thế là không cần phải có CSS hoặc JavaScript
đầy đủ chức năng và dễ tiếp cận. Việc tải CSS giúp hỗ trợ từ phải sang trái
ngôn ngữ, độ dọc, ảnh động, v.v. Việc tải JavaScript sẽ thực hiện việc chuyển đổi
có thể kéo và hữu hình.
Thuộc tính tuỳ chỉnh
Các biến sau đây đại diện cho các phần của nút chuyển và
. Là lớp cấp cao nhất, .gui-switch
chứa các thuộc tính tuỳ chỉnh được sử dụng
xuyên suốt các thành phần con và các điểm truy cập cho
phần tuỳ chỉnh.
Theo dõi
Độ dài (--track-size
), khoảng đệm và hai màu:
.gui-switch {
--track-size: calc(var(--thumb-size) * 2);
--track-padding: 2px;
--track-inactive: hsl(80 0% 80%);
--track-active: hsl(80 60% 45%);
--track-color-inactive: var(--track-inactive);
--track-color-active: var(--track-active);
@media (prefers-color-scheme: dark) {
--track-inactive: hsl(80 0% 35%);
--track-active: hsl(80 60% 60%);
}
}
Thumb
Kích thước, màu nền và màu sắc tương tác được làm nổi bật:
.gui-switch {
--thumb-size: 2rem;
--thumb: hsl(0 0% 100%);
--thumb-highlight: hsl(0 0% 0% / 25%);
--thumb-color: var(--thumb);
--thumb-color-highlight: var(--thumb-highlight);
@media (prefers-color-scheme: dark) {
--thumb: hsl(0 0% 5%);
--thumb-highlight: hsl(0 0% 100% / 25%);
}
}
Giảm chuyển động
Để thêm bí danh rõ ràng và giảm tình trạng lặp lại, hãy giảm bớt lựa chọn ưu tiên về chuyển động cho người dùng truy vấn phương tiện truyền thông có thể được đặt vào thuộc tính tùy chỉnh bằng mã PostCSS trình bổ trợ dựa trên bản nháp này thông số kỹ thuật trong Truy vấn phương tiện 5:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Markup (note: đây là tên ứng dụng)
Tôi đã chọn gói phần tử <input type="checkbox" role="switch">
của mình bằng một
<label>
, nhóm mối quan hệ của chúng lại để tránh liên kết hộp đánh dấu và nhãn
sự không rõ ràng, đồng thời giúp người dùng có thể tương tác với nhãn để
bật/tắt phương thức nhập.
<label for="switch" class="gui-switch">
Label text
<input type="checkbox" role="switch" id="switch">
</label>
<input type="checkbox">
được tạo sẵn bằng
API
và tiểu bang. Chiến lược phát hành đĩa đơn
trình duyệt quản lý
checked
thuộc tính và thông tin đầu vào
sự kiện
chẳng hạn như oninput
và onchanged
.
Bố cục
Flexbox, lưới và tuỳ chỉnh thuộc tính rất quan trọng trong việc duy trì kiểu của thành phần này. Chúng tập trung các giá trị, đặt tên để tính toán hoặc diện tích mơ hồ và bật thuộc tính tuỳ chỉnh nhỏ API để tuỳ chỉnh thành phần dễ dàng.
.gui-switch
Bố cục cấp cao nhất cho nút chuyển là flexbox. Lớp .gui-switch
chứa
thuộc tính tuỳ chỉnh riêng tư và công khai mà con sử dụng để tính toán
của bạn.
.gui-switch {
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
}
Mở rộng và sửa đổi bố cục hộp linh hoạt cũng giống như thay đổi bố cục hộp linh hoạt.
Ví dụ: để đặt nhãn phía trên hoặc phía dưới nút chuyển hoặc để thay đổi
flex-direction
:
<label for="light-switch" class="gui-switch" style="flex-direction: column">
Default
<input type="checkbox" role="switch" id="light-switch">
</label>
Theo dõi
Hộp đánh dấu đầu vào được tạo kiểu là kênh chuyển đổi bằng cách bỏ thông tin đầu vào
appearance: checkbox
và cung cấp kích thước riêng:
.gui-switch > input {
appearance: none;
inline-size: var(--track-size);
block-size: var(--thumb-size);
padding: var(--track-padding);
flex-shrink: 0;
display: grid;
align-items: center;
grid: [track] 1fr / [track] 1fr;
}
Bản nhạc cũng tạo ra một vùng theo dõi lưới ô riêng lẻ để thu thập xác nhận quyền sở hữu.
Thumb
Kiểu appearance: none
cũng sẽ xoá dấu kiểm trực quan do
trình duyệt. Thành phần này sử dụng một
phần tử giả và :checked
pseudo-class trên đầu vào để
thay thế chỉ báo trực quan này.
Thumb là một phần tử con giả (pseudo-phần tử con) được đính kèm vào input[type="checkbox"]
và
xếp chồng ở trên cùng thay vì bên dưới bản nhạc bằng cách xác nhận quyền sở hữu vùng lưới
track
:
.gui-switch > input::before {
content: "";
grid-area: track;
inline-size: var(--thumb-size);
block-size: var(--thumb-size);
}
Kiểu
Thuộc tính tuỳ chỉnh cung cấp thành phần nút chuyển linh hoạt có khả năng điều chỉnh theo màu sắc giao thức, ngôn ngữ từ phải sang trái và tuỳ chọn chuyển động.
Kiểu tương tác chạm
Trên thiết bị di động, trình duyệt sẽ thêm các tính năng nhấn làm nổi bật và chọn văn bản vào nhãn và
đầu vào. Các vấn đề này ảnh hưởng tiêu cực đến phong cách và phản hồi tương tác trực quan
cần công tắc này. Với một vài dòng CSS, tôi có thể loại bỏ các hiệu ứng đó và thêm
kiểu cursor: pointer
của riêng tôi:
.gui-switch {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
Không phải lúc nào cũng nên xoá các kiểu đó vì chúng có thể mang lại giá trị hình ảnh và tương tác. Hãy nhớ cung cấp các lựa chọn thay thế tuỳ chỉnh nếu bạn xoá chúng.
Theo dõi
Kiểu của phần tử này chủ yếu là về hình dạng và màu sắc mà phần tử truy cập
từ phần tử mẹ .gui-switch
thông qua
thác.
.gui-switch > input {
appearance: none;
border: none;
outline-offset: 5px;
box-sizing: content-box;
padding: var(--track-padding);
background: var(--track-color-inactive);
inline-size: var(--track-size);
block-size: var(--thumb-size);
border-radius: var(--track-size);
}
Nhiều tuỳ chọn tuỳ chỉnh cho kênh chuyển đổi có 4 lựa chọn
thuộc tính tuỳ chỉnh. border: none
được thêm vì appearance: none
không
xoá đường viền khỏi hộp đánh dấu trên tất cả trình duyệt.
Thumb
Phần tử thumb đã có ở bên phải track
nhưng cần kiểu vòng tròn:
.gui-switch > input::before {
background: var(--thumb-color);
border-radius: 50%;
}
Tương tác
Sử dụng thuộc tính tuỳ chỉnh để chuẩn bị cho những lượt tương tác sẽ hiển thị thao tác di chuột được đánh dấu và thay đổi vị trí ngón cái. Lựa chọn ưu tiên của người dùng cũng là đã chọn trước khi chuyển đổi kiểu đánh dấu chuyển động hoặc di chuột.
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
Vị trí ngón cái
Thuộc tính tuỳ chỉnh cung cấp một cơ chế nguồn duy nhất để định vị nút thumb trong
bản nhạc. Chúng tôi sẽ tuỳ ý sử dụng kích thước thumb và track sẽ sử dụng trong
các phép tính khác để đảm bảo độ lệch phù hợp và giữa các nội dung nằm trong kênh:
0%
và 100%
.
Phần tử input
sở hữu biến vị trí --thumb-position
và ngón cái
phần tử giả sử dụng nó làm vị trí translateX
:
.gui-switch > input {
--thumb-position: 0%;
}
.gui-switch > input::before {
transform: translateX(var(--thumb-position));
}
Giờ đây, chúng ta có thể thoải mái thay đổi --thumb-position
từ CSS và các lớp giả
được cung cấp trên các phần tử hộp đánh dấu. Vì chúng ta đặt transition: transform
var(--thumb-transition-duration) ease
sớm hơn trên phần tử này theo cách có điều kiện nên các thay đổi này
có thể tạo ảnh động khi thay đổi:
/* positioned at the end of the track: track length - 100% (thumb width) */
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
}
/* positioned in the center of the track: half the track - half the thumb */
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
}
Tôi nghĩ rằng sự sắp xếp tách rời này có kết quả tốt. Phần tử thumb là
chỉ liên quan đến một kiểu, vị trí translateX
. Dữ liệu đầu vào có thể quản lý tất cả
độ phức tạp và tính toán.
Dọc
Việc hỗ trợ được thực hiện bằng một lớp đối tượng sửa đổi -vertical
, lớp này sẽ thêm chế độ xoay với
CSS chuyển đổi thành phần tử input
.
Tuy nhiên, phần tử được xoay 3D không thay đổi chiều cao tổng thể của thành phần,
có thể loại bỏ bố cục khối. Tính đến việc này bằng cách sử dụng --track-size
và
Biến --track-padding
. Tính dung lượng tối thiểu cần thiết cho
một nút dọc để chạy trong bố cục như mong đợi:
.gui-switch.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(-90deg);
}
}
(RTL) từ phải sang trái
Một người bạn CSS, Elad Schecter và tôi đã tạo nguyên mẫu cùng một trình đơn bên trượt ra bằng cách sử dụng các biến đổi CSS được xử lý từ phải sang trái bằng cách lật một biến. Chúng tôi làm điều này vì không có biến đổi thuộc tính logic trong CSS, và có thể không bao giờ có. Elad có ý tưởng tuyệt vời về việc sử dụng giá trị thuộc tính tuỳ chỉnh để đảo ngược tỷ lệ phần trăm, để cho phép quản lý một vị trí theo logic cho phép biến đổi logic. Tôi đã sử dụng chính kỹ thuật này trong quá trình chuyển đổi này và tôi tôi nghĩ rằng mọi việc đã diễn ra rất tốt:
.gui-switch {
--isLTR: 1;
&:dir(rtl) {
--isLTR: -1;
}
}
Ban đầu, một thuộc tính tuỳ chỉnh có tên là --isLTR
chứa giá trị 1
, có nghĩa là
true
vì theo mặc định, bố cục của chúng ta là từ trái sang phải. Sau đó, sử dụng CSS
lớp giả :dir()
,
giá trị được đặt thành -1
khi thành phần này nằm trong bố cục từ phải sang trái.
Đưa --isLTR
vào thực tế bằng cách sử dụng nó trong calc()
ở bên trong một phép biến đổi:
.gui-switch.-vertical > input {
transform: rotate(-90deg);
transform: rotate(calc(90deg * var(--isLTR) * -1));
}
Bây giờ, hướng xoay của công tắc dọc tài khoản cho vị trí phía đối diện theo yêu cầu của bố cục từ phải sang trái.
translateX
biến đổi trên phần tử giả thumb cũng cần được cập nhật thành
tính đến yêu cầu ở chiều ngược lại:
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
--thumb-position: calc(
((var(--track-size) / 2) - (var(--thumb-size) / 2))
* var(--isLTR)
);
}
Mặc dù phương pháp này sẽ không hoạt động để giải quyết tất cả các nhu cầu về một khái niệm như CSS logic chuyển đổi, nó cung cấp một số Nguyên tắc về DRY (DRY) đối với nhiều các trường hợp sử dụng.
Tiểu bang
Việc sử dụng input[type="checkbox"]
tích hợp sẵn sẽ không hoàn chỉnh nếu không có
xử lý các trạng thái khác nhau như :checked
, :disabled
,
:indeterminate
và :hover
. :focus
cố tình để lại một mình với
điều chỉnh chỉ được thực hiện đối với khoản bù trừ; vòng lấy nét trông rất tuyệt trên Firefox và
Safari:
Đã chọn
<label for="switch-checked" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-checked" checked="true">
</label>
Trạng thái này thể hiện trạng thái on
. Ở trạng thái này, đầu vào "theo dõi"
nền được đặt thành màu hoạt động và vị trí ngón cái được đặt thành "
kết thúc".
.gui-switch > input:checked {
background: var(--track-color-active);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
Đã tắt
<label for="switch-disabled" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-disabled" disabled="true">
</label>
Nút :disabled
không chỉ có hình thức khác biệt mà còn khiến cho
Phần tử không thể thay đổi.Tính không biến đổi của tương tác là không có trong trình duyệt, nhưng
trạng thái hình ảnh cần kiểu do sử dụng appearance: none
.
.gui-switch > input:disabled {
cursor: not-allowed;
--thumb-color: transparent;
&::before {
cursor: not-allowed;
box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);
@media (prefers-color-scheme: dark) { & {
box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
}}
}
}
Trạng thái này khá phức tạp vì cần có giao diện tối và sáng khi bật cả hai tuỳ chọn trạng thái đã đánh dấu. Tôi đã chọn kiểu tối giản cho những trạng thái này sao cho dễ chịu gánh nặng duy trì của việc kết hợp kiểu.
Không xác định
Một trạng thái thường bị quên là :indeterminate
, trong đó không có hộp đánh dấu
đã chọn hoặc bỏ chọn. Đây là một trạng thái thú vị, hấp dẫn và khiêm tốn. Tốt
để nhắc rằng các trạng thái boolean có thể có trạng thái lén lút giữa các trạng thái.
Việc đặt hộp đánh dấu là không xác định, chỉ JavaScript mới có thể đặt hộp đánh dấu:
<label for="switch-indeterminate" class="gui-switch">
Indeterminate
<input type="checkbox" role="switch" id="switch-indeterminate">
<script>document.getElementById('switch-indeterminate').indeterminate = true</script>
</label>
Với tôi, tiểu bang không hề thân thiện và hấp dẫn nên tôi cảm thấy rất phù hợp để đưa vị trí ngón cái của công tắc ở giữa:
.gui-switch > input:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
Khoảng cách di
Hoạt động tương tác khi di chuột sẽ cung cấp hình ảnh trực quan cho giao diện người dùng được kết nối, đồng thời cung cấp hướng tới giao diện người dùng tương tác. Nút chuyển này làm nổi bật nút thumb vòng bán trong suốt khi di chuột qua nhãn hoặc dữ liệu đầu vào. Thao tác di chuột này ảnh động sau đó cung cấp hướng về phần tử thumb tương tác.
"Điểm nổi bật" hiệu ứng được thực hiện bằng box-shadow
. Khi di chuột, của một đầu vào không bị tắt, hãy tăng kích thước của --highlight-size
. Nếu người dùng vẫn ổn với chuyển động, chúng ta sẽ chuyển đổi box-shadow
và thấy nó lớn lên, nếu họ không ổn với chuyển động, thành phần được đánh dấu sẽ xuất hiện ngay lập tức:
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
.gui-switch > input:not(:disabled):hover::before {
--highlight-size: .5rem;
}
JavaScript
Đối với tôi, giao diện công tắc có thể gây bất tiện khi cố gắng mô phỏng một giao diện giao diện, đặc biệt là loại này với một vòng tròn bên trong một đường đi. iOS đã khắc phục được vấn đề này bằng công tắc của họ, bạn có thể kéo họ từ bên này sang bên kia, và thật hài lòng khi có tuỳ chọn. Ngược lại, một phần tử trên giao diện người dùng có thể cảm thấy không hoạt động nếu cử chỉ kéo đã cố gắng và không có gì xảy ra.
Ngón tay cái có thể kéo
Phần tử giả ngón cái nhận vị trí từ .gui-switch > input
trong phạm vi var(--thumb-position)
, JavaScript có thể cung cấp một giá trị kiểu cùng dòng trên
đầu vào để cập nhật động vị trí ngón tay cái, khiến vị trí đó dường như theo sau
cử chỉ con trỏ. Khi thả con trỏ, hãy xoá các kiểu cùng dòng và
xác định xem lực kéo đó gần với vị trí tắt hơn hay bật hơn bằng cách sử dụng thuộc tính tùy chỉnh
--thumb-position
. Đây là trọng tâm của giải pháp; sự kiện con trỏ
theo dõi có điều kiện vị trí con trỏ để sửa đổi các thuộc tính tuỳ chỉnh CSS.
Vì thành phần đã hoạt động 100% trước khi tập lệnh này hiển thị thì sẽ mất khá nhiều công sức để duy trì hành vi hiện tại, như nhấp vào một nhãn để bật/tắt mục nhập. JavaScript của chúng tôi không nên thêm tính năng tại những tính năng hiện có.
touch-action
Kéo là một cử chỉ tuỳ chỉnh, khiến nó trở thành một cử chỉ tuyệt vời
Lợi ích của touch-action
. Trong trường hợp công tắc này, một cử chỉ ngang sẽ
được tập lệnh của chúng tôi xử lý hoặc một cử chỉ dọc được ghi lại cho nút chuyển dọc
biến thể. Với touch-action
, chúng ta có thể cho trình duyệt biết cần xử lý cử chỉ nào
phần tử này, để một tập lệnh có thể xử lý một cử chỉ mà không cần cạnh tranh.
CSS sau đây hướng dẫn trình duyệt rằng khi cử chỉ con trỏ bắt đầu từ trong kênh chuyển đổi này, xử lý các cử chỉ dọc, không làm gì với thao tác ngang đơn vị:
.gui-switch > input {
touch-action: pan-y;
}
Kết quả mong muốn là một cử chỉ theo chiều ngang mà không xoay hoặc cuộn . Con trỏ có thể cuộn theo chiều dọc bắt đầu từ bên trong giá trị nhập và cuộn nhưng các trang ngang được xử lý tuỳ chỉnh.
Tiện ích kiểu của giá trị pixel
Khi thiết lập và trong quá trình kéo, bạn cần lấy nhiều giá trị số đã tính
từ các phần tử. Các hàm JavaScript sau đây trả về giá trị pixel đã tính toán
cho một thuộc tính CSS. Mã này được dùng trong tập lệnh thiết lập như thế này
getStyle(checkbox, 'padding-left')
.
const getStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element).getPropertyValue(prop));
}
const getPseudoStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element, ':before').getPropertyValue(prop));
}
export {
getStyle,
getPseudoStyle,
}
Hãy lưu ý cách window.getComputedStyle()
chấp nhận đối số thứ hai là phần tử giả mục tiêu. Khá thú vị khi JavaScript có thể đọc rất nhiều giá trị từ các phần tử, thậm chí từ các phần tử giả.
dragging
Đây là thời điểm cốt lõi trong logic kéo và có một vài điều cần lưu ý qua trình xử lý sự kiện hàm:
const dragging = event => {
if (!state.activethumb) return
let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
let directionality = getStyle(state.activethumb, '--isLTR')
let track = (directionality === -1)
? (state.activethumb.clientWidth * -1) + thumbsize + padding
: 0
let pos = Math.round(event.offsetX - thumbsize / 2)
if (pos < bounds.lower) pos = 0
if (pos > bounds.upper) pos = bounds.upper
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}
Nội dung chính của tập lệnh là state.activethumb
, vòng tròn nhỏ của tập lệnh này là
cùng với một con trỏ. Đối tượng switches
là Map()
trong đó
khoá là .gui-switch
, còn giá trị là giới hạn và kích thước được lưu vào bộ nhớ đệm để giữ cho
cho tập lệnh một cách hiệu quả. Từ phải sang trái được xử lý bằng cùng một thuộc tính tùy chỉnh
CSS đó là --isLTR
và có thể sử dụng CSS này để đảo ngược logic và tiếp tục
hỗ trợ RTL. event.offsetX
cũng có giá trị vì chứa delta
giá trị hữu ích để định vị ngón cái.
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
Dòng cuối cùng này của CSS đặt thuộc tính tùy chỉnh mà phần tử ngón cái sử dụng. Chiến dịch này
nếu không gán giá trị sẽ chuyển đổi theo thời gian, nhưng con trỏ trước đó
sự kiện đã tạm thời đặt --thumb-transition-duration
thành 0s
, xóa những gì
có thể là một tương tác chậm chạp.
dragEnd
Để người dùng được phép kéo ra ngoài công tắc và thả công tắc, sự kiện cửa sổ toàn cầu cần được đăng ký:
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
Tôi nghĩ rằng điều quan trọng là người dùng phải được tự do kéo và thả lỏng giao diện đủ thông minh để giải thích. Tôi không mất nhiều công sức để xử lý với việc chuyển đổi này, nhưng cần xem xét cẩn thận trong quá trình phát triển của chúng tôi.
const dragEnd = event => {
if (!state.activethumb) return
state.activethumb.checked = determineChecked()
if (state.activethumb.indeterminate)
state.activethumb.indeterminate = false
state.activethumb.style.removeProperty('--thumb-transition-duration')
state.activethumb.style.removeProperty('--thumb-position')
state.activethumb.removeEventListener('pointermove', dragging)
state.activethumb = null
padRelease()
}
Đã hoàn tất tương tác với phần tử, đã đến lúc đặt giá trị đầu vào
thuộc tính và xoá tất cả các sự kiện cử chỉ. Đã thay đổi hộp đánh dấu bằng
state.activethumb.checked = determineChecked()
.
determineChecked()
Hàm này (do dragEnd
gọi), xác định vị trí hiện tại của ngón cái
trong giới hạn của kênh và trả về true nếu giá trị đó bằng hoặc lớn hơn
ở giữa đường đua:
const determineChecked = () => {
let {bounds} = switches.get(state.activethumb.parentElement)
let curpos =
Math.abs(
parseInt(
state.activethumb.style.getPropertyValue('--thumb-position')))
if (!curpos) {
curpos = state.activethumb.checked
? bounds.lower
: bounds.upper
}
return curpos >= bounds.middle
}
Ý kiến khác
Thao tác kéo phát sinh một chút thiếu mã do cấu trúc HTML ban đầu
đã chọn, chủ yếu là gói thông tin đầu vào trong một nhãn. Nhãn, là cha mẹ
, sẽ nhận được lượt tương tác nhấp chuột sau khi nhập. Ở cuối
Sự kiện dragEnd
, có thể bạn đã thấy padRelease()
có vẻ kỳ lạ
.
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
Việc này là để tính đến việc nhãn nhận được lần nhấp sau này, vì nó sẽ bỏ chọn, hoặc kiểm tra, tương tác mà một người dùng đã thực hiện.
Nếu phải làm lại điều này, tôi có thể xem xét điều chỉnh DOM bằng JavaScript trong quá trình nâng cấp trải nghiệm người dùng, chẳng hạn như để tạo một phần tử tự xử lý các lượt nhấp vào nhãn và không chiến đấu bằng hành vi tích hợp sẵn.
Loại JavaScript này là loại khó viết nhất của tôi, tôi không muốn quản lý Hiển thị bong bóng sự kiện có điều kiện:
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
Kết luận
Thành phần chuyển đổi dành cho trẻ em này rốt cuộc trở thành thành phần quan trọng nhất trong tất cả Thử thách về giao diện người dùng đồ hoạ cho đến nay! Giờ bạn đã biết cách tôi thực hiện điều đó, bạn sẽ làm cách nào‽ 🙂
Hãy đa dạng hoá phương pháp tiếp cận và tìm hiểu tất cả các cách xây dựng ứng dụng trên web. Tạo một bản minh hoạ, tweet cho tôi các đường liên kết và tôi sẽ thêm vào vào phần bản phối lại của cộng đồng dưới đây!
Bản phối lại của cộng đồng
- @KonstantinRouda với một phần tử tuỳ chỉnh: bản minh hoạ và mã.
- @jhvanderschee bằng một nút: Codepen.
Tài nguyên
Tìm mã nguồn .gui-switch
trên
GitHub.