เนื้อหานี้จะประยุกต์เพิ่มเติมจากตอนที่แล้วเล็กน้อย เกี่ยวกับการใช้งาน
jQuery และ CSS กำหนดการทำการเคลื่อนไหว ซึ่งตอนที่แล้วเราใช้เมาส์
เป็นตัวกำหนดค่าตำแหน่งใหม่ของ div ที่ต้องการ และเนื้อหานี้ เราจะเพิ่ม
การ keyboard การใช้ปุ่มลูกศรซ้ายขวาบนล่าง ขยับ div ให้ไปอยู่ตำแหน่งที่ต้องการ
เพิ่มเติม คือ เสริมจากตอนที่แล้ว ดังนั้นโค้ดก็จะไม่แตกต่างจากเดิม เพียงแค่เสริมส่วน
ของการทำงานร่วมกับ keyboard เข้ามา
ย้ายตำแหน่งและกำหนดการเคลื่อนไหวด้วย jQuery และ Css อย่างง่าย http://niik.in/1023
https://www.ninenik.com/content.php?arti_id=1023 via @ninenik
รูปแบบการทำงาน
เราจะทำการเคลื่อนย้าย div ที่อยู่ในพื้นที่ที่กำหนด โดยใช้ลูกศรในแป้น keyboard เราสามารถย้ายตำแหน่ง
ทั้งในแนวตั้ง แนวนอน แล้วแนวทแยงมุมได้ ซึ่งเมื่อเลื่อนตำแหน่ง div แล้วจะต้องไม่ออกนอกพื้นที่ที่กำหนด
การใช้ keyboard เพื่อกำหนดตำแหน่งเพิ่มเติม จะช่วยให้เาระบุตำแหน่งได้แม่นยำมากกว่าการใช้เมาส์ ช่วยให้สามารถ
ชิดขอบได้ง่ายขึ้น
สิ่งที่จะได้เรียนรู้จากตัวอย่าง
เราจะได้รู้จักการใช้งาน event ของ keyboard รู้จักการสร้างเงื่อนไขการตรวจจับว่าตอนนี้กดปุ่มไหนอยู่ และการ
เปลี่ยนตำแหน่งด้วย jQuery และ CSS
ไฟล์ตัวอย่าง demo.html
ดูการทำงานที่ตัวอย่าง demo 2 ด้านล่าง
<!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); // ใช้ค่าตำแหน่งจากการอ้างอิง 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.fadeIn() .css({position:'absolute'}) .animate({ left:locateX, top:locateY }, 300 , function() { // ทำคำสั่งเมื่อหยุดการเคลื่อนไหวแล้ว }); }); // โค้ส่วนที่เพิ่มเติมเข้ามาในเนื้อหาตอนนี้ var ar = new Array(37,38,39,40); // ค่าคีโคด KeyCode ของลูกศร ซ้าย-บน-ขวา-ล่าง var d = {}; // object สำหรับเก็บว่า ปุ่มไหนถูกกดอยู่บ้าง var step = 10; // จำนวนพิกเซล ที่จะขับแต่ละครั้งเมื่อกดปุ่ม // พิกัดขอบเขตของพื้นที่ var minOffsetX = zoneArea.offset().left; var minOffsetY = zoneArea.offset().top; var maxOffsetX = (zoneArea.offset().left+zoneArea.width())-moveItem.width(); var maxOffsetY = (zoneArea.offset().top+zoneArea.height())-moveItem.height(); // เมื่อมีการกดปุ่มที่ keyboard $(window).keydown(function(e) { d[e.which] = true; // กำหนด object ให้กับปุ่มที่กด อธิบาบเพิ่มด้านล่าง if($.inArray(e.which,ar) > -1) { // ทำงานเฉพาะปุ่มที่กำหนดเท่านั้น e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; } }); // เมื่อมีการปล่อยปุ่มที่กด $(window).keyup(function(e) { // ตรวจสอบว่าปุ่มไหนถูกกด ควรจะบวกค่าเพิ่ม หรือลดค่า หรือคงค่าเดิม let locateX = d[37] ? "-="+step+"px": d[39] ? "+="+step+"px" : "+=0px"; let locateY = d[38] ? "-="+step+"px": d[40] ? "+="+step+"px" : "+=0px"; if($.inArray(e.which,ar) > -1) { // เมื่อมีการกดปุ่มที่ keyboard // ได้ตำแหน่ง แล้วนำมากำหนดการย้ายตำแหน่ง moveItem.css({position:'absolute',left:locateX,top:locateY}); // เงื่อนไขเมื่อย้ายแล้วเพิ่มเติม เช่น ออกนอกขอบเขตที่กำหนดหรือไม่ // เงื่อนไขขอบเขต ด้านบน ด้านซ้าย locateX = (moveItem.offset().left < minOffsetX)?minOffsetX+"px":"+=0px"; locateY = (moveItem.offset().top < minOffsetY)?minOffsetY+"px":"+=0px"; // เงื่อนไขขอบเขต ด้านล่าง ด้านขวา locateX = (moveItem.offset().left > maxOffsetX)?maxOffsetX+"px":locateX; locateY = (moveItem.offset().top > maxOffsetY)?maxOffsetY+"px":locateY; // ได้ตำแหน่งใหม่ และกำหนดการย้ายตำแหน่งอีกครั้ง moveItem.css({position:'absolute',left:locateX,top:locateY}); d[e.which] = false; // กำหนด object ให้กับปุ่มที่กด ยกเลิกปุ่มที่กด อธิบาบเพิ่มด้านล่าง e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; } }); }); </script> <script> $(function(){ }); </script> </body> </html>
อธิบายการทำงานเพิ่มเติมบางส่วน
// เมื่อมีการกดปุ่มที่ keyboard $(window).keydown(function(e) { d[e.which] = true; // กำหนด object ให้กับปุ่มที่กด อธิบาบเพิ่มด้านล่าง if($.inArray(e.which,ar) > -1) { // ทำงานเฉพาะปุ่มที่กำหนดเท่านั้น e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; } });
กำหนด object ให้กับปุ่มที่กด หมายถึงว่า เมื่อเรากดปุ่มลูกศรใดๆ ก็จะมีค่า KeyCode ของลูกศร
นั้นส่งมา เราจะใช้ค่านี้กำหนดการเคลื่อนไหว เช่น กดปุ่ม ลูกศรซ้าย ก็จะได้ค่า KeyCode ของลูกศร
เท่ากับ 37 นำค่าเป็น key ของ object d ก็จะได้ d[37] เท่ากับ true แสดงว่าปุ่มนี้ถูกกดอยู่
d[e.which] = true; // d[37] = true;
และเมื่อกดปุ่ม เราจะให้ทำงานเมื่อกดเฉพาะปุ่มที่มี KeyCode ตามที่กำหนดเท่านั้น
if($.inArray(e.which,ar) > -1) { // ทำงานเฉพาะปุ่มที่กำหนดเท่านั้น e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; }
จะเห็นว่าเมื่อปุ่มลูกศรใดๆ ถูกกด เราได้ทำการปิดการทำงานที่เป็นค่าเริ่มต้น ด้ายคำสั่ง
e.preventDefault() หรือก็คือป้องกันการทำงานค่าเริ่มของ event object นั้นๆ ซึ่งค่าเริ่มต้น
ก็เช่นว่า ถ้าเรากดลูกศรเลื่อนลง และหน้าเพจนั้นมี scrollbar ก็จะเป็นการเลื่อนหน้าเพจ แต่เราต้อง
การปิดการทำงานนี้ ให้ไม่ต้องทำงาน ก็ใช้คำสั่งข้างต้น นอกจากนั้นเรายังคืนค่า false ออกมา
นั่นคือ ไม่มีการทำงานใดๆ ต่อจากนี้แล้ว ดังนั้น คำสั่งเมื่อปุ่มถูกกด ก็จะมีแค่กำหนดค่า object ของปุ่ม
ที่ถูกกดเท่านั้น
e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false;
ต่อไปมาดูเมื่อปุ่มถูกปล่อยหลังจากกดไปแล้ว
// เมื่อมีการปล่อยปุ่มที่กด $(window).keyup(function(e) { // ตรวจสอบว่าปุ่มไหนถูกกด ควรจะบวกค่าเพิ่ม หรือลดค่า หรือคงค่าเดิม let locateX = d[37] ? "-="+step+"px": d[39] ? "+="+step+"px" : "+=0px"; let locateY = d[38] ? "-="+step+"px": d[40] ? "+="+step+"px" : "+=0px"; if($.inArray(e.which,ar) > -1) { // เมื่อมีการกดปุ่มที่ keyboard // ได้ตำแหน่ง แล้วนำมากำหนดการย้ายตำแหน่ง moveItem.css({position:'absolute',left:locateX,top:locateY}); // เงื่อนไขเมื่อย้ายแล้วเพิ่มเติม เช่น ออกนอกขอบเขตที่กำหนดหรือไม่ // เงื่อนไขขอบเขต ด้านบน ด้านซ้าย locateX = (moveItem.offset().left < minOffsetX)?minOffsetX+"px":"+=0px"; locateY = (moveItem.offset().top < minOffsetY)?minOffsetY+"px":"+=0px"; // เงื่อนไขขอบเขต ด้านล่าง ด้านขวา locateX = (moveItem.offset().left > maxOffsetX)?maxOffsetX+"px":locateX; locateY = (moveItem.offset().top > maxOffsetY)?maxOffsetY+"px":locateY; // ได้ตำแหน่งใหม่ และกำหนดการย้ายตำแหน่งอีกครั้ง moveItem.css({position:'absolute',left:locateX,top:locateY}); d[e.which] = false; // กำหนด object ให้กับปุ่มที่กด ยกเลิกปุ่มที่กด อธิบาบเพิ่มด้านล่าง e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; } });
ปกติถ้าเราจะขยับตำแหน่ง ก็จะใช้รูปแบบเป็นดังนี้
moveItem.css({position:'absolute',left:"-=1px",top:"+=1px"}); // เป็นการขยับโดยเพิ่มหรือลดจากตำแหน่งเดิมตามค่าที่กำหนด
แต่พอมีเงื่อนไขว่าเป็นปุ่มที่ลด หรือว่าเป็นปุ่มที่จะเพิ่ม และ เป็นปุ่มลดหรือเพิ่มฝั่งซ้ายขวา หรือ
ปุ่มลดหรือเพิ่มฝั่งด้านบนด้านล่าง ก็จะมีเงื่อนไขเข้ามาเป็นดังนี้
// ตรวจสอบว่าปุ่มไหนถูกกด ควรจะบวกค่าเพิ่ม หรือลดค่า หรือคงค่าเดิม let locateX = d[37] ? "-="+step+"px": d[39] ? "+="+step+"px" : "+=0px"; let locateY = d[38] ? "-="+step+"px": d[40] ? "+="+step+"px" : "+=0px";
รูปแบบคำสั่งข้างต้นเป็น if else แบบสั้น ที่ซ้อนสองเงื่อนไขใน 1 บรรทัด ถ้าแยกเป็นรูปแบบปกติก็จะเป็น
if(d[37]){ let locateX = "-="+step+"px"; // ขยับลดลง }else if(d[39]){ let locateX = "+="+step+"px"; // ขยับเพิ่มขึ้น }else{ let locateX = "+=0px"; // ไม่ขยับ }
ส่วนโค้ดที่เหลือก็จะเป็นเงื่อนไขการกำหนดขอบเขต ทำงานในลักษณะเดียวกัน คำอธิบายในโค้ด เงื่อนไข
ขอบเขตจะช่วยให้เมื่อเรากดเลื่อน ออกนอกพื้นที่ ก็จะถูกย้ายกลับเข้ามา กล่าวคือไม่ให้เคลื่อนออกนอกบริเวณ
ที่กำหนดนั่นเอง
การปรับประยุกต์เพิ่มเติม
ตัวอย่างการทำงานของโค้ดรูปแบบแรก ดูได้ที่ demo 2 ซึ่งจะเห็นว่า การเคลื่อนไหว จะมีเมื่อกดแล้วปล่อยปุ่ม
ก็จะเคลื่อนๆ ไปยังตำแหน่งที่ต้องการตามค่า step ที่กำหนด ซึ่งจะไม่สะดวกนัก แต่ก็มีข้อดีคือได้ตำแหน่งที่ชัดเจน
ถูกต้องแม่นยำกว่า อย่างไรก็ตาม เพื่อความสะดวก เราสามารถประยุกต์ให้กดปุ่มค้างไว้ เพื่อเลื่อนไปยังตำแหน่งที่
ต้องการได้ง่ายขึ้น ด้วยการปรับโค้ดเล็กน้อยดังนี้
// เมื่อมีการปล่อยปุ่มที่กด $(window).keyup(function(e) { if($.inArray(e.which,ar) > -1) { // เมื่อมีการกดปุ่มที่ keyboard d[e.which] = false; // กำหนด object ให้กับปุ่มที่กด ยกเลิกปุ่มที่กด อธิบาบเพิ่มด้านล่าง e.preventDefault(); // ปิดการทำงานค่าเริ่มต้น เช่น ไม่ต้องเลื่อนหน้าจอ return false; } }); // กำหนดให้การเคลื่อนเมื่อกดปุ่ม สะดวกขึ้น กดปุ่มค้างไว้ได้ setInterval(function(){ // ตรวจสอบว่าปุ่มไหนถูกกด ควรจะบวกค่าเพิ่ม หรือลดค่า หรือคงค่าเดิม let locateX = d[37] ? "-="+step+"px": d[39] ? "+="+step+"px" : "+=0px"; let locateY = d[38] ? "-="+step+"px": d[40] ? "+="+step+"px" : "+=0px"; // ได้ตำแหน่ง แล้วนำมากำหนดการย้ายตำแหน่ง moveItem.css({position:'absolute',left:locateX,top:locateY}); // เงื่อนไขเมื่อย้ายแล้วเพิ่มเติม เช่น ออกนอกขอบเขตที่กำหนดหรือไม่ // เงื่อนไขขอบเขต ด้านบน ด้านซ้าย locateX = (moveItem.offset().left < minOffsetX)?minOffsetX+"px":"+=0px"; locateY = (moveItem.offset().top < minOffsetY)?minOffsetY+"px":"+=0px"; // เงื่อนไขขอบเขต ด้านล่าง ด้านขวา locateX = (moveItem.offset().left > maxOffsetX)?maxOffsetX+"px":locateX; locateY = (moveItem.offset().top > maxOffsetY)?maxOffsetY+"px":locateY; // ได้ตำแหน่งใหม่ และกำหนดการย้ายตำแหน่งอีกครั้ง moveItem.css({position:'absolute',left:locateX,top:locateY}); },20);
จะเห็นว่าเราจะใช้ event การปล่อยปุ่มกดแค่เพียง ยกเลิก object ปุ่มที่กดเท่านั้น คล้ายกับ event
ตอนกดปุ่มที่ใช้กำหนดค่า
เราใช้วิธ๊ให้ div พร้อมเคลื่อนไหวตลอดเวลา ผ่านฟังก์ชั่น setInterval() ที่ให้ทำงานซ้ำๆ ทุก 20 มิลลิวินาที
โดยใช้เงื่อนไขเดิมที่ว่าปุ่มไหนถูกกดอยู่ค่าก็จะเปลี่ยนตามปุ่มนั้นๆ ถ้าไม่มีการกดปุ่มใดๆ ก็มีค่าการเปลี่ยนแปลง
เป็น +=0px นั่นคืออยู่ตำแหน่งเดิม วิธีนี้จะทำให้เราสามารถกดปุ่มค้างไว้ได้ แทนการกดแล้วปล่อยหลายๆ ครั้ง
ดูตัวอย่างได้ที่ demo 1
หวังว่าจะเป็นแนวทาง และได้เข้าใจเพิ่มเติมเกี่ยวกับการใช้งาน keyboard event และการประยุกต์ไม่มากก็น้อย