ทดลองทำเว็บวาดรูปเป็น pixel art ด้วย Svelte แบบง่าย ๆ กันเถอะ
จริงๆก็ดองมาสักพักใหญ่ๆแล้วหล่ะ ตอนนั้นพี่นาตรไลฟ์สตรีมสอนทำเว็บ r/place ที่ให้ช่องแชทพิมพ์ command เพื่อวาดรูปบนสตรีมได้ ทางเราเลยจดมานิดหน่อยแล้วลองทำดูจ้า
อันนี้จะเป็น flow การทำงานของ r/place และ streamie เนอะ ซึ่งในที่นี้ เราจะทำแค่หน้าเว็บที่เป็น r/place เท่านั้น เป็นเว็บที่วาด pixel art ก็แล้วกันเนอะ
อันนี้คือโพยที่มี
ขั้นตอนการทำ
ปล. เนื่องจากบล็อกนี้ร่างไว้นานแล้ว ไม่แน่ใจว่าจุดที่พังจาก svelte เขาแก้ไปหรือยัง
สร้างหน้าเว็บสำหรับ pixel board
ขั้นตอนแรกของพี่นาตร คือ การสร้าง place.svelte
ซึ่งอยู่ใน src/route
แหละ แต่ด้วยความที่ตอนนี้เราทำอยู่ในหน้าเว็บเดียว และไม่รู้ว่าจะมีอะไรยัดไปอีกไหม ก็เลยไปไว้ที่ index.svelte
ไปก่อนแล้วกันเนอะ (หรือทำอันใหม่แล้วแยกโปรเจกดีไหมนะ แบบแยกเรื่องไป)
จริงๆใช้ Tailwind CSS ในการจัด style ของเว็บนี้ แต่เรายังไม่ค่อยคล่องเท่าไหร่ เลยอาจจะจัดให้สวยงามทีหลัง
เอาฤกษ์เอาชัยด้วยการ สร้าง text header ของเว็บไว้ด้านบนก่อน ชื่อว่า Pixel Art Board!
<h1 class="text-center">Pixel Art Board!</h1>
แต่ตอนทำติดปัญหาที่ตัว Svelte Kit เอง ที่ด๊านนน ไม่ดึง %svelte.assets
และผองเพื่อนมาให้ พอนำ error ที่ได้ไป search พบว่าเป็นบัคหรืออัพเดตสักอย่างของเขาเอง
Error: %svelte.assets% in src/app.html should be replaced with %sveltekit.assets%
ดังนั้นจะต้องเปลี่ยนเป็น %sveltekit.assets
พร้อมกับแก้ผองเพื่อนทั้งหมด ถึงจะรันได้ เฮ้อออออ
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>
เมื่อแก้ได้แล้วจะได้หน้าเว็บที่มีคำอยู่ตรงกลางหล่ะ
ส่วนประกอบที่จะทำในหน้าเว็บนี้
เราทำ UI หน้าเว็บนี้ในกระดาษคร่าวๆ แบ่งเป็น 3 ส่วน คือ
- color picker เอาไว้เปลี่ยนสี กับ clear board ทิ้ง
- ตัว pixel board
- button ที่เอาไว้ import, export, save รูป และอาจจะมิ้นรูปตรงนี้ ;P
ทำตัว pixel board ก่อน
ต่อมาทำตัว pixel board กัน อันนี้เอาโพยพี่นาตรที่ได้ตอนดูสตรีมวันโน้น มาลองทำดู พร้อมพลังของ Github Copilot
สิ่งที่ต้องทำมี 2 ส่วน คือ ส่วนบน และส่วนล่างนั่นเอง (ห๊ะ งี้ก็ได้ด้วยหรอ?)
ทำส่วน script เพิ่มที่ด้านบน เป็นภาษา TypeScript โดยเราจะทำเป็นตาราง 32 x 32 ดังนั้นจะประกาศตัวแปร width
เป็น 32 และ height
เป็น 32
จากนั้นสร้างตัวแปร board
เป็น array 2 มิติ
จบด้วยการสร้าง functioon ที่ชื่อว่า paint
มี 3 parameter ก็คือ x y และสี เอามาใช้ตอนกดในแต่ละช่องเนอะ
<script lang="ts">
const width = 32
const height = 32
const board: string[][] = Array(height)
.fill(0)
.map(() => Array(width).fill(""))
function paint(x: number, y: number, color: string) {
board[y][x] = color
}
</script>
ด้านล่างเป็น html ที่มี text title รอเพื่อนอยู่อันนึง เราก็เอาไปต่อท้ายก่อนแล้วกัน
ตรงนี้เราจะใช้ for-loop วน 2 ชั้น ชั้นนนอกวน row ชั้นในวน column จนวาดตารางครบ 32 x 32 เนอะ ตัวช่องของตารางจะเป็น flex
ตัว View สามารถคลิกได้ คลิกแล้วทำอะไรต่อ ก็ทำการเรียก function paint
เพื่อใส่สีที่เราต้องการนั่นเอง ในที่นี้ random สีมาก่อน เพื่อดูการทำงานแล้วทำได้ไหม ทำได้หรือเปล่า
<h1 class="text-center my-12">Pixel Art Board!</h1>
<!-- board 32 x 32 -->
{#each board as row, rowIndex}
<div class="flex">
{#each row as column, columnIndex}
<div
class="flex flex-row border h-4 w-4 border-gray-100"
style={`background-color: #${column}; border-color: #${column}`}
on:click={() =>
paint(columnIndex, rowIndex, Math.floor(Math.random() * 16777215).toString(16))}
>
</div>
{/each}
</div>
{/each}
ผลที่ได้ เมื่อเราจิ้มไปที่ช่อง ช่องนั้นจะถูกถมสีลงไป ถ้ากดซํ้า สีก็จะเปลี่ยน
ในโพยที่มีนั้น เขาจะมีการ check เรื่อง overflow ด้วย เนื่องจากรับ input จากทางช่องแชทอะเนอะ
อันนี้สตรีมย้อนหลังฮับ
หลังจากนี้จะทำอะไรต่อนะ
ถ้ามีเวลาจะสร้างปุ่ม color picker และ clear board ทิ้ง
จริงๆเรากด F5 มันก็ clear ทิ้งแล้วนะ แต่เราอำนวยความสะดวกให้ user ไง และอาจจะเผื่อทำการ save cache อะไรแบบนี้ในอนาคตได้งี้
แนวคิดในหัว คือ user จะต้องเลือกสีได้ โดยการจิ้มสีใน View ของ color picker หรือใส่รหัสสีเองได้ จากนั้นนำค่าพวกนั้นมาใส่แทนเลขสีที่ random นะ
ตัว color picker เนี่ย เราไม่ได้เขียนเองนะ ไปเจอมาอีกทีนึง
ที่ลองทำก็จะประมาณนี้นะทุกคน
ติดตามข่าวสารตามช่องทางต่าง ๆ และทุกช่องทางโดเนทกันไว้ที่นี่เลย
ติดตามข่าวสารแบบไว ๆ มาที่ Twitter เลย บางอย่างไม่มีในบล็อก และหน้าเพจนะ