Làm chủ OpenSeadragon Bài 3: Cài đặt & Tích hợp cơ bản - Đưa OpenSeadragon vào Vanilla JS và các Framework hiện đại như ReactJS / VueJS.
Chào mừng bạn đến với bài đầu tiên trong series Làm chủ OpenSeadragon [cite: x]. Ở bài viết này, chúng ta sẽ cùng bóc tách những khái niệm cơ bản nhất: Deep Zoom là gì, OpenSeadragon đóng vai trò ra sao trong kiến trúc Frontend, và tại sao đây lại là "cứu cánh" cho các dự án Web phải xử lý hình ảnh chất lượng siêu cao [cite: x].
1. Cài đặt thư viện
Khởi tạo hoặc mở dự án ReactJS của bạn (sử dụng Vite, Create React App hoặc Next.js đều được). Mở terminal và chạy lệnh sau để cài đặt OpenSeadragon [cite: x]:
npm install openseadragon
# hoặc
yarn add openseadragon
2. Chuẩn bị tài nguyên tĩnh (Static Assets)
Trước khi code, bạn cần chú ý hai tài nguyên tĩnh bắt buộc phải có để OSD hoạt động [cite: x]:
- Dữ liệu DZI: Copy file
hinh-goc.dzivà thư mụchinh-goc_files(đã tạo ở Bài 2) vào thư mụcpubliccủa dự án React (ví dụ:public/deepzoom/) [cite: x]. - Bộ icon điều hướng của OSD: OpenSeadragon có sẵn các icon nút bấm (zoom in, zoom out, home, full screen). Bạn cần copy thư mục
imagestừnode_modules/openseadragon/build/openseadragon/images/thả vào thư mụcpublic(ví dụ:public/osd-images/) [cite: x].
3. Xây dựng Component DeepZoomViewer
Tạo một file mới tên là DeepZoomViewer.jsx. Ý tưởng cốt lõi ở đây là tạo một thẻ <div> trống, sau đó dùng useEffect để yêu cầu OSD "bơm" bản vẽ (canvas) của nó vào trong <div> đó [cite: x].
Dưới đây là đoạn code chuẩn nhất để tích hợp [cite: x]:
import React, { useEffect, useRef } from 'react';
import OpenSeadragon from 'openseadragon';
const DeepZoomViewer = () => {
// Sử dụng useRef để lưu trữ instance của viewer, giúp dọn dẹp (cleanup) dễ dàng
const viewerRef = useRef(null);
useEffect(() => {
// Khởi tạo OpenSeadragon
viewerRef.current = OpenSeadragon({
id: 'osd-container', // Trùng với id của thẻ div bên dưới
prefixUrl: '/osd-images/', // Đường dẫn tới thư mục chứa icon điều hướng
tileSources: '/deepzoom/hinh-goc.dzi', // Đường dẫn tới file DZI
// Các tuỳ chọn UI cơ bản
showNavigator: true, // Hiển thị bản đồ mini (minimap) ở góc
navigatorPosition: 'BOTTOM_RIGHT',
animationTime: 0.5, // Tốc độ hiệu ứng zoom/pan (giây)
blendTime: 0.1, // Thời gian mờ dần khi load các mảnh ảnh mới
constrainDuringPan: true, // Không cho phép người dùng kéo ảnh ra ngoài khu vực xem
maxZoomPixelRatio: 2, // Giới hạn mức độ zoom tối đa
});
// Cleanup function: Hủy instance khi component bị unmount
return () => {
if (viewerRef.current) {
viewerRef.current.destroy();
viewerRef.current = null;
}
};
}, []); // Cấp dependency rỗng để chỉ chạy 1 lần khi mount
return (
<div
id="osd-container"
style={{ width: '100%', height: '800px', backgroundColor: '#000' }}
/>
);
};
export default DeepZoomViewer;
4. Giải thích các Cấu hình (Configuration) quan trọng
Trong đoạn code trên, object truyền vào OpenSeadragon({...}) chính là trái tim của hệ thống. Dưới đây là các keys quan trọng nhất bạn cần hiểu [cite: x]:
id: Chuỗi ID của thẻ HTML mà OSD sẽ render vào. Yêu cầu thẻ này bắt buộc phải có thông sốwidthvàheightcụ thể (có thể dùngpx,vh, hoặc%) [cite: x].prefixUrl: OSD dùng đường dẫn này để nối với tên các file ảnh icon (nhưzoomin_rest.png). Nếu bạn thấy các nút bấm bị lỗi (icon vỡ), chắc chắn 100% là cấu hình này đang trỏ sai thư mục [cite: x].tileSources: Dữ liệu đầu vào. Nó có thể là URL trỏ tới file.dzitrên server của bạn, hoặc thậm chí là URL từ một server khác (nếu server đó đã mở CORS) [cite: x].showNavigator: Mở tính năng Minimap (Bản đồ nhỏ). Rất hữu ích khi bức ảnh quá khổng lồ và người dùng cần biết mình đang đứng ở góc nào của bức tranh [cite: x].constrainDuringPan: Nếu đặt làfalse, người dùng có thể kéo bức ảnh bay mất khỏi màn hình (chỉ còn lại nền đen). Đặt làtruesẽ khóa ảnh lại trong giới hạn của khung nhìn [cite: x].
5. Lưu ý "Tử Huyệt" với React 18 Strict Mode
Nếu bạn dùng React 18 ở chế độ StrictMode (chế độ mặc định khi tạo app mới), React sẽ cố tình render useEffect 2 lần trong môi trường Development để giúp bạn tìm bug [cite: x].
Nếu bạn quên viết hàm dọn dẹp (return () => viewerRef.current.destroy()) trong useEffect, OpenSeadragon sẽ tạo ra hai cái viewer chồng đè lên nhau trong cùng một thẻ div. Các nút bấm sẽ bị nhân đôi và việc điều khiển zoom sẽ bị loạn [cite: x].
Đoạn code trong phần 3 đã xử lý triệt để vấn đề này bằng hàm destroy(), đảm bảo instance cũ luôn bị tiêu hủy trước khi instance mới (nếu có) được tạo ra [cite: x].
All rights reserved