ตั้งแต่ฉันเริ่มทำงาน ฉันเขียนเกี่ยวกับ vue, react, กฎทั่วไป, อัลกอริธึม, โปรแกรมขนาดเล็ก ฯลฯ แต่ฉันไม่เคยเขียนเกี่ยวกับ Canvas เลย เพราะฉันไม่รู้จริงๆ ว่าต้องทำอย่างไร!
ในปี 2018 ฉันตั้งเป้าหมายเล็กๆ สำหรับตัวเอง: เรียนรู้ Canvas และบรรลุผลสำเร็จจากการใช้ Canvas เพื่อสร้างภาพเคลื่อนไหวบางรายการที่ไม่ง่ายที่จะทำด้วย CSS3
บทความนี้เป็นข้อดีประการแรกจากการเรียนรู้ Canvas การสาธิตแรกที่หลายคนทำเมื่อเรียนรู้ Canvas คือการนำนาฬิกาไปใช้จริง ๆ ด้วย แต่แทนที่จะพูดถึงเรื่องนี้ ฉันจะพูดถึงสิ่งที่น่าสนใจและง่ายกว่า หนึ่ง.
กดเมาส์ค้างไว้เพื่อวาดวิถี ความต้องการบนผืนผ้าใบ ไม่มีอะไรบนผืนผ้าใบในสถานะเริ่มต้น ตอนนี้ ฉันต้องการเพิ่มเหตุการณ์ของเมาส์ลงบนผืนผ้าใบ และใช้เมาส์เพื่อเขียนบนผืนผ้าใบ เอฟเฟกต์เฉพาะคือการเลื่อนเมาส์ไปยังจุดใดก็ได้บนผืนผ้าใบ จากนั้นกดเมาส์ค้างไว้ เลื่อนตำแหน่งเมาส์ จากนั้นคุณก็สามารถเริ่มเขียนได้!
หลักการมาวิเคราะห์แนวคิดโดยย่อ ขั้นแรก เราต้องการผืนผ้าใบ จากนั้นคำนวณตำแหน่งของเมาส์บนผืนผ้าใบ เชื่อมโยงเหตุการณ์ onmousedown และ onmousemove กับเมาส์ และวาดเส้นทางระหว่างการเคลื่อนไหว การวาดสิ้นสุดลง
แม้ว่าแนวคิดนี้จะเรียบง่ายมาก แต่ก็มีบางส่วนที่ต้องใช้เทคนิคบางอย่างในการนำไปปฏิบัติ
1. จำเป็นต้องมีไฟล์ html ซึ่งมีองค์ประกอบแคนวาส
เป็นผืนผ้าใบที่มีความกว้าง 800 และสูง 400 ทำไมไม่เขียน px? อ๋อ ยังไม่เข้าใจครับ แนะนำโดยเอกสาร canvas ครับ
<!doctype html><html class=no-js lang=zh> <head> <meta charset=utf-8> <meta http-equiv=x-ua-tablet content=ie=edge> <title>การเรียนรู้แคนวาส< /title> <meta name=description content=> <meta name=viewport content=width=device-width, default-scale=1> <link rel=manifest href=site.webmanifest> <link rel=apple-touch-icon href=icon.png> <link rel=stylesheet href=css/main.css> </head> <body> <canvas id=theCanvas width=800 ความสูง =400></canvas> <script src=js/main.js></script> </body></html>
2. ตรวจสอบว่าสภาพแวดล้อมปัจจุบันรองรับ Canvas หรือไม่
ใน main.js เราเขียนฟังก์ชันที่ดำเนินการด้วยตนเอง ต่อไปนี้คือข้อมูลโค้ดสำหรับการตัดสินความเข้ากันได้ ส่วนเนื้อหาหลักของโค้ดจะเป็นแกนหลักของข้อกำหนดการใช้งาน
(function() { la theCanvas = document.querySelector('#theCanvas') if (!theCanvas || !theCanvas.getContext) { //เข้ากันไม่ได้กับ canvas return false } else { //Code body}})()
3. รับวัตถุ 2d
ให้บริบท = theCanvas.getContext('2d')
4. รับพิกัดของเมาส์ปัจจุบันที่สัมพันธ์กับผืนผ้าใบ
ทำไมเราต้องได้พิกัดนี้? เนื่องจากค่าเริ่มต้นของเมาส์จะรับพิกัดสัมพัทธ์ของหน้าต่างปัจจุบัน และผืนผ้าใบสามารถอยู่ที่ใดก็ได้บนหน้า การคำนวณจึงจำเป็นเพื่อให้ได้พิกัดเมาส์จริง
การได้รับพิกัดที่แท้จริงของเมาส์ที่สัมพันธ์กับผืนผ้าใบนั้นถูกห่อหุ้มไว้ในฟังก์ชัน หากคุณรู้สึกว่าเป็นนามธรรม คุณสามารถวาดภาพบนกระดาษเพื่อทำความเข้าใจว่าทำไมจึงต้องดำเนินการนี้
โดยปกติแล้ว ค่านี้จะเป็น x - rect.left และ y - rect.top แต่ทำไมมันถึงเป็น x - rect.left * (canvas.width/rect.width)
canvas.width/rect.width หมายถึงการกำหนดพฤติกรรมการปรับขนาดในแคนวาสและค้นหาตัวคูณการปรับขนาด
const windowToCanvas = (canvas, x, y) => { // รับคุณลักษณะบางอย่างของหน้าต่างระยะทางองค์ประกอบผ้าใบ อธิบายไว้ใน MDN ให้แก้ไข = canvas.getBoundingClientRect() // พารามิเตอร์ x และ y ถูกส่งผ่านตามลำดับจากเมาส์ พิกัดหน้าต่างระยะทาง จากนั้นลบระยะห่างระหว่างผืนผ้าใบกับด้านซ้ายและด้านบนของหน้าต่าง กลับ { x: x - rect.left * (canvas.width/rect.width), y: y - rect.top * (canvas.height/rect.height) }}
5. ด้วยฟังก์ชันเครื่องมือในขั้นตอนที่ 4 เราสามารถเพิ่มกิจกรรมเมาส์ลงบนผืนผ้าใบได้!
ขั้นแรกให้ผูกเหตุการณ์ onmousedown ไว้กับเมาส์ และใช้ MoveTo เพื่อวาดจุดเริ่มต้นของพิกัด
theCanvas.onmousedown = function(e) { //รับพิกัดของจุดที่กดเมาส์สัมพันธ์กับผืนผ้าใบ ให้ ele = windowToCanvas(theCanvas, e.clientX, e.clientY) // การทำลายการกำหนดโครงสร้างของ es6 ให้ { x, y } = ele // จุดเริ่มต้นของการวาด บริบท.moveTo(x, y)}
6. เมื่อเลื่อนเมาส์ไม่มีเหตุการณ์การกดเมาส์ค้าง จะตรวจสอบได้อย่างไร?
เคล็ดลับเล็ก ๆ น้อย ๆ ที่ใช้ในที่นี้คือการดำเนินการเหตุการณ์ onmousemove (การเคลื่อนไหวของเมาส์) ภายใน onmousedown เพื่อให้สามารถตรวจสอบและเคลื่อนย้ายเมาส์ได้
theCanvas.onmousedown = function(e) { //รับพิกัดของจุดที่กดเมาส์สัมพันธ์กับผืนผ้าใบ ให้ ele = windowToCanvas(theCanvas, e.clientX, e.clientY) // การทำลายการกำหนดโครงสร้างของ es6 ให้ { x, y } = ele // จุดเริ่มต้นของการวาด context.moveTo(x, y) //เหตุการณ์การย้ายเมาส์ theCanvas.onmousemove = (e) => { //รับตำแหน่งพิกัดใหม่เมื่อเคลื่อนที่ ใช้ lineTo เพื่อบันทึกพิกัดปัจจุบัน จากนั้นลากเส้นเพื่อวาดจุดก่อนหน้าไปที่ เส้นทางจุดปัจจุบัน ให้ ele = windowToCanvas(theCanvas, e.clientX, e.clientY) ให้ { x, y } = ele context.lineTo(x, y) context. stroke() }}
7. เมื่อปล่อยเมาส์ เส้นทางจะไม่ถูกวาดอีกต่อไป
มีวิธีใดที่จะป้องกันทั้งสองเหตุการณ์ที่ถูกตรวจสอบด้านบนในเหตุการณ์ onmouseup หรือไม่? มีหลายวิธี การตั้งค่า onmousedown และ onmousemove เป็น null เป็นวิธีหนึ่งที่ฉันใช้สวิตช์ isAllowDrawLine ถูกตั้งค่าเป็นค่าบูลเพื่อควบคุมว่าฟังก์ชันจะถูกดำเนินการหรือไม่ สำหรับโค้ดเฉพาะ โปรดดูซอร์สโค้ดแบบเต็มด้านล่าง
ซอร์สโค้ดแบ่งออกเป็น 3 ไฟล์ ได้แก่ index.html, main.js และ utils.js ที่นี่ฉันใช้ parcle เพื่อกำหนดค่าสภาพแวดล้อมการพัฒนา ดังนั้นจะไม่มีข้อผิดพลาดหากคุณคัดลอกโค้ดโดยตรง เมื่อทำงาน หากเกิดข้อผิดพลาดและไม่สามารถอัปเกรดเบราว์เซอร์ได้ คุณสามารถเปลี่ยนไวยากรณ์ es6 เป็น es5 ได้
1.ดัชนี.html
ดังที่ได้แสดงไว้ข้างต้นแล้ว และจะไม่ทำซ้ำอีก
2.main.js
นำเข้า { windowToCanvas } จาก './utils'(function() { la theCanvas = document.querySelector('#theCanvas') if (!theCanvas || !theCanvas.getContext) { return false } else { la context = theCanvas.getContext ('2d') ให้ isAllowDrawLine = false theCanvas.onmousedown = function(e) { isAllowDrawLine = true ให้ ele = windowToCanvas(theCanvas, e.clientX, e.clientY) ให้ { x, y } = ele context.moveTo(x, y) theCanvas.onmousemove = (e) => { if (isAllowDrawLine) { ให้ ele = windowToCanvas(theCanvas , e.clientX, e.clientY) ให้ { x, y } = ele context.lineTo(x, y) บริบท.จังหวะ() } } } theCanvas.onmouseup = function() { isAllowDrawLine = false } }})()
3.utils.js
/** รับพิกัดของเมาส์บนผืนผ้าใบ* */const windowToCanvas = (canvas, x, y) => { la rect = canvas.getBoundingClientRect() return { x: x - rect.left * (canvas.width /rect .width), y: y - rect.top * (canvas.height/rect.height) }} ส่งออก { windowToCanvas}สรุป
มีความเข้าใจผิดที่นี่ ฉันใช้ Canvas Object เพื่อผูกเหตุการณ์ theCanvas.onmouseup จริงๆ แล้ว Canvas ไม่สามารถผูกเหตุการณ์ได้จริงๆ แต่เนื่องจากเบราว์เซอร์จะตัดสินให้คุณโดยอัตโนมัติและมอบการประมวลผลเหตุการณ์ จึงไม่จำเป็นต้องกังวลเลย
ข้างต้นคือเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการศึกษาของทุกคน ฉันหวังว่าทุกคนจะสนับสนุน VeVb Wulin Network