ห่างหายจากการเขียน Blog ไปเป็นหลายเดือนอยู่เหมือนกันนะเนี่ย กลับมาคราวนี้ เพราะว่ามีของมาปล่อยน่ะเอง เป็นโปรแกรมที่ผมอยากจะทำตั้งนานละ แต่ว่าไม่ว่างทำซะที เนื่องจากมัวแต่ไปปั๊มยอดขายอยู่ พอดีว่าโปรโมชั่นที่ผ่านมาของเรา ประสบความสำเร็จอย่างดีงามมาก เลยพอมีเวลาให้ผม (นัน) ได้พักหายใจหายคอทำอย่างอื่นบ้าง เหอๆๆ ผ่านไปหนึ่งวัน ผมก็เสกโปรแกรมนี้ขึ้นมาให้ครับ ตั้งชื่อว่า SystemZ!
สำหรับ SystemZ นี้ จะว่าโปรแกรมเสิรมก็ไม่เชิง เพราะว่ามันคือไฟล์ HTML+JavaScript ที่เขียนแบบ Single Page App (SPA) ด้วย Angular JS (เวอร์ชั่นเก่า เวอร์ชั่นใหม่ที่เป็น TypeScript ยังไม่มีโอกาสได้ลองใช้เลย และเคยดูแล้ว รู้สึกว่าไม่ชอบ) และก็ใช้ Chart JS ในการแสดงผลกราฟ
แล้วทำไมโปรแกรม SystemZ ไม่เขียนเป็นโปรแกรมทั่วไป แต่ทำเป็น SPA ? นั่นก็เพราะว่า ผมตั้งใจเอาไว้แต่แรกแล้วว่า ต้องการจะให้มันเป็น Browser Source บน OBS หมายความว่า เราจะสามารถ อัดภาพหน้าจอ หรือ LIVE โดยที่มี Overlay เป็น ข้อมูลต่างๆ ของเครื่องได้ โดยไม่ต้องถูกจำกัดด้วยการแสดงผลที่เหมือนกันหมด ของโปรแกรมอื่นๆ ที่เคยมีมาแบบนี้
แล้วก็ไม่ต้องให้มันแสดงในหน้าจอตอนเราเล่นเกมของเรา ให้เสียอรรถรสด้วยยังไงละ!
ที่สำคัญก็คือ มันสามารถ Customize การแสดงผลเองได้ทุกอย่าง โดยการแก้โค๊ด HTML ง่ายๆ เองจ้า~!!!
เริ่มใช้งาน SystemZ
สำหรับโปรแกรม SystemZ นั้น จะเป็นส่วนหนึ่งของ SystemX สามารถดูในโพส SystemX เพื่อดูวิธีการติดตั้งได้เลย
หลังจากติดตั้งแล้ว เมื่อเปิด SystemX ขึ้นใช้งานครั้งแรก โปรแกรมจะถามให้ลงทะเบียน ก็สามารถปิดไปได้เลย เพราะว่าโปรแกรม SystemX จะออกแบบมาเพื่อใช้งานคู่กับเครื่อง LEVEL51 ถ้าเป็นเครื่องยี่ห้ออื่นก็จะไม่ค่อยเกี่ยวข้องเท่าไหร่ ไม่ต้องลงทะเบียนก็ได้ :) ส่วนถ้าเป็นเครื่อง LEVEL51 โปรแกรมจะลงทะเบียนตัวเองได้อัตโนมัติ ไม่ต้องทำอะไร แต่ว่าถ้าไม่สามารถเข้าใช้งานได้ สามารถแจ้งมาทาง Inbox ให้เราลงทะเบียนให้ได้นะ
หลังจากเปิดใช้งาน SystemX แล้ว ใน Tray จะมีไอคอนรูป 51 โผล่ขึ้นมา ให้คลิกขวาที่ไอคอนนี้ แล้วเลือก SystemZ Link
จะเป็นการเปิดหน้า Browser ขึ้นมาและในหน้าจอจะแสดง QR Code สามารถใช้มือถือ ส่อง QR Code นี้ เพื่อรับ Link ที่ใช้ในการเปิดดู SystemZ ได้เลย โดยมือถือ จะต้องต่ออยู่ในเครือข่ายเดียวกันกับเครื่องที่เปิด SystemX นะ (เช่น ถ้าเครื่องที่เปิด SystemX เสียบสาย Lan อยู่กับ Router ที่บ้าน ก็มือถือ จะต้องต่อ WiFi ที่อยู่ในเครือข่ายเดียวกันนี้ด้วย)
ส่วนถ้าจะต้องการต่อดูจากข้างนอกผ่านอิินเตอร์เน็ต ก็สามารถทำได้นะ โดยไป Forward Port ที่ Router ให้มาที่ Port 5293 ของเครื่องนี้ วิธีการ Forward Port ยังไม่ขอกล่าวถึงในโพสนี้แล้วกัน เดี๋ยวมันจะนอกเรื่องเกินไป :) ปล. ตอนที่กดเปิดดู QR Code ครั้งแรก ตัว SystemX จะทำการเปิด Port นี้ใน Firewall ของ Windows ให้อัตโนมัติแล้ว
หลังจากนั้น ในมือถือ ก็สามารถเปิดดู SystemZ ได้เลย และแน่นอนว่า ถ้าจะเปิดดูด้วย Browser ในเครื่องด้วย ก็ได้เหมือนกัน โดยการใช้ลิงค์นี้
http://localhost:5293/systemz/index.html (จริงๆ เดี๋ยวไปทำปุ่มใส่ไว้ในหน้า QR Code ด้วยดีกว่า เพิ่งนึกได้...)
สำหรับท่านที่ Network เครื่องซับซ้อนกว่านี้ เช่น มีหลาย Private IP, ลง VMWare/VirtualBox ไว้ ตัวโปรแกรมจะเลือกเอา IP ตัวแรกที่เป็น IPv4 ออกมานะ อาจจะได้ IP ที่ไม่ถูกต้อง อันนี้ต้องใส่ IP ของเครื่องเองนะ
วิธีการใช้งาน
การใช้งานของ SystemZ ก็ตรงไปตรงมามาก หน้าจอแรก จะแบ่งออกเป็นสองส่วนหลัก ก็คือ
- กราฟประวัติ ขออนุญาตเรียกมันว่าเป็น กราฟ Timeseries นะ เป็นชื่อที่เดี๋ยวจะใช้เรียกตอนปรับแต่งอีกที ในกราฟนี้ จะมีการแสดงผล 3 เส้น
- สีฟ้า (ที่ดูดสีมาจากเว็บ Intel) คือ อุณหภูมิ ของ CPU หน่วยเป็นองศาเซลเซียส กราฟเป็นเสกล 0 - 100 ดังนั้นถ้ามันอยู่ตรงกลางๆ แสดงว่าความร้อนประมาณ 40-50c
- สีเขียว (ที่ดูดสีมากจากเว็บ Nvidia) คือ อุณหภูมิ ของ GPU
- สีแดง (อันนี้จิ้มสีมั่วมา) คือ ประวัติ Frame Per Second (Fps) ของโปรแกรมที่อยู่หน้าสุดในตอนนั้น แต่ปกติเส้นสีแดงจะไม่แสดงออกมา นอกจากจะเลือกตัวเลือก FPS Counter ในไอคอน 51 ไว้นะ
ในการเปิดให้ SytemX จับ Frame Per Second ออกมาด้วย จะต้องไปคลิกตัวเลือก "FPS Counter" ในไอคอน 51 ก่อน โดยวิธีการจับ Fps ผมใช้วิธีเดียวกับโปรแกรม PresentMon ของ Intel คือการใช้ระบบ ETW ของ Windows ซึ่งมี Impact กับประสิทธิภาพของเกม น้อยกว่าการใช้ Dll Injection/Dll Hook แบบที่หลายโปรแกรมชอบใช้กัน (เช่น Fraps, RivaTuner Statistics Server) แต่มันก็ยังมีอยู่บ้าง และก็ไม่จำเป็นจะต้องเปิดไว้ตลอด ถ้าเกิดไม่ได้คิดจะใช้งาน เนื่องจากว่า ปัจจุบันนี้ หน้าจอของโปรแกรม Windows ก็ใช้ DirectX ในการแสดงผล ดังนั้นมันจะมีผล Fps ออกมาตลอดเวลาเลยโดยที่ไม่จำเป็นจ้า อย่างโปรแกรม Battle.net นี่ ก็วาดหน้าจอด้วย DirectX เหมือนกัน
ปล. SystemX ไม่ได้ใช้โปรแกรม PresentMon นะ ใช้การคุยกับ ETW โดยตรงจ้า
ส่วนล่างลงมา จะเป็น Panel ที่แสดงข้อมูลคล้ายๆ กัน แต่ว่าแสดงเป็นตัวเลข พร้อมกับกราฟโค้งๆ ครึ่งวงกลม ที่จะเรียกมันว่า Gauge (อ่านว่า เกจ)
- เกจสีฟ้า คือ CPU Utilization/Load ถ้ามันวิ่งมาเกือบเต็ม หรือเต็ม ก็แสดงว่า CPU ใช้งานอยู่ 100% และเลขที่เป็น GHz ก็คือความเร็วในขณะนั้น
- เกจสีเขียว คือ GPU Utilization/Load โดยดูจาก Graphics Core อย่างเดียวนะ เดี๋ยวนี้มันมี Memory Unit Load, Video Unit Load ด้วย ไม่ได้เอามาคิดรวมกัน
- เกจสีแดง คือ ระดับของ Fps ถ้าเต็มแสดงว่าตอนนั้น Fps เกิน 100 หรือมากกว่า ถ้ามันอยู่กลางๆ แสดงว่า Fps ตอนนั้นอยู่ประมาณ 50-60 จัดว่าภาพลื่นใช้ได้ ถ้าเกิดว่าไปเกือบเต็ม ก็คือโคตรลื่น
- ตัวเลขตรง Frame Time (Avg) จะแสดงชื่อโปรแกรม ที่ตอนนั้นกำลังทำงานอยู่บนสุด (Foreground Window) อย่างถ้าเราเปิดเกมไว้ แต่ว่าไม่ได้คลิกไปที่จอ มันก็จะไม่นับออกมาให้ เลขนี้เป็น ระยะเวลาระหว่างภาพ (เฟรม) หนึ่งภาพในเกม หน่วยเป็นมิลลิวินาที (ms) แน่นอนว่า เลขยิ่งน้อย ก็ยิ่งดี โดยเลขที่แสดงเป็น ค่าเฉลี่ย (Average, Avg) จากประมาณ 1 วินาที หรือ 100 เฟรมที่ผ่านมา ถ้าเกิดว่า Average ค่อนข้างนิ่ง ถือว่าดี โดยเราเอา Average นี้ ไปคำนวณเป็น Fps อีกที ว่าโดยเฉลี่ยใน รอบที่ผ่านมา ได้ประมาณกี่เฟรมต่อวินาทีจ้า
ถ้าเกิดว่า Geek กว่านั้น จะมีหน้าอีกหน้านึง เรียกว่า Sensor เอาไว้ดูข้อมูล Sensor ทะั้งหมด ที่ SystemX อ่านออกมาได้ด้วยเลย (ซึ่ง SystemX จะใช้ Library ที่ชื่อว่า OpenHardwareMonitor ซึ่งผม Fork มาแก้อะไรนิดหน่อยเพื่อให้ใช้กับ SystemX ได้สะดวก
สำหรับการใช้งาน SystemZ เพื่อดูข้อมูล ก็จะประมาณนี้ มีอะไรแพลนไว้ว่าจะทำอีกหลายอย่าง เดี๋ยวต้องรอจังหวะอีกที :D
วิธีการใช้ SystemZ Overlay
OBS จะมี Source ชนิดที่เรัียกว่า Browser Source ซึ่งเราสามารถเอาหน้าเว็บ มาแสดงผลซ้อนไปบน Stream (หรือ Record) ของเราได้ อย่างที่บอกไว้ก่อนหน้านี้ว่า ที่ผมออกแบบใหเ SystemZ เป็นเว็บ ก็เพราะว่าจะให้มันสามารถทำเป็น Overlay ได้ ก็เพราะแบบนี้ยังไงละ
ขั้นตอนแรก ให้ไป Copy ไฟล์ overlaysample.html ที่อยู่ใน My Documents / SystemX ออกมาก่อน ไฟล์ overlaysample.html จะถูกเขียนทับทุกครั้ง ที่ SystemX เริ่มทำงานใหม่ ดังนั้น อย่าไปแก้ไฟล์นี้ละ แล้วก็ตั้งชื่อเป็นชื่อที่จะพิมพ์ง่ายๆ เช่น timeseries.html
วีธีทำก็คือ กดสร้าง Scene ใหม่ขึ้นมา แล้วกดปุ่ม + ตรง Source
ฺจากนั้น ใส่ URL ว่า http://localhost:5293/timeseries.html ในช่อง ตัวโปรแกรม OBS จะแสดงผลเป็นกราฟ timeseries ขึ้นมาเลย แบบนี้
ส่วนถ้าสงสัยว่า ทำไมไม่ใช้เป็น Local File นั่นก็เพราะว่า ถ้าเราเปิดไฟล์ .html ด้วยที่อยู่ในเครื่อง เช่น C:\sample.html แบบนี้ ตัว Browser จะมีการแบ่ง Zone การทำงาน ซึ่งอาจจะทำให้อะไรบางอย่างใช้งานไม่ได้ ใน SystemX ก็เลยมีการฝัง Application Server ไว้ในตัว (เป็น NancyFx ที่ใช้ระบบ HttpListener ของ Windows) การเรียกผ่าน URL ที่เป็น http:// แบบนี้ จะทำให้เราสามารถใช้ความสามารถทุกอย่างของการเขียนเว็บได้ครบชัวร์ๆ ครับ
วิธีการแก้ไข Overlay (หรือวิธีเขียน HTML/CSS/AngularJS เบื้องต้น!)
แต่ก่อนผมเขียน Tutorial ไว้เยอะมากในเว็บส่วนตัวที่ชื่อ CoreSharp.net (ตอนนี้ปิดไปละ มันมีแต่ข้อมูลเก่า) คิดถึงเหมือนกันนะเนี่ย :D โพสนี้ผมขอสอนวิธีการเขียน HTML/CSS/AngularJS แบบสั้นๆ เท่าที่พอจะใช้ในการแก้ไขตัว Overlay ละกันนะ
สำหรับวิธีที่ดีที่สุด ในการจะหัดเขียนอะไรซักอย่าง ก็คือเราจะต้องตั้งเป้าหมายขึ้นมาก่อน สำหรับเป้าหมายวันนี้ เราจะทำการทำ Overlay ขึ้นมา ตาม Design ของ Overlay ของโปรแกรม RivaTuner มา โดยใช้ระบบ ของ SystemZ อันนี้เป็นภาพ Reference ที่ผมค้นจาก Google มาด้วย Keyword "rivatuner overlay" เอาละ มาดูกันว่าจะต้องทำยังไงบ้าง
ทำความรู้จักกับภาษา HTML ก่อน
เครื่องไม้เครื่องมือที่เราจะใช้ ก็คือ Visual Studio Code นี่ปี 2019 แล้ว จะมามัวเขียนเว็บด้วย Notepad ไม่ได้แล้วนะ! กดลิงค์ดาวน์โหลดมาลง เปิดขึ้นมา แล้วก็ลากไฟล์ timeseries.html ที่เรา Copy ออกมา ไปวางได้เลย
สิ่งที่เราเห็นในไฟล์ HTML นี้ มองแล้วอย่าเพิ่งไปตกใจ มันเป็นภาษาที่เราใช้คุยกับ Browser เพื่อควบคุมการแสดงผล เรียกว่าเป็นภาษาแบบ Mark Up ก็คือ เราจะให้การแสดงผลออกมาเป็นยังไง เราก็เอาภาษานี้ ล้อมกรอบตัวอักษรที่เราต้องการไป
ก่อนอื่นเลย เพื่อให้หน้าจอโค๊ด ดูไม่ยุ่งเกินไปจนน่ากลัว เราสามารถ พับ (Fold) โค๊ดบางส่วนออกไปได้ โดยเอาเมาส์ชี้ไปที่ด้านหลังตัวเลขบรรทัด แล้วคลิกที่ปุ่ม - ข้างหน้า เพื่อพับ หรือถ้าจะเปิดมันออกมาใหม่ ก็กดปุ่ม + หรือคลิกไปบริเวณที่โดนพับอยู่
พอพับทุกอย่างจนหมดแล้ว จะเห็นโครงสร้างของไฟล์ timeseries.html ชัดเจนขึ้น
เริ่มจากบรรทัดที่เขียนว่า DOCTYPE html อันนี้เป็นการระบุว่า ไฟล์นี้ เป็นภาษา HTML เวอร์ชั่น 5 สมัยก่อนจะมีหลายเวอร์ชั่น แต่ตอนนี้้เราไม่ต้องไปสนใจแล้ว (มันเป็นเรื่องเมื่อสิบปีก่อน) ใส่แค่ html เฉยๆ รู้กัน
พอเรากาง html ก็จะเห็นว่า มันเป็น <head> กับ <body> ที่อยู่ข้างใน <html> อีกที html, head, body นี้ เรียกว่า Tag และจะเห็นว่า ลักษณะของ Tag คือ มันสามารถอยู่ซ้อนกันได้
พอลองกาง body ออกมา ก็จะเจอว่ามี Tag div กับ script อยู่ข้างใน และมีข้อความเขียวๆ อยู่ สีเขียวๆ นี้เรียกว่า Comment เอาไว้เขียนอธิบายเสริมในโค๊ดของเรา ว่ามันคืออะไร เราเขียนอะไรไป บางทีหลายท่านจะเขียนโค๊ดซับซ้อนมาก อ่านแล้วก็ไม่ค่อยเข้าใจ การมี Comment แบบนี้ จะช่วยให้อ่านโค๊ดง่ายขึ้น
ขยับมาดูที่บรรทัด 103 อยู่ (สามารถกด CTRL+G แล้วพิมพ์เลข 103 ลงไปก็ได้) จะเห็นว่ามันเป็น Tag div ที่ครอบ canvas อยู่
พอจะเดาออกมั๊ยว่า canvas มันคืออะไร? :D ถ้าเดาไม่ออก ลองลบมันออก (ตั้งแต่บรรทัดที่ 105-129) จากนั้นกดเซฟ (CTRL+S) แล้วเปิด http://localhost:5293/timeseries.html ด้วย Chrome (หรือ Browser อื่นๆ) ดู จะพบว่า กราฟมันหายไปละ กลายเป็นหน้าว่างๆ ไปเลย แบบนี้
ภาษา HTML ก็จะเป็นประมาณนี้ คือ เรามี Tag ซ้อนกันไปเรื่อยๆ แต่ละ Tag จะมีหน้าที่ของมันว่ามีันจะแสดงผลอะไรออกมา และจะมีการแสดงผลอย่างไรบ้างในเบื้องต้น เช่น ถ้าเราต้องการแสดงผลข้อความว่า สวัสดี เป็นตัวหนา เราก็จะเขียนแบบนี้
<strong>สวัสดี</strong>
ก็ลองพิมพ์ลงไประหว่าง Tag div ได้เลย สังเกตว่า ตอนพิมพ์ ก็จะมี Auto Complete ขึ้นมาให้ด้วย พอ Auto Complete มันเลือกตัวที่ใช่ให้เราแล้ว ก็กด ปุ่ม Tab เพื่อให้มันพิมพ์จนจบให้เราได้เลย เหลือเพียงแค่พิมพ์ > ลงไป ตัว Visual Studio Code ก็จะพิมพ์ Tag ปิดข้างหลังให้เราเรียบร้อย
และจะเห็นว่า ระหว่างที่เราพิมพ์ ตรง </div> จะขึ้นเป็นสีแดง แปลงว่า เรายังเขียนอะไรบางอย่างไม่เรียบร้อย เพราะว่า tag จะต้องมี <div> (เปิด Tag) กับ </div> (ปิด Tag) แบบนี้คู่กันเสมอ
และฝึให้ชิน ก็คือ เราสามารถแบ่งครึ่งจอ โดยการกดปุ่ม Windows + ลูกศรซ้าย หรือ ลูกศรขวา เพื่อจัดให้หน้าต่างพิมพ์โค๊ดของเรา วางคู่กับหน้าต่าง Browser ได้แบบนี้ พอพิมพ์โค๊ดจบแล้ว เราก็สามารถกด CTRL+S เพื่อเซฟ, ALT+TAB เพื่อสลับไปหน้าจอ Browser จากนั้นกด CTRL+F5 เพื่อ Force Refresh หน้าต่าง Browser ได้เลย ทำแบบนี้จนชิน จะทำให้เราเขียนได้คล่องขึ้น
สำหรับ Tag ของ HTML จะมีด้วยกันสองแบบ คือ
- Block เช่น div p h1 h2 h3 h4 h5 h6 ul ol li section Tag ที่เป็นแบบนี้ มันจะกินพื้นที่ไป 1 บรรทัดเต็มความกว้างของหน้าจอ
- In-line เช่น span b u i o Tag แบบนี้ มันจะเป็นข้อความ ที่อยู่ภายในบรรทัด นั่นก็คือ เราจะเอา span ไปครอบ div ไม่ได้ แต่ว่า span อยู่ใน div ได้
ซึ่งจริงๆ มี Tag เยอะกว่านี้มาก แต่ที่เราใช้บ่อย จะมีแค่ที่ยกตัวอย่างไปเท่านี้แหละ อยากรู้ว่ามันจะออกมาหน้าตาเป็นยังไง ก็ลองพิมพ์ดูในโค๊ดเลย เพียงแค่ว่า li จะต้องอยู่ใน ol อยู่ ul เท่านั้นนะ ลองดูว่าได้ผลเป็นยังไง
ทีนี้เราลองมา ลองดูภาพ Reference นี้ประกอบอีกที ว่าเราจะเขียนมันออกมาเป็น Tag HTML ได้อย่างไร
จะเห็นว่า ข้อความมีอยู่ 5 บรรทัด เราจะสนใจแค่บรรทัดแรกก่อนนะ
ในบรรทัดนี้ เราสามารถมองว่า มันถูกแบ่งออกเป็น 7 ส่วน แบบนี้
หรือ เราจะมองว่า มันแบ่งออกเป้น 4 ส่วน และข้างใน 3 ส่วนหลัง มีส่วนที่มันเป็นหน่วยอยู่ แบบนี้ก็ได้
จุดสังเกต:
- Tag sup เป็น Tag อีกตัวนึง แบบ Inline ซึ่งมันจะทำให้ตัวอักษรเป็ีน Superscript (ตัวยก)
- เราจะวางโครง Tag ยังไงก็ได้ ตามแต่ที่เราชอบ
- เวลาที่เราเอา Tag ซ้อนกัน เราจะกด Tab ให้มันขยับไป ซึ่ง Visual Studio Code ก็จะแสดงเส้นนำสายตาให้เราด้วย เพื่อให้เราอ่านโค๊ดได้สะดวกขึ้น
ส่วนถ้าเป็นผม ผมจะเลือกแบบที่สอง เพราะว่ามันดูเป็นระเบียบดี ลองเขียนตามแบบที่สองแล้วรีเฟรชดู จะได้ผลออกมาแบบนี้ เห็นมั๊ยว่ามันออกมาคล้ายกับตัวอย่างเลย
Attribute และ CSS
โอเค มันมี การแสดงผลออกมาละ แล้วถ้าเราจะปรับเปลี่ยนการแสดงผลออกมาตามใจเราละ จะทำยังไง? เราจะใช้ Attribute (คุณลักษณะ) คู่กับ Style Sheet สมมุติว่า อย่างแรกเลย ก็คือ GTX 980 มันควรจะเป็นสีเขียวสด และตัวอักษรสามกลุ่มข้างหลัง ควรจะเป็นสีขาว เราก็จะต้องใช้ Attribute เพื่อบอกกับ Browser ว่าเราต้องการแบบนี้
- style คือ Attribute ที่เอาไว้เติมลงไปใน Tag โดยแต่ละ Tag ก็จะมี Attribute เฉพาะของมัน แต่ว่า ในปัจจุบันนี้ เราเลือกที่จะเลือกใช้ Attribute ประจำ Tag แล้ว เพราะว่าเราจะต้องมานั่งจำว่า แต่ละ Tag มันมี Attribute อะไรบ้าง เราจะใช้ตัวกลางเลยคือ style
- "color: lime" (กล่องสี่เหลี่ยมที่เป็นสี มันจะแสดงขึ้นมาเองนะ) ส่วนนี้คือ Style Sheet เป็นอีกภาษาที่อยู่คู่กับ HTML เรียกว่า CSS โดยภาษานี้ไม่มีอะไรมาก เป็นการกำหนดคุณสมบัติเหมือนกัน โดยทุก Tag สามารถใช้คุณสมบัติชุดเดียวกันได้หมด อย่างเช่นถ้าเรากำหนด Attribute color ถ้ามันไปอยู่ใน Tag ที่มีการแสดงตัวอักษร ก็จะเป็นการกำหนดว่า สีตัวอักษร จะเป็นสีตามที่เรากำหนด นั่นเอง
สีของ CCS เดิมจะใช้เขียนเป็นเลขฐาน 16 แต่สมัยนี้ เราจะนิยมเขียนเป็นคำว่า rgba(255,255,255,1) แบบนี้กันแล้ว โดยเราสามารถใช้ Google จิ้มสีได้เลย แบบนี้
แต่ของ Google จะแสดงเป็น RGB เฉยๆ ไม่มี A ตัว A ที่เพิ่มเข้ามาจะมีค่าตั้งแต่ 0.0 0.1 0.2 0.3.....1 อันนี้เป็นตัวกำหนดความใส อย่างเช่นถ้าเราต้องการให้บรรทัดแรกของเรามีพื้นสีดำ แต่ว่า ให้มันใสทะลุไปข้างหลัง 50% เราก็ไปเติม style ไว้ใน div ที่คลุมข้อความบรรทัดแรกของเรา แบบนี้ (ถ้าต้องการ 10% ก็ใส่ 0.1 แทนที่จะเป็น 0.5 เป็นต้น)
แล้วถ้าจะให้ตัวอักษรทุกตัว เป็นสีขาว เราก็จะต้องไปเติม CSS ลงไป และถ้าจะให้มันมีเงาด้วย เราจะใช้ text-shadow แบบนี้ ลองเเปลี่ยนแลข 1, 2, 3 ดูนะว่า มันให้ผลแตกต่่างกันไปอย่างไร
color: white; text-shadow: 1px 2px 3px black
โดยหลังจากเราใส่ลงไปทั้งหมดแล้ว จะเห็นว่า โค๊ดเรายาวขึ้นกว่าเดิมมากเลย ว่ามั๊ย? แล้วถ้าจะไปเปลี่ยนให้ Style ของทุกตัวเหมือนกัน เราก็จะต้องนั่งแก้ทีละตัว นี่แค่บรรทัดเดียวนะ ถ้าเขียนเสร็จหมดทุกบรรทัด แล้วต้องมานั่งแก้ทีละตัวแบบนี้ ตายพอดี
วิธีการใช้ LESS Stylesheet
เพื่อให้เราสามารถกำหนดการแสดงผลได้ง่ายขึ้น เราจะใช้สิ่งที่เรียกว่า Stylesheet มาช่วย มันก็คือไฟล์ ที่กำหนด Style อย่างเดียว แต่ปัจจุบันเรามีภาษาที่เหนือกว่า CSS ไปอีก ชื่อว่า LESS ซึ่งผมจะใช้ภาษานี้ ในการเขียน เพราะว่ามันเขียนคล้ายกับ CSS เดิม แต่ว่าทำอะไรได้มากขึ้น
เริ่มจาก เราต้องสร้างไฟล์ใหม่ขึ้นมาก่อน ใช้เมนู File -> New แล้วเซฟไฟล์ใหม่นี้ว่า style.less เอาไว้ที่เดียวกันกับไฟล์ timeseries.html
จากนั้น เราจะต้องทำการ Link ไฟล์ style.less เข้าไฟล์ timeseries.html โดยการไปที่ tag head ของไฟล์ timeseries.html ตามนี้ แล้วใส่โค๊ดพวกนี้ลงไป
<link rel="stylesheet/less" type="text/css" href="style.less" />
<script src="
//cdnjs.cloudflare.com/ajax/libs/less.js/3.9.0/less.min.js"></script>
ข้อสังเกต
- tag link นั้น ไม่มีปิด tag แต่ว่าเป็น /> แทน อันนี้หมายถึงว่า เป็น Tag แบบที่ไม่มีไส้ เป็น Tag ที่ไม่มีเนื้อหาอะไรข้างใน
- href="style.less" เราไม่ต้องใส่ชื่อ Path อย่าง C:\Windows\ หรือ http:// อะไรทั้งสิ้น ใส่แต่ชื่อไฟล์ หมายถึงว่า ให้เอาไฟล์ ที่อยู่ใน Folder เดียวกันกับไฟล์ html ที่เรากำลังเปิดอยู่ในตอนนี้ เนื่องจากไฟล์ timeseries.html ตอนนี้เราเปิดมาจาก http://localhost:5293/timeseries.html ตัว Browser ก็จะทำการโหลดไฟล์ style.less มาจาก http://localhost:5293/style.less (ลองเอาไฟล์ใส่ folder แล้วหาทางเรียกมันมาใช้ให้ได้ดูสิ)
- src="//cdnjs..." จะเห็นว่าไม่ได้ใช้คำว่า http:// ใช้้แค่ // ข้างหน้า อันนี้หมายถึง ให้ใช้ Protocol ปัจจุบัน ในการดาวน์โหลดไฟล์ less.min.js มาให้ เนื่องจากว่าหน้านี้้ เราเปิดด้วย http:// ก็จะเป็นการใช้ http:// ด้วยเหมือนกัน
เมื่อพร้อมแล้ว เราก็มาเริ่มเขียน LESS กันต่อ ซึ่งจุดประสงค์เดียวเลยของไฟล์ style.less นี้ ก็คือการใส่ Style ให้กับไฟล์ HTML ที่มันเชื่อมกันอยู่
สมมุติว่า เราจะให้ตัวอักษรของ tag span ทั้งหมด เป็นสีแดง ให้พิมพ์แบบนี้ อ้าว ทำไมไม่เปลี่ยน?
แต่แบบนี้กลับได้ (เติม !important ลงไป)
นี่คือที่มาของชื่อภาษา CSS เลยแหละ มันย่อมาจาก Cascading Style Sheet แปลว่ามันจะกระทบชิ่ง (Cascade) กันได้ สำหรับกรณีแรก ที่ สีแดงของเราไม่มีผล ก็เพราะว่า เรามีการกำหนดสีเอาไว้ ใน Tag span อยู่แล้ว แต่พอเราบอกว่า มัน !important มากเลยนะ Style ของเรา เลยถูกใช้
แน่นอนว่า เราคงจะไม่ต้องการที่จะให้ span ทุกตัวเป็นสีแดง เราเลยจะต้องมีการใช้ CSS Selector เข้ามาช่วย พร้อมกับการแก้ไข HTML ด้วย เพื่อให้มันรองรับกัน
CSS Selector
เริ่มแรก เราก็จะลบ style ยุ่งๆ เมื่อกี้ที่เราเพิ่มเข้าไปออกก่อน เหลือแต่โครงสร้างว่างๆ สวยๆ แบบตอนแรกเอาไว้ แล้วเราก็ต้องหาทางที่จะ "เลือก" ให้เฉพาะ tag ที่เราต้องการ ได้รับ Style ที่เราตั้งเอาไว้แทน ซึ่งการเลือก จะทำได้หลักๆ สองแบบ
- การใช้ Attribute id หรือ class โดย id จะเหมาะกับ tag ที่มีแค่ tag เดียว เพราะว่า id นั้น ไม่ควรจะซ้ำกัน และ class จะเหมาะกับ tag ลักษณะเดียวกัน แต่มีซ้ำๆ กัน
- การใช้ ความสัมพะันธ์ระหว่าง tag เช่น tag span ที่อยู่ข้างใน div เป็นต้น
เวลาที่เราใช้งานจริง เราจะใช้ทั้งสองอย่างนี้ ผสมกัน อย่างในกรณีตัวอย่าง ภาพนี้
สิ่งที่เราต้องการ ก็คือ
- สองบรรทัดแรก ตัวอักษรกลุ่มแรกของแถว เป็นสีเขียว นอกนั้นสีขาว (ถ้ายังจำได้ เราแบ่งออกเป็น 4 กลุ่ม)
- สองบรรทัดต่อมา ตัวอักษรกลุ่มแรกของแถว เป็นสีส้ม นอกนัี้นสีขาว
ดังนั้น เราก็จะเขียน CSS Selector แบบนี้
- .greenrow สังเกตว่า มีจุดอยู่ข้างหน้า หมายถึงว่า ให้ tag อะไรก็ตาม ที่มี Attribute class ที่มีคำว่า greenrow อยู่ (เราสามารถใส่ class มากกว่า 1 class ก็ได้นะ)
- สำหรับการเขียน Style สำหรับ Id เราไม่ได้ใช้ในตัวอย่างนี้ แต่ถ้าจะใช้ เขียนว่า #box ถ้า Tag เราใส่ Attribute ว่า id="box"
- > span หมายถึง tag span จะต้องอยู่ข้างใน tag ที่มี class ว่า greenrow
- > span:first-child หมายถึงว่า tag span ที่อยู่ใน class greenrow เฉพาะ tag อันแรกเท่านั้น อันต่อไปไม่เกี่ยว
- span โดยไม่กำหนดอะไรเลย หมายถึง tag span ทุกตัว
สังเกตผลลัพทธ์ที่ออกมา
สังเกตว่า
- เฉพาะ span ที่เป็นตัวแรก มีสีตามที่เรากำหนด
- span ที่ไม่ตรงตาม Selector นั้น มีสีขาว
- span ทุกตัว มีเงา (text-shadow) เหมือนกันหมด
ที่เป็นแบบนี้ก็คือ Selector Rule ที่มีความเจาะจงกว่า จะไปทำการตั้งค่า Style ทับกับ ตัวที่เจาะจงน้อยกว่า อย่างแรกก็คือ span ทุกตัวจะเป็นสีขาว และมีเงา แต่ว่า ด้วย Selector ที่เจาะจงของเรา มันเลยไปเปลี่ยนสีขาวเป็นสีเขียว และสีส้ม ตามลำดับ แต่ว่าเงายังคงอยู่ตามเดิม
ถ้าเราเขียนด้วย LESS จะเขียนได้เป็นแบบนี้ สังเกตว่า การเขียนแบบ LESS จะใกล้เคียงกับโครงสร้างจริง ของ HTML ทำให้อ่านเข้าใจง่ายกว่า แบบนี้
และข้อดีอีกอย่างก็คือ ถ้าเราต้องการจะเขียน Selector ที่ซ้อนกันแบบนี้บ่อยๆ เราไม่ต้องเขียนข้างหน้าซ่้ำหลายรอบ สมมุติว่า ถ้าต้องการจะเปลี่ยนสีของ span ตัวสุดท้ายด้วย ถ้าจะเขียนด้วย CSS เราจะต้องเขียน Selector .orangerow > span:firstchild กับ .orangerow > span:last-child ซึ่งมี .orangerow ซ้ำกัน แต่ถ้าเขียนแบบ LESS เราสามารถซ้อนลงไปข้างใน .greenrow ได้เลย
ส่วนทางในด้านของ HTML เราก็แค่ไปเพิ่ม class greenrow กับ orangerow เอาไว้ใน div ของบรรทัดต่างๆ ตามนี้
และลองฝากให้หาทาง เขียน Style ให้ได้ผลออกมาแบบนี้ดูนะ ใบ้ให้ว่า ต้องเพิ่ม Selector สำหรับ sub และใช้ line-height, vertical align, padding, background-color ช่วยในการทำให้ตัวอักษรออกมาแบบนี้ และมีกรอบสีดำโปร่งๆ แบบนี้
Angular Binding เบื้องต้น
เอาละ เรารู้จักกับ tag และ Attribute กันแล้ว และเราก็เขียน Style กันพอได้แล้ว ต่อไปก็ ต้องเอาข้อมูลออกมาแสดงจริงๆ กันซะทีนะ
อย่างแรกเลย สังเกตดูว่า จะมี div ที่มี attribute ชื่อว่า ng-controller อยู่ tag นี้ เป็นตัวเชื่อมระหว่างโค๊ด JavaScript ของ SystemZ ที่ผมเขียนเอาไว้ เข้ากับไฟล์ HTML โดยกำหนดว่า div ตัวนี้ จะเป็นการใช้งาน Controller หรือ ตัวควบคุม ที่ชื่อว่า SystemZ และภายใน Tag นี้ทั้งหมด จะอยู่ใน Scope (ขอบเขต) ของ Controller ตัวนี้
สำหรับ Controller ตัวนี้ ผมได้สร้าง ตัวแปรเอาไว้ให้ 3 ตัวด้วยกัน คือ
- telemetry เป็นตัวแปร ที่เก็บข้อมูลแบบสรุป ของอุณหภูมิ ความเร็ว CPU/GPU ในตอนนั้น
- sensor เป็นตัวแปรที่รวม Sensor ทั้งหมด ที่ SystemX อ่านออกมา
- fpsProcess เป็นตัวแปรที่เก็บข้อมูลเกี่ยวกับ fps ทั้งหมด
ซึ่งการจะเอาตัวแปรพวกนี้มาใช้ เราจะใช้การเขียน Binding Expression ซึ่งเป็นโค๊ดภาษาพิเศษของ AngularJS ที่คล้ายๆ กับ JavaScript ลงไปใน HTML เลย โดยเพื่อความไม่งง แนะนำให้ Copy ไฟล์ overlaysample.html ออกมาเป็นไฟล์ใหม่อีกไฟล์ เพื่อทดลองเขียนก่อน
เริ่มจากลองพิมพ์ ลงไปก่อน ระหว่าง tag div อันนี้แปลว่า ให้แสดงผลตัวแปรที่ชื่อ sensors ออกมา เราจะได้ผลลัพทธ์ออกมาเป็นข้อความแปลกๆ และที่สำคัญคือมันจะเปลี่ยนไปเรื่อยๆ เองด้วยนะ
ที่เห็นเป็นข้อความแปลกๆ นั้นคือ JSON (JavaScript Object Notation) มันเป็นรูปแบบการแสดงผลข้อมูลแบบหนึ่งที่มีโครงสร้าง เป็นที่นิยมใช้กันทั่วไปในปัจจุบันนี้ วิธีการง่ายๆ เลย ที่จะรู้ว่า หน้าตาของข้อมูลมันมีอะไรบ้าง ก็คือ สร้าง tag ชื่อ textarea ขึ้นมา แล้วใส่ Binding Expression ไว้ตรงกลาง เราจะได้กล่องเอาไว้พิมพ์ ที่สามารถ CTRL+A, CTRL+C ข้อมูลออกมาได้ง่ายๆ แบบนี้
แล้วก็เอาไปวางในเว็บ JsoneditorOnline.org เพื่อดูโครงสร้างของมันได้ โดยการ Paste ลงไป
แต่สำหรับข้อมูลเบื้องต้นทั่วไป ไม่จำเป็นต้องไปไล่หา Sensor รายตัว เพราะว่า SystemX จะสรุปในเบื้องต้นมาให้แล้ว อยู่ใน ตัวแปรที่ชื่อ telemetry ซึ่งมีโครงสร้างแบบนี้
กลับมาที่หน้า timeseries.html ของเรา ที่เราเขียน Style ค้างไว้ ถ้าเราจะให้มันแสดงเป็นข้อมูลจริงๆ ออกมา ก็เพียงแค่ไปเปลี่ยนข้อความหลอกที่เราพิมพ์ไว้ ให้เป็น Binding Expression แบบนี้
จุดสังเกต
- ตัวแปร telemetry นั้นเหมือนเป็นกลุ่มของข้อมูล มันจะมีข้อมูลซ้อนเข้าไปข้างในอีก ข้อมูลแต่ละตัวนี้ จะเรียกว่า Attribute (คำเดียวกับของ HTML) หรือ Property ก็ได้ หมายถึงคุณสมบัติทั้งคู่
- ตัวแปร telemetry ที่เป็นกลุ่มของข้อมูลนี้ เราเรียกว่า Object (อ็อบเจ็กต์) หรือ วัตถุ เป็นตัวแทนของสิ่งที่เรากำลังสนใจ
- การที่เราจะอ่านข้อมูลที่ชื่อว่า GPU ซึ่งเป็นชื่อการ์ดจอออกมา จากวัตถุ telemetry เราจะใช้ จุด คั่น คือ telemetry.GPU ซึ่งเราควรจะได้คำว่า NVIDIA GeForce RTX 2060 ออกมา
- เนื่องจาก คำว่า NVIDIA GeForce RTX 2060 เอง ในภาษา JavaScript ก็เป็นวัตถุอีกชนิดนึง เรียกว่า string หมายถึง ข้อความ วัตถุแบบ string จะมีีการทำงาน (ฟังก์ชั่น) ผูกกับมันอยู่ หนึ่งในฟังก์ชั่นนั้น ชื่อว่า replace ซึ่งเป็นฟังก์ชั่น ที่รับตัวแปรสองตัว ตัวแรก ที่เขียนว่า "NVIDIA GeForce" คือ string ที่จะให้มันเปลี่ยน และ "" (เครื่องหมายฟะันหนูสองตัวติดกัน เรียกว่า Empty String) คือ string ที่จะไปแทนที่ ผลคือเราเลยได้แค่ RTX 2060 ออกมา
- GPU Clock ควรจะได้้เป็นเลขทศนิยม แต่ว่า เรามีการใช้ Filter เพื่อตัดเลขทศนิยมออก เป็น 0 ตำแหน่ง ก็คือไม่มีทศนิยมนั่นแหละ
แต่ในบรรทัดถัดมา จะเกิดปัญหาขึ้นเล็กน้อย เพราะว่า ความเร็วกับปริมาณ VRAM นั้น ไม่ได้อยู่ใน Telemetry แต่ว่ามันมีอยู่ใน Sensors ซึ่งวิธีการเอาค่าจาก Sensor รายตัวออกมา สามารถทำได้โดยการไปเปิดหา Id ของ Sensor ก่อน ด้วย JsonEditorOnline โดยเราจะพบว่า Sensor ที่เราต้องการ คือ GPU Memory Clock, กับ GPU Memory Used
เราสามารถอ่านค่าจาก Sensor ได้ โดยใช้ Binding Expression {{sensors.map[ 'ID ที่ Copy มา' ] }} แบบนี้ นั่นก็คือตัวแปร sensors จะมี Property ที่ชื่อ map อยู่ ซึ่งผมได้ทำการทำให้มันเป็น Mapping แบบที่เราใส่ String ลงไปได้ (string ใน JavaScript จะใช้ฟันหนู หรือเครื่องหมาย ' ก็ได้)
เมื่อทำการค้นหา Sensor เจอทุกตัว เราก็จะได้ผลออกมาแบบนี้ ยินดีด้วย เราสำเร็จครุึ่งทางแล้ว!
การใช้ sz-timeseries Directive เพื่อแสดงกราฟ
นอกจากนี้จะเห็นว่า ในภาพ Reference จะมีกราฟของ FPS อยู่ด้วย เรามาดูกันว่าเราจะทำกราฟแบบนั้นบ้างได้้ยังไง อย่างแรกเลย เราก็จะต้องไป Copy โค๊ดตรงที่เป็น canvas จากไฟล์ overlaysample.html มาวางไว้ก่อน ก็จะมีกราฟออกมาเลยแบบนี้
คงจะพอเดาได้แล้วนะ ว่าตัว Directive นี้ จะเป็น Attribute ที่เอาไว้แปะลงไปใน tag Canvas ซึ่งจะทำให้มันออกมาเป็นกราฟเองอัตโนมัติ (Magic!!!) โดยมี Attribute ต่างๆ มากมาย ซึ่งในตัวอย่างที่เขียนไว้ให้ ก็คือทั้งหมดที่สามารถปรับเล่นได้แล้วนั่นแหละ แต่ว่า Attribute ที่เราจะต้องสนใจ จะมีตามนี้
- watch Attribute นี้จะเป็นตัวแปรที่กำหนดว่า เมื่อไหร่จะให้กราฟอัพเดท โดยตอนนี้จะเห็นว่า มันถูกตั้งเป็น telemetry อยู่ แปลว่า กราฟจะถูกอัพเดท ทันทีที่ค่าของตัวแปร telemetry นั้นเปลี่ยนไป หรือก็คือ หน้าเว็บ SystemZ ได้รับข้อมูลใหม่มาจาก SystemX แล้วนั่นเอง
- Attribute source ของ Tag series จากในโครงสร้าง น่าจะพอเดาได้ว่า tag series จะเป็นตัวกำหนดว่า ในกราฟนี้จะมีเส้นอะไรบ้าง (Series) โดยในตัวอย่าง จะมีสามเส้น คือ CPU GPU และก็ FPS นั่นเอง โดยแต่ละเส้น จะเอาตัวเลขจาก source นี้ มาแสดง
สำหรับตัวแปร fpsProcess ก็มีโครงสร้างตามนี้นะ
โดย Attribute ที่เราจะเปลี่ยน ก็จะมีแต่ source จากเดิมที่เป็น CPU/GPU/FPS ก็เปลี่ยนไปใช้ FrameTimeAvg, Min, Max จาก fpsProcess แทน
เรียบร้อยแล้ว!
ทีนี้ก็เหลือแค่ว่า จะเอา Overlay นี้ไปใช้ยังไง ขอบคุณมาก ที่อ่านมาจนถึงตรงนี้นะครับ หวังว่าจะได้ความรู้เรื่อง HTML / CSS / AngularJS เบื้องต้น ติดไปด้วยนะ
เอาไปใช้ที่ไหน อย่าลืมกลับมาบอกกันบ้างละ!