Now.js Framework Documentation
MediaViewer
MediaViewer
ภาพรวม
MediaViewer คือ component สำหรับแสดง media (images, videos, YouTube) แบบ slideshow ใน Now.js Framework รองรับ zoom, fullscreen และ touch gestures
ใช้เมื่อ:
- ต้องการ image gallery/lightbox
- ต้องการ video player
- ต้องการ slideshow
- ต้องการ media preview
ทำไมต้องใช้:
- ✅ Multiple media types (image, video, YouTube)
- ✅ Slideshow with thumbnails
- ✅ Zoom และ pan
- ✅ Touch gestures (swipe)
- ✅ Keyboard controls
- ✅ Fullscreen support
- ✅ Accessibility (ARIA)
การใช้งานพื้นฐาน
HTML Declarative
<div data-component="media-viewer">
<img src="/images/photo1.jpg" alt="Photo 1">
<img src="/images/photo2.jpg" alt="Photo 2">
<img src="/images/photo3.jpg" alt="Photo 3">
</div>With Mixed Media
<div data-component="media-viewer">
<img src="/images/photo.jpg" alt="Photo">
<video src="/videos/clip.mp4"></video>
<div data-youtube="dQw4w9WgXcQ"></div>
</div>JavaScript API
const viewer = new MediaViewer({
items: [
{ type: 'image', src: '/photo1.jpg', caption: 'Photo 1' },
{ type: 'image', src: '/photo2.jpg', caption: 'Photo 2' },
{ type: 'video', src: '/video.mp4', caption: 'Video' },
{ type: 'youtube', videoId: 'dQw4w9WgXcQ', caption: 'YouTube' }
],
showThumbnails: true,
loop: true
});
viewer.show();Media Item Types
| Type | Properties |
|---|---|
image |
src, caption, alt |
video |
src, caption, poster |
youtube |
videoId, caption |
iframe |
src, caption |
html |
content, caption |
Options
new MediaViewer({
// Media items array
items: [],
// Show thumbnail strip
showThumbnails: true,
// Loop slideshow
loop: true,
// Enable zoom on images
enableZoom: true,
// Auto-play slideshow
autoPlay: false,
autoPlayInterval: 5000,
// Show controls
showNavigation: true,
showCounter: true,
showCaption: true,
// Keyboard shortcuts
keyboard: true,
// Close on backdrop click
closeOnBackdrop: true,
// Callbacks
onOpen: () => {},
onClose: () => {},
onChange: (index) => {}
});API อ้างอิง
new MediaViewer(options)
สร้าง MediaViewer instance
Returns: MediaViewer
viewer.show(items?, startIndex?)
แสดง viewer
| Parameter | Type | Description |
|---|---|---|
items |
array | Media items (optional) |
startIndex |
number | Starting index (default: 0) |
viewer.show();
viewer.show(items, 2); // Start at index 2viewer.hide()
ซ่อน viewer
viewer.next()
ไปรูปถัดไป
viewer.prev()
ไปรูปก่อนหน้า
viewer.goTo(index)
ไปยัง index ที่กำหนด
viewer.play()
เริ่ม slideshow
viewer.stop()
หยุด slideshow
Keyboard Shortcuts
| Key | Action |
|---|---|
→ |
Next item |
← |
Previous item |
Space |
Play/Pause slideshow |
Escape |
Close viewer |
+ / = |
Zoom in |
- |
Zoom out |
0 |
Reset zoom |
F |
Toggle fullscreen |
Touch Gestures
| Gesture | Action |
|---|---|
| Swipe Left | Next item |
| Swipe Right | Previous item |
| Pinch | Zoom |
| Double-tap | Toggle zoom |
| Swipe Down | Close viewer |
การจัดรูปแบบ CSS
/* Viewer container */
.media-viewer {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.95);
z-index: 9999;
display: flex;
flex-direction: column;
}
.media-viewer-content {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
/* Main media */
.media-viewer-main img,
.media-viewer-main video {
max-width: 90%;
max-height: 80vh;
object-fit: contain;
}
/* Navigation */
.media-viewer-nav {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255,255,255,0.1);
color: white;
border: none;
padding: 16px;
cursor: pointer;
}
.media-viewer-prev { left: 16px; }
.media-viewer-next { right: 16px; }
/* Thumbnails */
.media-viewer-thumbnails {
display: flex;
gap: 8px;
padding: 16px;
overflow-x: auto;
justify-content: center;
}
.media-viewer-thumb {
width: 60px;
height: 60px;
object-fit: cover;
opacity: 0.5;
cursor: pointer;
}
.media-viewer-thumb.active {
opacity: 1;
outline: 2px solid white;
}
/* Caption */
.media-viewer-caption {
text-align: center;
color: white;
padding: 16px;
}
/* Close button */
.media-viewer-close {
position: absolute;
top: 16px;
right: 16px;
background: none;
border: none;
color: white;
font-size: 24px;
cursor: pointer;
}ตัวอย่างการใช้งานจริง
Product Gallery
<div class="product-gallery">
<div class="main-image" id="main-image">
<img src="/products/shoe-1.jpg" alt="Main">
</div>
<div class="thumbnails" data-component="media-viewer">
<img src="/products/shoe-1.jpg" alt="View 1">
<img src="/products/shoe-2.jpg" alt="View 2">
<img src="/products/shoe-3.jpg" alt="View 3">
<video src="/products/shoe-video.mp4" poster="/products/shoe-poster.jpg"></video>
</div>
</div>Photo Album
// Open viewer from grid
document.querySelectorAll('.photo-grid img').forEach((img, index) => {
img.addEventListener('click', () => {
const items = Array.from(document.querySelectorAll('.photo-grid img')).map(img => ({
type: 'image',
src: img.src.replace('thumb', 'full'),
caption: img.alt
}));
const viewer = new MediaViewer({ items });
viewer.show(null, index);
});
});Video Gallery with YouTube
const videos = [
{ type: 'youtube', videoId: 'video1', caption: 'Tutorial Part 1' },
{ type: 'youtube', videoId: 'video2', caption: 'Tutorial Part 2' },
{ type: 'video', src: '/local-video.mp4', caption: 'Demo' }
];
const viewer = new MediaViewer({
items: videos,
showThumbnails: true
});
document.getElementById('watch-btn').onclick = () => viewer.show();ข้อควรระวัง
⚠️ 1. YouTube Video ID
// ❌ Full URL
{ type: 'youtube', videoId: 'https://youtube.com/watch?v=abc123' }
// ✅ Video ID เท่านั้น
{ type: 'youtube', videoId: 'abc123' }⚠️ 2. Image Paths
// ❌ Relative to current page
{ type: 'image', src: 'photo.jpg' }
// ✅ Absolute หรือ from root
{ type: 'image', src: '/images/photo.jpg' }เอกสารที่เกี่ยวข้อง
- BackdropManager - Backdrops
- AnimationManager - Animations