สำหรับโทรศัพท์ หรือ แท็บเล็ต เท่านั้น
ในหลายโปรเจกต์ของ Google Apps Script (GAS) ที่เกี่ยวกับการถ่ายรูป เช่น ระบบลงทะเบียน, ระบบบัตรนักเรียน หรือระบบอัปโหลดภาพผ่านมือถือ มักพบปัญหาสำคัญคือ
❌ “เปิดกล้องไม่ได้” หรือ preview ภาพไม่ทำงานบนมือถือบางเครื่อง
❌ Crop รูปแล้วตำแหน่งเพี้ยน
❌ ระบบอัปโหลดทำงานไม่เสถียร
บทความนี้จะอธิบายแนวทางแก้ปัญหาแบบครบระบบ โดยใช้เทคนิค:
- 📷 HTML5 file input + capture camera
- ✂️ Cropper.js แบบ fixed ratio
- 🧠 face-api.js สำหรับ auto center face
- 🚀 Google Apps Script สำหรับ upload + Google Drive
🚨 ปัญหาที่พบบ่อยใน GAS Camera App
1. กล้องไม่เปิดในบาง browser
เกิดจาก:
-
ใช้
<video getUserMedia>ใน GAS web app - Permission policy ของ iframe
2. Crop แล้วตำแหน่งภาพผิด
เกิดจาก:
- scale image ไม่ตรงกับ natural size
- ใช้ cropper.setData โดยไม่ map resolution
3. upload แล้ว preview ค้าง / ซ้ำ
เกิดจาก:
- ไม่ clear objectURL
- ไม่ reset state หลัง upload
💡 แนวทางแก้แบบมืออาชีพ (ที่ใช้ได้จริง)
✅ 1. ใช้ file input + capture แทน getUserMedia
<input id="camera" type="file" accept="image/*" capture="environment" hidden>
✔ ข้อดี
- ใช้ได้ใน GAS Web App
- ไม่ติด iframe security
- ใช้กล้องมือถือได้ทันที
✂️ 2. Cropper.js แบบ Fixed Ratio (เช่น 1:1 บัตรนักเรียน)
cropper = new Cropper(img, {
aspectRatio: 1,
viewMode: 2,
autoCropArea: 1,
movable: true,
zoomable: true
});
✔ ผลลัพธ์
- ได้ภาพขนาดมาตรฐาน
- เหมาะกับบัตรนักเรียน / โปรไฟล์
🧠 3. Auto Face Center Crop ด้วย face-api.js
const detection = await faceapi.detectSingleFace(
img,
new faceapi.TinyFaceDetectorOptions()
);
🔥 แนวคิด
ระบบจะ:
- ตรวจใบหน้าอัตโนมัติ
- คำนวณ center
- ปรับ crop box ให้พอดีใบหน้า
const centerX = (box.x + box.width / 2) * scale;
const centerY = (box.y + box.height / 2) * scale;
🚀 4. ปรับ Crop ให้สมจริง (Smart Padding)
const size = Math.max(box.width, box.height) * 1.8 * scale;
✔ ทำให้:
- ไม่ตัดหัว
- ได้เฟรมสวยเหมือนถ่ายสตูดิโอ
☁️ 5. Upload ไป Google Drive + บันทึก Sheet
const file = DriveApp.getFolderById(FOLDER_ID)
.createFile(blob);
sheet.appendRow([
new Date(),
file.getId(),
file.getUrl()
]);
🔄 6. Reset UI หลัง Upload (สำคัญมาก)
img.src = "";
img.style.display = "none";
cropper.destroy();
croppedBlob = null;
✔ ผลลัพธ์
- ไม่มี cache ค้าง
- ใช้งานต่อเนื่องได้ลื่น
- ไม่เกิด bug ซ้ำภาพ
⚡ เทคนิค Performance ที่ช่วยให้ลื่นขึ้น
✔ delay ก่อน detect face
await new Promise(r => setTimeout(r, 100));
✔ revoke object URL ป้องกัน memory leak
URL.revokeObjectURL(oldUrl);
✔ disable upload button จน crop เสร็จ
uploadBtn.disabled = true;
🎯 สรุป
การแก้ปัญหา “GAS บล็อกกล้อง + crop + upload” ให้เสถียร ต้องออกแบบระบบใหม่ 3 ชั้น:
🟢 ชั้นที่ 1: Input Layer
- ใช้ file input + capture แทน webcam API
🟡 ชั้นที่ 2: Processing Layer
- Cropper.js fixed ratio
- face-api.js auto center
🔵 ชั้นที่ 3: Storage Layer
- Google Drive upload
- Google Sheet logging
🚀 ผลลัพธ์ที่ได้จากระบบนี้
✔ ใช้ได้บนมือถือ 100%
✔ ไม่โดน GAS block camera
✔ crop อัตโนมัติแม่นยำ
✔ ได้ภาพบัตรมาตรฐาน
✔ upload เสถียรไม่ค้าง
✔ พร้อมใช้ production

