fix: change md files to md folder
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
|
||||
## 💡 Nguyên lý tính toán đúng (Zoom to Mouse Pointer)
|
||||
|
||||
Để điểm dưới con trỏ chuột đứng yên tại đúng vị trí đó sau khi zoom, bạn cần giữ nguyên **tỷ lệ thời gian (time ratio)** tại điểm con trỏ chuột so với chiều rộng hiện tại của vùng hiển thị (Viewport).
|
||||
|
||||
### **Công thức chuyển đổi:**
|
||||
|
||||
Giả sử thanh cuộn (Scrollbar) có vị trí xả hiện tại là `scrollLeft`:
|
||||
|
||||
1. **Tìm điểm thời gian tương đối tại vị trí chuột ($T_{mouse}$):**
|
||||
|
||||
$$T_{mouse} = \text{scrollLeft} + X_{mouse\_in\_canvas}$$
|
||||
|
||||
|
||||
2. **Tính tỷ lệ zoom mới ($S_{new} / S_{old}$):**
|
||||
|
||||
$$\text{ratio} = \frac{\text{scale}_{new}}{\text{scale}_{old}}$$
|
||||
|
||||
|
||||
3. **Cập nhật vị trí cuộn mới (`scrollLeft_{new}`):**
|
||||
|
||||
$$\text{scrollLeft}_{new} = (T_{mouse} \times \text{ratio}) - X_{mouse\_in\_canvas}$$
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Code mẫu ngắn gọn (Pure JS / Canvas)
|
||||
|
||||
Dưới đây là đoạn code lắng nghe sự kiện `wheel` (lăn chuột) trên Waveform Canvas/Container để xử lý zoom đúng chuẩn các phần mềm DAW:
|
||||
|
||||
```javascript
|
||||
const container = document.getElementById('waveform-container');
|
||||
let pixelsPerSecond = 100; // Tỉ lệ Zoom ban đầu (mức Zoom)
|
||||
|
||||
container.addEventListener('wheel', (e) => {
|
||||
// Chỉ thực hiện zoom khi giữ phím Ctrl (hoặc bạn có thể bỏ condition này nếu muốn lăn chuột là zoom)
|
||||
if (!e.ctrlKey) return;
|
||||
e.preventDefault();
|
||||
|
||||
// 1. Lấy vị trí con trỏ chuột so với viền trái của Waveform Container (Viewport)
|
||||
const rect = container.getBoundingClientRect();
|
||||
const mouseX = e.clientX - rect.left;
|
||||
|
||||
// 2. Tính tọa độ thời gian (giây) tại điểm con trỏ chuột đang chỉ vào
|
||||
const currentScrollLeft = container.scrollLeft;
|
||||
const timeAtMouse = (currentScrollLeft + mouseX) / pixelsPerSecond;
|
||||
|
||||
// 3. Tính tỉ lệ zoom mới (Phóng to / Thu nhỏ)
|
||||
const zoomFactor = e.deltaY < 0 ? 1.2 : 0.8; // Lăn lên = phóng to, lăn xuống = thu nhỏ
|
||||
const newPixelsPerSecond = Math.max(10, Math.min(2000, pixelsPerSecond * zoomFactor));
|
||||
|
||||
// 4. Cập nhật tỉ lệ zoom mới vào ứng dụng
|
||||
pixelsPerSecond = newPixelsPerSecond;
|
||||
|
||||
// (Thực hiện render lại Waveform với pixelsPerSecond mới tại đây)
|
||||
renderWaveform();
|
||||
|
||||
// 5. CẬP NHẬT SCROLLBAR: Cuộn lại sao cho điểm 'timeAtMouse' vẫn nằm đúng ở 'mouseX'
|
||||
container.scrollLeft = (timeAtMouse * pixelsPerSecond) - mouseX;
|
||||
}, { passive: false });
|
||||
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📌 Nhắc nhở thêm nếu dùng thư viện:
|
||||
|
||||
* **Nếu bạn dùng Canvas thuần:** Đảm bảo hàm `renderWaveform()` vẽ lại waveform dựa theo `pixelsPerSecond` mới trước khi cập nhật `container.scrollLeft`.
|
||||
* **Nếu bạn đang dùng `wavesurfer.js`:** Thư viện này đã hỗ trợ sẵn logic này, bạn chỉ cần dùng method:
|
||||
```javascript
|
||||
wavesurfer.zoom(newPxPerSec);
|
||||
|
||||
```
|
||||
|
||||
|
||||
*(Nếu WaveSurfer bản cũ bị trôi, bạn áp dụng lại công thức tính `scrollLeft` ở trên sau khi gọi lệnh `zoom()`)*.
|
||||
Reference in New Issue
Block a user