หลายคนคงเคยเล่น Google Gravity (ที่หน้าเว็บตกลงมากองข้างล่าง) หรือ Google Antigravity (ที่หน้าเว็บลอยเคว้งคว้างเหมือนอยู่ในอวกาศ) ซึ่งเป็น “Easter Egg” สุดคลาสสิก แม้มันจะดูเหมือนการจำลองฟิสิกส์ที่ซับซ้อน แต่ในมุมของนักเขียนโค้ด นี่คือผลงานระดับมาสเตอร์พีซของการใช้ JavaScript เพื่อควบคุม DOM Elements ได้อย่างน่าทึ่ง
วันนี้เราจะไม่คุยเรื่องสูตรฟิสิกส์ แต่เราจะมาคุยกันว่า “เขาเขียนโค้ดยังไงให้หน้าเว็บพังได้แบบนั้น?”
1. จุดเริ่มต้น: ไม่ใช่ Google ทำเองทั้งหมด
โปรเจกต์นี้ไม่ได้ถูกสร้างโดยวิศวกรหลักของ Google โดยตรง แต่เป็นผลงานของ Ricardo Cabello หรือที่รู้จักในวงการว่า “Mr. Doob” (ผู้สร้าง Three.js อันโด่งดัง)
ในยุคที่สร้าง Google Gravity (ประมาณปี 2009-2010) เว็บไซต์ส่วนใหญ่ยังนิ่งสนิท (Static) การทำให้ Element บนหน้าเว็บขยับชนกันได้แบบ Real-time บน Browser จึงเป็นเรื่องที่ “ล้ำ” มากในยุคนั้น
2. หัวใจสำคัญ: Physics Engine (Box2D)
เบื้องหลังการร่วงหล่น การกระเด้ง และการชนกัน ไม่ได้เกิดจากการเขียน if-else ธรรมดา แต่เป็นการใช้ Physics Engine
โค้ดชุดนี้ใช้ไลบรารีที่ชื่อว่า Box2DJS (ซึ่งพอร์ตมาจาก Box2D ของ C++ ที่ใช้ในเกม Angry Birds)
หลักการทำงานในมุมโค้ด:
- World Creation: โค้ดจะสร้าง “โลกจำลอง” (World) ขึ้นมาในตัวแปร JavaScript ซึ่งโลกนี้จะมีค่าแรงโน้มถ่วง (Gravity Vector)
- Google Gravity: ตั้งค่า Vector แรงโน้มถ่วงเป็นแกน Y ลงด้านล่าง
- Google Antigravity: ตั้งค่า Vector เป็น 0 หรือติดลบ ทำให้วัตถุลอย
- Mapping DOM to Body: นี่คือส่วนที่ยากที่สุด โค้ดจะวนลูปหา HTML Elements ทุกตัว (โลโก้, ช่องค้นหา, ปุ่ม) แล้วสร้างกรอบสี่เหลี่ยมที่มองไม่เห็น (Collision Box) ในโลกฟิสิกส์ให้มีขนาดเท่ากับ Element นั้นๆ
- Simulation Loop: ใช้ฟังก์ชันจำพวก
setIntervalหรือrequestAnimationFrameเพื่อคำนวณตำแหน่งใหม่ทุกๆ เสี้ยววินาที
3. เมื่อ HTML กลายเป็นวัตถุ (Rigid Bodies)
ปกติแล้ว HTML Element (<div>, <img>, <input>) จะถูกวางตำแหน่งโดย CSS (Static หรือ Relative) แต่เมื่อสคริปต์ Antigravity ทำงาน มันจะเปลี่ยนสถานะของ Element เหล่านั้น:
- CSS Position: ถูกเปลี่ยนเป็น
absoluteทั้งหมด - Coordinate System: โปรแกรมจะดึงค่าพิกัด (X, Y) และองศาการหมุน (Rotation) จาก Physics Engine มายัดใส่ใน CSS
top,leftและtransform: rotate(...)ของ Element นั้นๆ
ตัวอย่าง Logic (Pseudocode):
JavaScript
function update() {
// 1. คำนวณฟิสิกส์ 1 เฟรม (การชน, ความเร็ว)
world.Step(1 / 60, 10, 10);
// 2. วนลูปทุกวัตถุในหน้าเว็บ
for (let body = world.GetBodyList(); body; body = body.GetNext()) {
// ดึง Element HTML ที่ผูกไว้กับวัตถุนี้
let element = body.GetUserData();
if (element) {
// 3. อัปเดตตำแหน่ง CSS ตามค่าที่คำนวณได้จาก Physics Engine
let position = body.GetPosition();
let angle = body.GetAngle();
element.style.left = position.x + 'px';
element.style.top = position.y + 'px';
element.style.transform = 'rotate(' + angle + 'rad)';
}
}
}
4. ความแตกต่างระหว่าง Gravity และ Antigravity
ในเชิง Coding ทั้งสองเวอร์ชันคือ Code Base เดียวกัน 99% สิ่งที่ต่างกันคือการตั้งค่าตัวแปรเริ่มต้น (Configuration):
- Google Gravity:JavaScript
// แรงดึงดูดลงด้านล่าง (แกน Y เป็นบวก) world.SetGravity(new b2Vec2(0, 10.0));เมื่อเมาส์ไปลากวัตถุแล้วปล่อย วัตถุจะตกลงพื้นตามปกติ - Google Antigravity:JavaScript
// ไม่มีแรงดึงดูด (Zero Gravity) world.SetGravity(new b2Vec2(0, 0));เมื่อค่าแรงโน้มถ่วงเป็น 0 วัตถุจะไม่มีน้ำหนัก เมื่อเราเอาเมาส์ไป “ชน” หรือ “ลาก” มัน มันจะลอยไปเรื่อยๆ จนกว่าจะชนขอบหน้าจอ (Wall) ตามกฎข้อที่ 1 ของนิวตัน (ซึ่ง Box2D คำนวณให้เอง)
5. การตรวจจับเมาส์ (Mouse Interaction)
ความสนุกของ Antigravity คือเราสามารถ “เหวี่ยง” โลโก้ Google ได้ เทคนิคที่ใช้คือ:
- Mouse Joint: เมื่อเราคลิกเมาส์ค้างไว้ โค้ดจะสร้าง “จุดเชื่อม” (Joint) ระหว่างเมาส์กับวัตถุนั้น
- Force Application: เมื่อเราขยับเมาส์ มันจะส่งแรง (Force) ไปยังวัตถุให้เคลื่อนที่ตาม
- Release: เมื่อปล่อยเมาส์ Joint จะถูกทำลาย แต่วัตถุยังคงมี “โมเมนตัม” (ค่า Velocity ที่ค้างอยู่) ทำให้มันลอยกระเด็นออกไป
บทสรุป: แรงบันดาลใจสู่นักพัฒนาเว็บรุ่นใหม่
Google Antigravity สอนให้รู้ว่า “หน้าเว็บไม่จำเป็นต้องน่าเบื่อ”
ในยุคปัจจุบัน หากคุณอยากลองเขียนอะไรแบบนี้ เราไม่ต้องใช้ Box2DJS เวอร์ชันเก่าแล้ว เรามี Library สมัยใหม่อย่าง Matter.js หรือ Cannon.js ที่เขียนง่ายกว่ามาก แต่หลักการยังคงเดิม คือการผสาน HTML DOM เข้ากับ Physics Mathematics
การทดลองเล่นๆ ของ Mr. Doob ในวันนั้น ได้กลายเป็นแรงบันดาลใจให้นักพัฒนาเว็บไซต์ทั่วโลกกล้าที่จะฉีกกฎการวาง Layout แบบเดิมๆ และใส่ความคิดสร้างสรรค์ลงไปในทุกบรรทัดของโค้ด



