Now.js Framework Documentation

Now.js Framework Documentation

MediaViewer

TH 15 Dec 2025 08:52

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 2

viewer.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;
}

ตัวอย่างการใช้งานจริง

<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);
  });
});
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' }

เอกสารที่เกี่ยวข้อง