หากคุณยังไม่ทราบว่า Canvas คืออะไรคุณสามารถตรวจสอบบทความก่อนหน้านี้ได้
เมื่อเรียนรู้ที่จะวาดเส้นเป็นพื้นฐานที่สุดและการเชื่อมต่อของเส้นสามารถสร้างรูปร่างใด ๆ เช่นเดียวกันในผืนผ้าใบ
ก่อนที่เราจะเริ่มต้นเรานำผืนผ้าใบและแปรงออกมา:
var cvs = document.getElementById ('CVS'); //ผ้าใบ
var ctx = cvs.getContext ('2d'); // แปรง
เมื่อเราวาดจุดปากกาจะไม่ได้รับการแก้ไขและจะเปลี่ยนแปลงได้ตลอดเวลา แม้ว่าผืนผ้าใบไม่ได้กำหนดจุดเขียนผ่านมือ แต่ก็มีวิธีการซึ่งก็คือ moveto Moveto เทียบเท่ากับการยกปลายปากกาออกจากผืนผ้าใบและย้ายไปยังจุดที่ระบุ (เช่นพิกัด)
ctx.moveto (x, y)
ไม่มีการวาดกราฟิกในระหว่างกระบวนการนี้ซึ่งเทียบเท่ากับการแกว่งไปมาบนผืนผ้าใบด้วยปากกาของคุณ
แต่มันก็ไร้ประโยชน์ที่จะแกว่งไปมาเราต้องเริ่มวาด วาดง่ายที่สุด: เส้นตรง
วิธีการวาดเส้นตรงคือ lineto พารามิเตอร์ของมันเหมือนกับ Moveto และทั้งคู่เป็นจุดเดียวกัน
แน่นอน CTX.lineto (x, y) เมื่อคุณวาดเส้นจุดปากกาก็จะเคลื่อนที่ดังนั้นหลังจากลินโตจุดปากกากลายเป็นจุดเป้าหมาย
ctx.moveto (100,100);
ctx.lineto (200,100);
ในเวลานี้คุณรีเฟรชหน้าเว็บและคุณจะพบว่าไม่มีสายที่คาดหวังบนผืนผ้าใบและไม่มีอะไร เพราะเรามีขั้นตอนน้อยกว่าหนึ่งขั้นตอนที่จริงแล้วเป็นเส้นทางที่วาดและมองไม่เห็นด้วยตัวเอง ถ้าเราต้องการให้เขาแสดงมันเราต้องวาดเขา
นักเรียนที่ใช้ PS จะรู้ว่าทั้งสองโหมดของกราฟิกหนึ่งคือการเติมและอีกโหมดหนึ่งคือจังหวะ ตอนนี้เราได้วาดเส้นซึ่งเทียบเท่ากับการวาดเส้นทางใน PS ในเวลานี้เราสามารถวาดขอบของเส้นทางและรูปจะปรากฏขึ้น
วิธีการของ Canvas stroke คือ stroke () ตอนนี้ให้กรอกรหัส:
ctx.moveto (100,100);
ctx.lineto (200,100);
ctx.stroke (); รีเฟรชในเวลานี้และคุณสามารถดูบรรทัด แน่นอนว่าคุณสามารถวาดเส้นทางหลายร้อยเส้นทางอย่างต่อเนื่องและจากนั้นทำการกระทำจังหวะเพื่อวาดหลายร้อยบรรทัดในครั้งเดียว ตอนนี้เรามาวาดสี่เหลี่ยมที่มี 4 บรรทัด:
ctx.moveto (100,100);
ctx.lineto (200,100);
ctx.lineto (200,200);
ctx.lineto (100,200);
ctx.lineto (100,100);
ctx.stroke ();
ที่นี่ก่อนอื่นเราวาดเส้นทางทั้งหมดแล้วตีมันกันอีกครั้ง
- การร้องเรียนของผู้เขียน: หนึ่งในสิ่งที่ไม่ดีเกี่ยวกับการวาดภาพผ้าใบคือมันขึ้นอยู่กับการคาดเดาและมันก็ไม่ได้ใช้งานง่าย
เคล็ดลับที่ร้ายแรง: กระบวนการวาดภาพของผ้าใบ (เช่นการเติมและจังหวะ) นั้นใช้ทรัพยากรมาก หากคุณต้องการประหยัดทรัพยากรของระบบและปรับปรุงประสิทธิภาพการที่ดีที่สุดคือการวาดเส้นทางทั้งหมดและเติมหรือก้าวเข้าสู่รูปในครั้งเดียว
จากรูปด้านบนเราจะเห็นว่าความหนาของเส้นเริ่มต้นคือ 1px ในขณะที่สีของเส้นเป็นสีดำ แน่นอนว่าเราสามารถตั้งค่าได้ แต่สิ่งที่แปลกคือความกว้างของเส้นคือ linewidth ในขณะที่สไตล์เส้นเรียกว่า Strokestyle ทำไมไม่สายเลือด? ฉันไม่รู้เหมือนกัน -
ctx.lineWidth = 10;
ctx.strokestyle = 'rgba (255,0,0,0.5)';
รหัสด้านบนตั้งค่าความกว้างของบรรทัดเป็น 10px และสีของเส้นจะกลายเป็นสีแดงโปร่งแสง
ดังที่แสดงในรูปที่ 1 รีเฟรชดูเหมือนว่ามีบางอย่างผิดปกติ! ทำไมดูเหมือนว่าชิ้นเล็ก ๆ จะหายไปที่มุมซ้ายบน? นี่ไม่ใช่ภาพลวงตา เหตุผลเริ่มต้นด้วยวิธีการวาดเส้นผ้าใบ
คำถาม: หากเส้นทางของสี่เหลี่ยมผืนผ้าที่ฉันวาดคือความกว้างและความสูง 100 และความกว้างของเส้นขอบของฉันคือ 10px แล้วความกว้างและความสูงโดยรวมของสี่เหลี่ยมนี้คืออะไร มันคือ 100+10*2 = 120 หรือไม่?
หากขอบถูกดึงออกไปนอกเส้นทางอย่างสมบูรณ์มันก็คือ 120 แต่ผ้าใบไม่ได้ เส้นในผืนผ้าใบมีกึ่งกลางซึ่งตั้งอยู่ตรงกลางของเส้นและจังหวะของเส้นขยายไปถึงทั้งสองด้านด้วยเส้นตรง ตัวอย่างเช่นหากความกว้างของสายของคุณคือ 1 เส้นตรงกลางจะอยู่ที่ 0.5; หากความกว้างเป็น 5 เส้นตรงกลางจะอยู่ที่ 2.5 เมื่อรูปผ้าใบถูกลูบเส้นทางที่เหมาะกับเส้นกึ่งกลางของเส้นแล้วจังหวะ ดังแสดงในรูปที่ 2:
ดังนั้นเมื่อลูบครึ่งหนึ่งของเส้นอยู่ด้านนอกและครึ่งหนึ่งอยู่ด้านในนั่นคือความกว้างโดยรวมของสี่เหลี่ยมบนคือ 100+ (10/2)*2 ซึ่งเท่ากับ 110
ด้วยเหตุนี้จึงเป็นเรื่องธรรมดาที่จะมีมุมที่หายไปที่มุมซ้ายบน เพราะไม่มีใครวาดที่นี่
แต่ทำไมไม่มีช่องว่างในมุมที่เหลือ? ดูรูปของคุณไม่มีช่องว่างในมุมทั้งสี่ใช่ไหม
นั่นเป็นเพราะฉันไม่ได้ยกแปรงขึ้นในระหว่างการวาดเส้นและแปรงก็ต่อเนื่องนั่นคือฉันไม่เคยเคลื่อนไหวมาก่อน ถ้าคุณไม่เชื่อเลยให้มาดูกันเลย:
ctx.moveto (100,100);
ctx.lineto (200,100);
ctx.moveto (200,100); // หมายเหตุที่นี่
ctx.lineto (200,200);
ctx.lineto (100,200);
ctx.lineto (100,100);
ctx.lineWidth = 10;
ctx.strokestyle = 'rgba (255,0,0,0.5)';
ctx.stroke ();
เราย้ายไปก่อนที่จะวาดบรรทัดที่สองและพิกัดของ moveto ไม่เปลี่ยนแปลงและมันก็ยังคงเป็นจุดเดียวกัน แต่หลังจากการรีเฟรชรูปจะกลายเป็นเช่นนี้ [รูปที่ 3]::
เข้าใจ? เพราะเรายกปากกา
ตอนนี้ให้ลบ Moveto ไม่ต้องกังวลลองคิดดูว่าจะเติมมุมที่หายไปที่มุมซ้ายบนหรือไม่
ก่อนอื่นให้ฉันถามคำถามเส้นทางของเราปิดหรือไม่? นี่ไม่ใช่เรื่องไร้สาระใช่ไหม เราไม่ได้หันเส้นทางกลับไปที่ต้นกำเนิดแล้วใช่ไหม แน่นอนว่ามันปิด!
ผิด! นี่เป็นเพียงจุดสุดท้ายของเส้นทางที่ทับซ้อนกับจุดเริ่มต้น แต่เส้นทางนั้นไม่ได้ปิด!
จะปิดเส้นทางในผืนผ้าใบได้อย่างไร? ใช้ ClosePath ()
ctx.moveto (100,100);
ctx.lineto (200,100);
ctx.lineto (200,200);
ctx.lineto (100,200);
ctx.lineto (100,100);
ctx.closepath (); // close path
ctx.lineWidth = 10;
ctx.strokestyle = 'rgba (255,0,0,0.5)';
ctx.stroke ();
การสดชื่นในเวลานี้จะทำให้คุณเป็นสี่เหลี่ยมจัตุรัสที่สมบูรณ์แบบ รูปที่ 4:
ไม่ว่าเราจะเปลี่ยนเส้นให้หนาแค่ไหน - ยิ่งมีคนชอบพวกเขามากเท่าไหร่ใช่ไหม? -สี่มุมของสี่เหลี่ยมนี้เป็นมุมขวาปกติและจะไม่ราบรื่น กรณีที่มีมุมเรียบคืออะไร? โปรดดูจังหวะสแควร์ใน PS, รูปที่ 5:
ฉันเห็นมัน ยิ่งขอบหนาขึ้นส่วนโค้งของเชิงมุมของเขาก็ยิ่งใหญ่ขึ้นเท่านั้น
ถ้าฉันคิดว่าเส้นขอบในผืนผ้าใบเหมือนกับใน PS มีวิธีใดบ้าง? แน่นอนว่ามีแอตทริบิวต์ LineJoin
LineJoin ซึ่งหมายถึงจุดตัดของเส้นมี 3 คุณสมบัติ: MITOR (ค่าเริ่มต้น, มุมคม), มุมเอียง (มุมเอียง), และกลม (กลม) ดังแสดงในรูปที่ 6:
ไม่ต้องสงสัยเลยว่าเราสามารถเข้าใจได้ว่าสี่เหลี่ยมผืนผ้าของเราใช้มุมที่คมชัดดังนั้นลองเปลี่ยนเป็นมุมโค้งมน:
กราฟิกกลายเป็นเช่นนี้รูปที่ 7:
มันเหมือนกับ PS ใช่มั้ย
นอกจากนี้จากภาพก่อนหน้านี้เราได้เรียนรู้ว่าปลายทั้งสองของเส้นผืนผ้าใบนั้นแบนสามารถเปลี่ยนได้หรือไม่? ท้ายที่สุดมันไม่ได้ดูดี
นอกจากนี้ยังเป็นไปได้นั่นคือคุณสมบัติ linecap ซึ่งเป็นจุดสิ้นสุดที่กำหนดบรรทัด Linecap มี 3 ค่า: ก้น (แบน, ค่าเริ่มต้น), กลม (วงกลม), สี่เหลี่ยมจัตุรัส (สี่เหลี่ยม) ดังแสดงในรูปที่ 8
คุณสามารถพบว่าหัวแบนนั้นเหมือนกันกับหัวสี่เหลี่ยมความแตกต่างเพียงอย่างเดียวคือหัวแบนไม่ยืดออก ทั้งหัวกลมและหัวสี่เหลี่ยมจะถูกยืดออกเป็นชิ้น ส่วนนี้นานแค่ไหน? นั่นคือครึ่งหนึ่งของความกว้างของเส้น
คุณเคยคิดอะไรบ้าง? ฮ่าฮ่าปัญหาเส้นทางปิดก่อนหน้านี้หากเราตั้งค่า linecap เป็นส่วนหัวของสี่เหลี่ยมเอฟเฟกต์จะเหมือนกัน!
แต่เพื่อให้ปลอดภัยเรายังต้องปิดเส้นทางจำไว้!
ฉันยังต้องการเตือนคุณ: เส้นทางที่ปิดไม่มีจุดสิ้นสุด! ดังนั้นรูปแบบของจุดสิ้นสุดจึงไม่ปรากฏบนเส้นทางปิด
นอกจากนี้ : linecap ค่อนข้างคล้ายกับ linejoin ระวังอย่าให้ยุ่งหากคุณมีความคมชัดและโชคร้ายคุณอาจพบว่าบางครั้งเส้น 1 พิกเซลนั้นไม่กว้าง 1 พิกเซล แต่ดูเหมือนจะกว้างขึ้นและเบลอ ดังแสดงในรูปที่ 9:
ยินดีด้วย! คุณพบข้อผิดพลาดที่ไม่ใช่ข้อผิดพลาด นี่เป็นเรื่องพิเศษมากฉันจะวางเขาไว้ในบทความถัดไป