Zum keluar zum masuk dengan titik tongkat ialah kes penggunaan biasa yang kami temui pada alat reka bentuk atau pembina seperti Figma. Dalam blog ini, saya akan membentangkan algoritma asas untuk mengendalikannya dengan javascript, HTML dan CSS.
Demonstrasi
1. Buat bekas dan item boleh skala
<div id="app"> <div class="parent"> <div class="scalable-child"></div> </div> </div>
.scalable-child { width: 300px; height: 300px; position: relative; top: 0; left: 0; pointer-events: none; transform-origin: left top; background-image: url('https://cdn4.vectorstock.com/i/1000x1000/17/58/caro-pattern-background-vector-2261758.jpg'); background-size: contain; } .parent { position: relative; background-color: white; width: 100vw; height: 100vh; }
Dalam contoh ini, saya menggunakan div sebagai item boleh skala dengan kelas “scalable-child” dan bekasnya ialah div dengan kelas “parent”.
Sila ambil perhatian untuk beberapa hartanah:
Atas, kiri: 0 ialah kedudukan lalai
Peristiwa penuding: tiada, kerana kami akan menambah acara pada induk, jika peristiwa penuding !== tiada algoritma akan gagal.
Ubah-asal: atas kiri, yang menjadikan asal koordinat untuk mengira kedudukan
2. Tambahkan pendengar acara roda
const parent = document.querySelector('.parent'); const child = document.querySelector('.scalable-child');
parent.addEventListener('wheel', wheelEventHandler, { passive: false, capture: true, });
Kami akan menggunakan WheelEvent untuk mengendalikan zum masuk, zum keluar dan kanak-kanak bergerak
Nota: contoh ini menunjukkan hanya untuk pad jejak. Anda perlu mengendalikan acara untuk kekunci pintas seperti (Ctrl +, Ctr -) atau tetikus juga.
let left = 0; let top = 0; let scale = 1; const wheelEventHandler = (e) => { e.preventDefault(); // Handle zoom with touch pad and hot key. const isZooming = e.ctrlKey || e.metaKey; let newValues = {}; if (isZooming) { newValues = calculateOnZooming(e, scale, left, top); } else { newValues = calculateOnMoving(e, scale, left, top); } left = newValues.newLeft; top = newValues.newTop; scale = newValues.newScale; Object.assign(child.style, { transform: `scale(${scale})`, left: `${left}px`, top: `${top}px`, }); };
Pertama, kami mempunyai pembolehubah isZooming untuk menyemak sama ada mengezum atau mengalihkan elemen anak.
Kemudian kami mengira kedudukan dan skala baharu untuk elemen kanak-kanak. Kiri, atas dan skala digunakan sebagai pembolehubah sederhana.
Dan tiba masanya untuk memfokuskan algoritma pada 2 fungsi pengiraan:
3. Kira pada Zum
const calculateOnZooming = (e, oldScale, oldLeft, oldTop) => { let newScale = oldScale - e.deltaY * oldScale * 0.01; newScale = Math.max(newScale, 0.1); const newLeft = oldLeft - (e.offsetX - oldLeft) * (newScale / scale - 1); const newTop = oldTop - (e.offsetY - oldTop) * (newScale / scale - 1); return { newScale, newLeft, newTop, }; };
Apabila mengezum, wheelEvent akan mengembalikan deltaY sebagai nisbah skala dan kami boleh menggunakannya untuk mengira Skala baharu
deltaY > 0 => zum keluar
deltaY < 0 => zum masuk
DetalScale = e.deltaY * oldScale * 0.01 untuk mengawal kelajuan penskalaan
Mari lihat imej di bawah untuk lebih memahami cara mengira pembolehubah Kiri dan Baharu baharu:
Mula mengezum masuk kanak-kanak apabila tetikus berada dalam titik A. Pada masa itu, kita boleh mendapatkan beberapa nilai:
e.offsetX: jarak antara tetikus ke tepi kiri ibu bapa
e.offsetY: jarak antara tetikus ke tepi atas ibu bapa
kiri: nilai gaya kiri kanak-kanak semasa
atas: nilai gaya teratas kanak-kanak semasa
Kanak-kanak diskalakan daripada nisbah skala kepada nisbah skala’, dan titik A pergi ke A’.
Jadi untuk menjadikan A mata melekit (dengan ibu bapa), kita perlu mengira deltaX dan deltaY kemudian gerakkan kembali anak dengan tepat px.
detalX = x’ - x
= x * (skala’ / skala) - x
= x * (skala’ / skala - 1)
= (e.offsetX - kiri) * (skala’ / skala - 1)
detalY = y’ - y
= y * (skala’ / skala) - y
= y * (skala’ / skala - 1)
= (e.offsetY - atas) * (skala’ / skala - 1)
newLeft = kiri - detalX
newTop = atas - detalY
4. Kira semasa Bergerak
const calculateOnMoving = (e, oldScale, oldLeft, oldTop) => { return { newLeft: oldLeft - e.deltaX * 2, newTop: oldTop - e.deltaY * 2, newScale: oldScale, }; };
Mengenai acara bergerak, kita perlu mengira hanya nilai Kiri baru dan baruAtas. Dan kami *2 setiap nilai delta untuk meningkatkan kelajuan juga.
Itu sahaja yang perlu kami tangani. Saya harap ia membantu. Terima kasih kerana menonton!
Anda boleh melihat kod sumber penuh di sini.
Atas ialah kandungan terperinci Zum masuk zum keluar titik melekit dalam kanvas. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!