Now.js Framework Documentation
ImageGallery
ImageGallery
ภาพรวม
ImageGallery คือ component แสดงภาพแบบ inline ใน Now.js Framework แสดงภาพหลัก (hero) พร้อม thumbnail strip ด้านล่าง และเปิด fullscreen lightbox ผ่าน MediaViewer เมื่อผู้ใช้กดที่ภาพ
ใช้เมื่อ:
- แสดงภาพสินค้า หรือชิ้นส่วนภายใน card หรือ modal
- แสดงชุดภาพในฟอร์ม หรือ loop ของ TemplateManager (
data-for) - ทุกที่ที่ต้องการให้ดูภาพหลายรูปได้โดยไม่ต้องออกจากหน้า
ทำไมต้องใช้:
- ✅ Declarative เต็มรูปแบบ — เขียนแค่ HTML ไม่ต้องเขียน JS เพิ่ม
- ✅ Auto-init ผ่าน ComponentManager (ทำงานใน template, modal, content ที่โหลดจาก API)
- ✅ เลือก effect ได้ (fade, slide, none)
- ✅ เลือกตำแหน่ง thumbnail ได้ (bottom, left, right, top)
- ✅ Fullscreen zoom ผ่าน MediaViewer (swipe, pinch, keyboard)
- ✅ รองรับ REST API (
data-api) - ✅ Touch swipe เพื่อเปลี่ยนรูป
- ✅ Keyboard navigation (← / →)
- ✅ Responsive ด้วย container queries
- ✅ Accessible (ARIA labels, focus management)
การใช้งานพื้นฐาน
HTML Declarative
<div data-component="image-gallery">
<img src="/images/photo1.jpg" alt="ด้านหน้า" data-caption="ด้านหน้า">
<img src="/images/photo2.jpg" alt="ด้านข้าง" data-caption="ด้านข้าง">
</div>รูปเต็ม vs รูปย่อ (thumbnail)
ใช้ data-src สำหรับรูปขนาดเต็ม ส่วน src ใช้แสดงเป็น thumbnail
ถ้าไม่ระบุ data-src จะใช้ src ทั้งสองอย่าง
<div data-component="image-gallery">
<img src="/thumbs/photo1_sm.jpg" data-src="/images/photo1.jpg" alt="ภาพ 1" data-caption="ภาพ 1">
<img src="/thumbs/photo2_sm.jpg" data-src="/images/photo2.jpg" alt="ภาพ 2">
</div>Transition effect
<!-- Fade (ค่าเริ่มต้น) -->
<div data-component="image-gallery" data-effect="fade">...</div>
<!-- Slide -->
<div data-component="image-gallery" data-effect="slide">...</div>
<!-- ไม่มี animation -->
<div data-component="image-gallery" data-effect="none">...</div>Aspect ratio
<!-- สี่เหลี่ยมจัตุรัส (1:1) -->
<div data-component="image-gallery" data-aspect="square">...</div>
<!-- กว้าง (16:9) -->
<div data-component="image-gallery" data-aspect="wide">...</div>
<!-- สูง (3:4) -->
<div data-component="image-gallery" data-aspect="tall">...</div>
<!-- อัตโนมัติตามภาพจริง — ค่าเริ่มต้น -->
<div data-component="image-gallery" data-aspect="auto">...</div>ตำแหน่ง thumbnail
<!-- ด้านล่าง (ค่าเริ่มต้น) -->
<div data-component="image-gallery" data-thumbnails-position="bottom">...</div>
<!-- ด้านซ้าย -->
<div data-component="image-gallery" data-thumbnails-position="left">...</div>
<!-- ด้านขวา -->
<div data-component="image-gallery" data-thumbnails-position="right">...</div>
<!-- ด้านบน -->
<div data-component="image-gallery" data-thumbnails-position="top">...</div>ซ่อน thumbnail
Thumbnail จะแสดงอัตโนมัติเมื่อมีภาพ 2 รูปขึ้นไป
ใช้ data-show-thumbnails="false" เพื่อซ่อนเสมอ
<div data-component="image-gallery" data-show-thumbnails="false">
<img src="/images/hero.jpg" alt="ภาพหลัก">
</div>ปิด fullscreen zoom
<div data-component="image-gallery" data-enable-zoom="false">...</div>โหลดภาพจาก REST API
โหลดรายการภาพจาก API endpoint component จะแสดง loading indicator ระหว่างดึงข้อมูล
<div data-component="image-gallery" data-api="api/parts/images?id=5"></div><!-- POST endpoint -->
<div data-component="image-gallery"
data-api="api/products/gallery"
data-api-method="POST">
</div>รูปแบบ response ที่รองรับ
API สามารถตอบกลับได้หลายรูปแบบ:
["url1.jpg", "url2.jpg"][
{ "url": "photo1.jpg", "alt": "ด้านหน้า", "caption": "ด้านหน้า" },
{ "url": "photo2.jpg", "thumb": "photo2_sm.jpg", "alt": "ด้านข้าง" }
]{ "data": [ ... ] }{ "items": [ ... ] }Field ที่รองรับ: url / src / path, thumb / thumbnail, alt, caption / title
ใช้กับ TemplateManager
ทำงานภายใน loop data-for ได้ ComponentManager จะ auto-init แต่ละ gallery หลังจาก TemplateManager render เสร็จ
ภาพเดียวต่อ card
<div data-for="item in results">
<div class="product-card">
<div data-component="image-gallery" data-aspect="square" data-show-thumbnails="false">
<img data-attr="src:item.image;alt:item.name" data-if="item.image" loading="lazy">
</div>
<div data-text="item.name"></div>
</div>
</div>หลายภาพต่อ item
เมื่อ API ส่ง item.images[] ใช้ data-for บน <img> โดยตรง:
<div data-component="image-gallery" data-effect="fade">
<img data-for="img in item.images"
data-attr="src:img.url;alt:img.alt"
data-attr-extra="data-caption:img.caption"
loading="lazy">
</div>ใช้ใน Modal / ResponseHandler
เมื่อเซิร์ฟเวอร์ส่ง HTML ที่มี data-component="image-gallery" กลับมาผ่าน action.html,Modal.setContent() จะ inject HTML เข้า DOM และ CoreObserver จะ triggerComponentManager อัตโนมัติ — ไม่ต้องเขียน JS เพิ่ม
PHP (Kotchasan controller)
// สร้าง HTML จาก images array ที่ได้จาก model
$imgTags = '';
foreach ($part->images as $i => $img) {
$url = htmlspecialchars($img['url']);
$imgTags .= '<img src="'.$url.'" data-src="'.$url.'" alt="'.htmlspecialchars($part->name).'">';
}
$html = '<div data-component="image-gallery" data-effect="fade" '
. 'data-aspect="auto" data-thumbnails-position="bottom" '
. 'data-show-thumbnails="true" data-enable-zoom="true">'
. $imgTags
. '</div>';
// ส่งกลับเป็น modal action
$this->sendSuccess(['html' => $html, ...]);Programmatic API
ใช้ ImageGallery.create() เมื่อต้องสร้าง gallery จาก JavaScript ล้วนๆ
const gallery = ImageGallery.create(element, {
images: [
{ url: '/images/photo1.jpg', thumb: '/thumbs/photo1.jpg', alt: 'ภาพ 1', caption: 'ภาพ 1' },
{ url: '/images/photo2.jpg', alt: 'ภาพ 2' }
],
effect: 'slide',
aspect: 'wide',
thumbnailsPosition: 'bottom',
enableZoom: true
});
// ไปยังภาพที่ต้องการ
gallery.goTo(1);
// เปลี่ยนชุดภาพทั้งหมด
gallery.update(newImages);
// ลบ gallery และ cleanup event
gallery.destroy();Data Attributes อ้างอิง
| Attribute | ค่าที่รองรับ | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-effect |
fade | slide | none |
fade |
Effect ตอนเปลี่ยนภาพ |
data-aspect |
square | wide | tall | auto |
auto |
Aspect ratio ของ hero |
data-show-thumbnails |
true | false |
true |
แสดง thumbnail strip (ซ่อนอัตโนมัติเมื่อมีภาพ ≤ 1 รูป) |
data-thumbnails-position |
bottom | left | right | top |
bottom |
ตำแหน่ง thumbnail strip |
data-enable-zoom |
true | false |
true |
เปิด fullscreen zoom ผ่าน MediaViewer |
data-empty-icon |
CSS icon class | icon-picture |
Icon แสดงเมื่อไม่มีภาพ |
data-api |
URL | — | REST API endpoint สำหรับโหลดภาพ |
data-api-method |
GET | POST |
GET |
HTTP method สำหรับเรียก API |
<img> Attributes อ้างอิง
| Attribute | คำอธิบาย |
|---|---|
src |
URL รูป thumbnail (แสดงใน thumbnail strip) |
data-src |
URL รูปขนาดเต็ม (ใช้ใน fullscreen viewer) ถ้าไม่ระบุจะใช้ src แทน |
alt |
Alt text สำหรับ accessibility |
data-caption |
คำอธิบายที่แสดงใต้ภาพหลัก ถ้าไม่ระบุจะใช้ alt แทน |
Programmatic API อ้างอิง
ImageGallery.create(element, options)
สร้าง gallery บน element ด้วย JavaScript
| Parameter | Type | คำอธิบาย |
|---|---|---|
element |
HTMLElement |
Element ที่ต้องการใช้เป็น container |
options.images |
Array |
Array ของ image objects |
options.effect |
string |
fade | slide | none |
options.aspect |
string |
square | wide | tall | auto |
options.showThumbnails |
boolean |
แสดง thumbnail strip |
options.thumbnailsPosition |
string |
bottom | left | right | top |
options.enableZoom |
boolean |
เปิด fullscreen viewer |
options.emptyIcon |
string |
CSS class สำหรับ icon ตอนไม่มีภาพ |
คืนค่า object ที่มี:
| Method | คำอธิบาย |
|---|---|
goTo(index) |
ไปยังภาพที่ index ที่ระบุ |
update(newItems) |
เปลี่ยนชุดภาพทั้งหมดและ rebuild |
destroy() |
ลบ event listeners และ cleanup |
Keyboard & Touch Controls
| การควบคุม | การทำงาน |
|---|---|
← / → |
ภาพก่อนหน้า / ถัดไป (เมื่อ gallery หรือ child มี focus) |
| คลิก / แตะภาพ | เปิด fullscreen MediaViewer |
| ปุ่ม zoom (hover) | เปิด fullscreen MediaViewer |
| Swipe ซ้าย / ขวา | ภาพถัดไป / ก่อนหน้า |
CSS Classes อ้างอิง
| Class | คำอธิบาย |
|---|---|
.ig |
Root element |
.ig--fade / .ig--slide / .ig--none |
Effect modifier ที่ active อยู่ |
.ig--square / .ig--wide / .ig--tall / .ig--auto |
Aspect ratio modifier |
.ig--bottom / .ig--left / .ig--right / .ig--top |
ตำแหน่ง thumbnail ที่ active อยู่ |
.ig-hero |
Container ของภาพหลัก |
.ig-main-img |
<img> ที่กำลังแสดงอยู่ |
.ig-zoom-btn |
ปุ่ม fullscreen zoom (แสดงเมื่อ hover) |
.ig-caption |
ข้อความคำอธิบายใต้ภาพหลัก |
.ig-thumbs |
Container ของ thumbnail strip |
.ig-thumb |
ปุ่ม thumbnail แต่ละรูป |
.ig-thumb.is-active |
Thumbnail ของภาพที่กำลังดูอยู่ |
.ig-empty |
Modifier เมื่อไม่มีภาพ |
.ig-loading |
Modifier ระหว่างโหลดจาก API |
การทำงานร่วมกับ MediaViewer
เมื่อ data-enable-zoom="true" (ค่าเริ่มต้น) การคลิกที่ hero หรือปุ่ม zoom จะเรียกMediaViewer.show() โดยส่งภาพทั้งหมดเริ่มจาก index ที่กำลังดูอยู่MediaViewer จะให้ฟีเจอร์ zoom, pan, keyboard, touch และ autoplay สำหรับมุมมอง fullscreen
MediaViewer ถูกโหลดอัตโนมัติเป็นส่วนหนึ่งของ core bundle
ดูเพิ่มเติม
- MediaViewer — Fullscreen lightbox ที่ใช้โดย ImageGallery
- ComponentManager — จัดการ lifecycle auto-init
- TemplateManager —
data-for,data-if,data-attrdirectives