เนื้อหานี้จะเป็นโค้ดตัวอย่าง อย่างง่ายเป็นแนวทาง และเป็นการเรียนรู้เกี่ยวกับ
การใช้งาน jQuery ในการกำหนดการทำการเคลื่อนไหว หรือ animation เบื้องต้น
สำหรับการย้ายตำแหน่ง
รูปแบบการทำงาน
เราจะสร้างพื้นที่มาหนึ่งพื้นที่ ที่ให้เราสามารถกำหนดการคลิก แล้วให้ div ที่เรากำหนด
ย้ายตำแหน่งไปยังจุดที่เราคลิก เข้าใจอย่างง่ายก็คือ คลิกตรงไหน กล่อง div ก็จะย้ายมาอยู่ที่
ตรงตำแหน่งนั้นๆ
สิ่งที่จะได้เรียนรู้จากตัวอย่าง
เราจะรู้ว่า เมื่อคลิกที่ตำแหน่งใดๆ ในพื้นที่ๆ กำหนด เราสามารถกำหนด event เพื่อทำคำสั่งที่ต้องการได้
เมื่อเราคลิกไปที่ตำแหน่งหนึ่ง จะมีค่า event object ที่มีค่า property ต่างๆ ที่เราสามารถนำไปใช้งานได้มากมาย
เช่น ตำแหน่งเมาส์ ตัว div หรือ element เป้าหมายที่เราคลิก เป็นต้น จะได้รู้เกี่ยวกับการใช้คำสั่งของ jQuery
เช่น การตรวจสอบว่าตัวที่คลิกเป็นตัวที่เราต้องการหรือไม่ การทำการเคลื่อนไหวด้วยคำสั่งง่ายๆ เป็นต้น
ไฟล์ตัวอย่าง demo.html
ดูการทำงานที่ตัวอย่าง demo ด้านล่าง
<!doctype html> <html lang="th"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>Document</title> <link rel="stylesheet" href="https://unpkg.com/bootstrap@4.5.0/dist/css/bootstrap.min.css" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" > <style> body{ background: #CCCCCC; } </style> </head> <body> <style> .click-zone{ height: 600px; background-color: antiquewhite; } .red-box{ width: 100px; height: 100px; background: rgb(204, 22, 61); } </style> <div class="container mt-5 mx-auto"> <div class="click-zone"> <div class="red-box"></div> </div> </div> <script src="https://unpkg.com/jquery@3.3.1/dist/jquery.min.js"></script> <script type="text/javascript"> jQuery(document).ready(function($) { // ตัวแปรกำหนด element หกักเพื่อให้เรียกใช้ง่ายขึ้น var moveItem = $(".red-box"); var zoneArea = $(".click-zone"); $(document.body).on("click",".click-zone",function(e){ // ตัวที่คลิกโดนมีตัวอื่นมาทับ หรืออยู่ด้านบน // ใช้การตรวจสอบ เป้าหมายถ้าไม่มีคลาสตามที่กำหนด ไม่ต้องทำงาน if(!$(e.target).hasClass('click-zone')){ return false; // ไม่ทำคำสั่งใดๆ } // ค่าต่างๆ ที่จะนำไปใช้ // ตัวอย่างอิงตำแหน่งของกล่อง let itemOffset = moveItem.offset(); // กล่อง let itemWidth = moveItem.width(); let itemHeight = moveItem.height(); // พื้นที่ let zoneWidth = zoneArea.width(); let zoneHeight = zoneArea.height(); // ค่านี้เราจะรู้ทั้งหมดว่า event object มีอะไรบ้าง console.log(e); // ค่าที่ควรรู้ไว้ // console.log($(e.target)); // ตัวที่คลิกโดนก่อน อยู่บนสุด // console.log($(e.currentTarget)); // ตัวที่เรากำหนดเป็นพื้นที่คลิก // ตำแหน่งเมาส์เทียบกับส่วนแสดงผล รวม scroll ค่า page // console.log(e.pageX); // console.log(e.pageY); // ตำแหน่งเมาส์เทียบกับส่วนแสดงผล ไม่รวม scroll ค่า client // console.log(e.clientX); // console.log(e.clientY); // ตำแหน่งเมาส์ เทียบกับพ้ืนที่ที่คลิก ค่า offset // console.log(e.offsetX); // console.log(e.offsetY); // ตำแหน่งเมาส์ เทียบกับหน้าจอ screen // console.log(e.screenX); // console.log(e.screenY); // ใช้ค่าตำแหน่งจากการอ้างอิง page let locateX = e.pageX; let locateY = e.pageY; // คำนวณการ กำหนดตำแหน่ง ไม่ให้กล่องออกจากพื้นที่ locateX = ((e.offsetX + itemWidth) > zoneWidth)?(locateX - ((e.offsetX + itemWidth) - zoneWidth)):locateX; locateY = ((e.offsetY + itemHeight) > zoneHeight)?(locateY - ((e.offsetY + itemHeight) - zoneHeight)):locateY; // ย้ายตำแหน่งแบบไม่ต้องมีการเคลื่อนไหว // moveItem.offset({left:locateX,top:locateY}); // ย้ายตำแหน่งแบบมีการเคลื่อนไหว moveItem.fadeIn() .css({position:'absolute'}) .animate({ left:locateX, top:locateY }, 300 , function() { // ทำคำสั่งเมื่อหยุดการเคลื่อนไหวแล้ว }); }); }); </script> <script> $(function(){ }); </script> </body> </html>
อธิบายการทำงานเพิ่มเติมบางส่วน
เมื่อพื้นที่ที่เรากำหนดถูกคลิก หรือก็คือ div.click-zone เราก็จะส่ง event object เข้าไป
ทำงานในฟังก์ชั่น ผ่านตัวแปร e
$(document.body).on("click",".click-zone",function(e){ // การทำงาน });
การตรวจสอบแรกคือ เราต้องการแน่ใจว่า เราคลิกโดนพื้นที่ที่ต้องการ และไม่มีตัวอื่นมาบัง
// ตัวที่คลิกโดนมีตัวอื่นมาทับ หรืออยู่ด้านบน // ใช้การตรวจสอบ เป้าหมายถ้าไม่มีคลาสตามที่กำหนด ไม่ต้องทำงาน if(!$(e.target).hasClass('click-zone')){ return false; // ไม่ทำคำสั่งใดๆ }
ค่าที่น่าสนใจส่วนนี้มีสองค่าคือ e.target กับ e.currentTarget
- e.target ตัวบนสุด ถ้ามี เช่น มีกล่องสีแดงอยู่ด้านบน เราคลิกโดนตัวนี้
- e.currentTarget ตำแหน่งเป้าหมายที่เราต้องการ ค่านี้จะเป็นค่าตามที่กำหนด event ไม่เปลี่ยนแปลง
ดังนั้นถ้าเราคลิกไปยังพื้นที่ที่กำหนด และไม่มีอะไรบังอยู่ด้านบน ค่า e.target ก็จะเท่ากับ e.currentTarget
หรือเป็นค่าเดียวกัน
แต่ถ้าเราคลิกในพื้นที่ที่กำหนดก็่จริง แต่ตัวที่เราคลิกหรือตำแหน่งที่เราคลิกมีตัวอื่นอยู่ด้านบน แสดงว่าค่า
e.target ก็จะ ไม่ เท่ากับ e.currentTarget เป็นคนละตัวกัน
การตรวจสอบด้านบน นอกจากจะใช้ css class แล้ว เราก็สามารถใช้การเช็คค่าสองค่าข้างต้นแทนได้ เช่น
if(!(e.target==e.currentTarget)){ return false; // ไม่ทำคำสั่งใดๆ }
ค่าเกี่ยวกับ pageX pageY clientX clientY screenX screenY
เป็นการอ้างอิงตำแหน่งของเมาส์เมื่อเทียบกับส่วนต่างที่อยู่ในหน้าจอ
ถ้าอ้างอิง screen ก็จะเป็นการอ้างอิงจากหน้าจอ หรือพื้นที่ทั้งหมด ห่างจากขอบด้านซ้าย กี่พิกเซล x ห่างจาก
ขอบด้านบน กี่พิกเซล y
ถ้าอ้างอิงจากหน้าเว็บ จะหมายถึงช่องที่แสดงหน้าเว็บ ไม่รวมส่วนต่างๆ ของบราวเซอร์ แต่นับรวมจากขอบที่ถูก
ซ่อนหรือมี scrollbar ด้วย ถ้าหน้านั้นๆ ยาวและมี scrollbar ตรงนี้จะใช้ค่าจาก page
ถ้าอ้างอิงจากหน้าเว็บเหมือนกัน แต่เอาเฉพาะส่วนที่มองเห็น เข้าใจง่ายๆ คือขอบบนขอบซ้ายของช่องแสดงหน้าเว็บ
ไม่นับส่วนที่มองไม่เห็นเหมือนค่า page ส่วนนี้จะใช้ค่า client ค่า page กับ client อาจจะมีค่าเท่ากันถ้าเว็บนั้นๆ
หรือหน้าเพจน้้นๆ ไม่มี scrollbar
ถ้าอ้างอิงจากขอบบนขอบซ้ายของพื้นที่ที่กำหนด ก็จะใช้เป็นค่า offset แทนนั่นคือจากขอบพื้นที่ที่เรากำหนด มาถึง
ตำแหน่งของเมาส์เป็นเท่าไหร่
การใช้ตำแหน่งจากเมาส์
ในโค้ดตัวอย่าง เริ่มต้นเรากำหนดให้ใช้ตำแหน่งของเมาส์จากค่า page
// ใช้ค่าตำแหน่งจากการอ้างอิง page let locateX = e.pageX; let locateY = e.pageY;
ถ้าไม่มีการกำหนดเงื่อนไขเพิ่มเติม เพื่อกันไม่ให้แสดงนอกพื้นที่ที่กำหนด และไม่ต้องมีการกำหนดการ
เคลื่อนไหว โค้ดส่วนนี้ก็จะใช้ประมาณนี้
// ใช้ค่าตำแหน่งจากการอ้างอิง page let locateX = e.pageX; let locateY = e.pageY; // ย้ายตำแหน่งแบบไม่ต้องมีการเคลื่อนไหว moveItem.offset({left:locateX,top:locateY});
ดูตัวอย่างที่ demo 2
กำหนดเงื่อนไขเพิ่มเติมในการระบุตำแหน่ง
ถ้าเราสังเกตใน demo 2 เมื่อคลิกไปที่ตำแหน่งชิดขอบขวา หรือชิดขอบล่าง เราจะเห็นว่า กล่องจะไปอยู่
ในตำแหน่งที่ล้นออกมาจากพื้นที่ที่กำหนด ดังนั้น เพื่อแก้ปัญหานี้ เราจึงสร้างเงื่อนไข สำหรับกำหนดให้ว่า ถ้า
ตำแหน่งกล่องที่ย้ายไปตำแหน่งที่คลิก เลยพื้นที่ที่กำหนด จากค่าส่วนเกินที่เกิดขึ้น ให้เราลบเอาค่าส่วนเกินนั้นเอง
แล้วให้ตำแหน่งกล่องชิดขอบขวา หรือขอบล่างแล้วแต่กรณี
// คำนวณการ กำหนดตำแหน่ง ไม่ให้กล่องออกจากพื้นที่ locateX = ((e.offsetX + itemWidth) > zoneWidth)?(locateX - ((e.offsetX + itemWidth) - zoneWidth)):locateX; locateY = ((e.offsetY + itemHeight) > zoneHeight)?(locateY - ((e.offsetY + itemHeight) - zoneHeight)):locateY;
สมมติ พื้นที่กว้าง 600 กล่องกว้าง 100 ถ้าเราคลิกที่ขอบขวาเลย ค่า e.offsetX ที่อิงจากพื้นที่ก็จะมีค่ามากสุด
เท่ากับ 600 ดังนั้นตำแหน่งของกล่องก็จะเลยไปเท่ากับ 100 เพราะมีค่า
e.offsetX + itemWidth > zoneWidth
x + 100 > 600
หากเข้าเงื่อนไขข้างต้น ต้องใช้ค่า locateX ใหม่ แต่ถ้าไม่เข้าเงื่อนไข ก็ใช้ค่าตามเดิม
ค่าจากเงื่อนไขใหม่คือ ตำแหน่งเดิม - ส่วนต่างที่เกิน
locateX - ((e.offsetX + itemWidth) - zoneWidth)
ใช้รูปแบบเดียวกันกับแนว Y
การทำการเคลื่อนไหวหรือ animation
ในการสร้างการเคลื่อนไหวด้วย jQuery เราใช้คำสั่ง animate แล้วกำหนด property ค่า top กับ left
แทนการกำหนดด้วยคำสั่ง offset() กำหนดให้ทำงานให้เสร็จใน 300 มิลลิวินาที
// ย้ายตำแหน่งแบบมีการเคลื่อนไหว moveItem.fadeIn() .css({position:'absolute'}) .animate({ left:locateX, top:locateY }, 300 , function() { // ทำคำสั่งเมื่อหยุดการเคลื่อนไหวแล้ว });
ถึงรูปแบบการทำงานจะดูไม่ซับซ้อน แต่ก็มีรายละเอียดที่ทำให้เราสามารถทำไปประยุกต์ใช้ รวมถึงทำความ
เข้าใจการทำงานเพิ่มเติมได้ไม่มากก็น้อย และอาจจะมีบทความประยุกต์เพิ่มเติม รอติดตาม