Dodaj przeciąganie do istniejącego elementu pływającego, takiego jak panel, paleta, pasek narzędzi, inspektor lub okno dialogowe. Przeciąganie nie określa sposobu wyświetlania, odrzucania, układania ani zaznaczania elementu.
Używanie dedykowanego nicka
Zacznij przeciągać od specjalnego uchwytu, gdy element zawiera tekst, przyciski, dane wejściowe lub linki, które można wybrać. Dzięki temu jego normalna zawartość pozostaje użyteczna. Umożliwiaj zaznaczanie uchwytu za pomocą klawiatury i nadaj mu nazwę na potrzeby ułatwień dostępu, która wspomina o interakcji za pomocą klawiszy strzałek.
Nie nakładaj role="application" na uchwyt. niepotrzebnie zmienia interakcję z technologią wspomagającą osoby z niepełnosprawnością,
Zastosuj cursor: grab/grabbing, touch-action: none oraz user-select: none i -webkit-user-select: none do uchwytu, a nie do całego elementu, który można przeciągać, aby tekst poza nim można było zaznaczać, a gesty dotykowe zachowywały swoje zwykłe działanie:
.drag-handle {
cursor: grab;
touch-action: none;
-webkit-user-select: none;
user-select: none;
}
.drag-handle.dragging {
cursor: grabbing;
}
Zachowanie pozycji wskaźnika i dostępności
Jeśli chcesz ograniczyć ruch do widocznego obszaru, użyj modelu pozycjonowania względem widocznego obszaru, takiego jak position: fixed.
- Rozpocznij przeciąganie tylko za pomocą głównego przycisku wskaźnika (
event.button === 0). - Zapisz przesunięcie wskaźnika na elemencie
pointerdowni używaj go przy każdym ruchu, aby element nie przeskakiwał, gdy zostanie chwycony poza rogiem. - Utrzymuj przeciąganie po opuszczeniu uchwytu przez wskaźnik. Domyślnie ustaw
setPointerCapture()i wyczyść stan przeciągania wlostpointercapture. Jeśli uchwyt może zostać usunięty lub ponownie wyrenderowany w trakcie przeciągania, użyj detektorówpointermove,pointerupipointercancelna poziomie dokumentu, ponieważ w takim przypadku przechwytywanie zostanie utracone. - Opcjonalnie możesz poczekać na ruch o około 4 piksele, zanim przejdziesz do stanu przeciągania, aby kliknięcie uchwytu nie powodowało zmiany stylu przeciągania.
Dzięki przechwytywaniu wskaźnika detektory ruchu mogą pozostać na uchwycie:
handle.addEventListener('pointerdown', (event) => {
if (event.button !== 0 || event.target.closest('button, input, select, textarea, a')) return;
const rect = draggable.getBoundingClientRect();
offsetX = event.clientX - rect.left;
offsetY = event.clientY - rect.top;
handle.setPointerCapture(event.pointerId);
});
handle.addEventListener('pointermove', (event) => {
if (!handle.hasPointerCapture(event.pointerId)) return;
handle.classList.add('dragging');
moveTo(event.clientX - offsetX, event.clientY - offsetY);
});
handle.addEventListener('lostpointercapture', () => {
handle.classList.remove('dragging');
});
function moveTo(left, top) {
const maxLeft = Math.max(0, window.innerWidth - draggable.offsetWidth);
const maxTop = Math.max(0, window.innerHeight - draggable.offsetHeight);
draggable.style.left = `${Math.max(0, Math.min(left, maxLeft))}px`;
draggable.style.top = `${Math.max(0, Math.min(top, maxTop))}px`;
}
Zablokuj każdą pozycję wskaźnika i klawiatury za pomocą tego samego pomocnika, aby element był dostępny. ponownie przypiąć go w bieżącej pozycji po zmianie rozmiaru widocznego obszaru lub elementu. W przypadku elementów o skomplikowanym układzie rozważ translację podczas przeciągania, aby uniknąć układu dla każdej klatki, a następnie po zwolnieniu zatwierdź ostateczną pozycję we właściwościach left i top.
Zapewnij możliwość poruszania się za pomocą klawiatury
Gdy uchwyt jest zaznaczony, przesuń element za pomocą klawiszy strzałek i wywołaj preventDefault() dla tych klawiszy. Użyj tego samego pomocnika pozycjonowania z ograniczeniem co w przypadku ruchu wskaźnika. Dobrym punktem wyjścia jest przyrost o 15 pikseli. Dostosuj go do rozmiaru komponentu i wymaganej precyzji.
Uwaga dotycząca okna
<dialog> lub [popover] może używać tego mechanizmu z nagłówkiem jako uchwytem. Ustaw margin: 0 przed przypisaniem left i top, ponieważ domyślne marginesy przeglądarki zakłócają ręczne pozycjonowanie. Informacje o zachowaniu okien dialogowych i okienek popover podczas otwierania, zamykania, zaznaczania i odrzucania znajdziesz w artykułach Declarative Dialog and Popover Control (Deklaratywne okno dialogowe i kontrola okienek popover) oraz Platform Controls Dismiss Dialog (Okno dialogowe odrzucania elementów sterujących platformy).
Strategie zastępcze
Jeśli przeciąganie tylko zmienia pozycję komponentu, potraktuj to jako progresywne ulepszanie: bez JavaScriptu element, jego zawartość i elementy sterujące powinny być widoczne, czytelne i funkcjonalne w rozsądnej domyślnej pozycji. Nie udostępniaj niedziałającego uchwytu do przeciągania: jeśli uchwyt jest samodzielnym elementem sterującym, ukryj go domyślnie i wyświetl, gdy JavaScript zostanie zainicjowany. Jeśli nagłówek pełni funkcję uchwytu, dołącz jego funkcje przeciągania, gdy JavaScript zostanie zainicjowany.
Uwzględnij -webkit-user-select: none przed user-select: none, aby zaznaczanie tekstu było wyłączone podczas przeciągania w Safari.