ทำโปรเจกต์ PWA แบบไม่ต้อง setup project เยอะ โดยใช้ Glitch
อยากลองทำ PWA แบบง่าย ๆ แต่ไม่รู้จะเริ่มยังไงดี บน Glitch มี template project ให้เราลองทำแล้วนะ
จาก content ที่แล้วเรามาพูดถึง PWA เบื้องต้นกันไปแล้ว ในตอนนี้เราพามาสร้าง Progressive Web Apps เป็นของตัวเองกันเถอะ
ในที่นี้เราทำเว็บ Position Sizing Calculator ซึ่งสูตรนี้มาจากเพจ CryptoTeller นั่นเอง มาลองทำเว็บเพิ่มความท้าทายสำหรับคนไม่ค่อยได้ทำเว็บแบบเราหน่อย ว่าถ้าใช้ Glitch ที่เขามีส่วน PWA มาให้แล้ว เราต้องทำอะไรตรงไหนเพิ่มบ้างเนอะ
อันนี้ Excel ต้นฉบับ
สร้างโปรเจกต์ใหม่จาก Glitch
เข้าที่เว็บไซต์ https://glitch.com/ แล้วก็ log-in ให้เรียบร้อย แล้วสร้างโปรเจกต์ใหม่
เราจะพบหน้าเว็บของ Glitch ที่เปลี่ยนไปจากตอนนั้นที่เราสอนทำ bio link website แล้วก็บล็อกเนอะ เราจะเห็นส่วน Make your web app installable! ให้ทำการกด Remix it! ตรง Hello Installable เพื่อสร้างโปรเจกต์ PWA กัน
ส่วนประกอบในโปรเจกต์
หลังจากกดสร้างโปรเจกต์แล้ว ข้างในโปรเจกต์มีอะไรบ้างนะ
README.md
บอกรายละเอียดคร่าว ๆ ของ template project นี้ ว่าเป็น PWA นะ มีส่วนประกอบอะไรบ้าง และเราทำอะไรได้บ้างpublic/index.js
: เป็นไฟล์ JavaScript ของ PWA ของเรา ซึ่งเขา implement ของบางอย่างมาให้เราแล้ว อย่างสั่งให้ service worker ทำงาน, การติดตั้ง web app ของเรา, notification แล้วมีเรื่อง badge ด้วยแหะ, Orientation changes เราสามารถ implement อะไรเพิ่มเติมได้ แต่แนะนำแยกเป็นไฟล์ใหม่ดีกว่า แหะ ๆpublic/install.html
: หน้าเว็บที่สอนวิธีการ install PWA ของเราpublic/manifest.json
: manifest files สำหรับ PWApublic/service-worker.js
: เป็นไฟล์ JavaScript ที่ทำให้ PWA ของเรานั้น สามารถทำงานแบบ background และ handle สิ่งต่าง ๆ ไม่ว่าจะเป็นการ caching การรับส่ง notificationspublic/style.css
: สไตล์ของหน้าเว็บของเราindex.html
: หน้าเว็บหลักที่เราจะมาทำกัน
ปรับแต่ง Manifest File กัน
ไฟล์ public/manifest.json
เขาเตรียมของให้เราพร้อมแล้ว มีอะไรที่เราแก้เล่นได้บ้างนะ
name
ชื่อเต็มของ PWA ของเราshort_name
ชื่อย่อของ PWA ของเรา ใช้ในการแสดงผลพร้อมไอคอน ไม่ควรใส่เกิน 12 ตัวอักษร แนะนำ 5-6 ตัวอักษร ดีที่สุดแล้วdescription
อธิบาย PWA ของเราคร่าว ๆ ว่าคือแอพอะไรdisplay
บอกให้ OS วาดหน้าต่าง PWA ออกมายังไง ส่วนใหญ่ใช้เป็นstandalone
นะ ปล. แบบminimal
ใช้ได้เฉพาะบน android เท่านั้นicon
เขามี size 120, 180, 192 และ 512 แบบ default เปลี่ยนแค่รูปของ PWA อาจจะไปทำ maskable icon ของ size 512 เผื่อไว้ด้วยนะ โดยมีpurpose
เป็นmaskable
background_color
สี placeholder ก่อนที่ stylesheet จะโหลดเสร็จ ใส่เป็น hex color อาจจะใช้สีเดียวกันกับtheme_color
ได้theme_color
สีหลักของแอพ ใส่เป็น hex colorstart_url
กำหนกว่ารัน PWA แล้ว ให้ไปรันหน้าไหน ในที่นี้คือ/
ก็คือหน้าแรกแหละ
ทดลองเปลี่ยน Display Mode
ค่า display
โดย default จะเป็น standalone
ถ้าลองเปลี่ยนแล้ว อันอื่น ๆ จะแสดงผลยังไงบ้างนะ
standalone
อันนี้เป็น by default เท่าที่ลองอันนี้ดู UX ดีสุดล่ะfullscreen
แสดงเต็มจอ ไม่มี bottom navigationminimal-ui
เหมือนเปิดใน Chrome Custom Tab มีเฉพาะบน Android เท่านั้นbrowser
เหมือนเป็น shortcut ของเว็บปกติ
การทดสอบแต่ละแบบ คือ เข้าเว็บ และทำการ install ตัว PWA ลงไป แล้วเปิดตัวแอพ PWA ลงไป
ทำ maskable icon
ใครที่มี icon app ให้ลองไป check ขนาด safe zone กันก่อนที่ Maskable.app กันได้เลย หรือทำเองผ่านเว็บนี้ก็ได้เช่นกัน
ในที่นี้เรานำภาพคาถากันดอย มา cutout เหลือแค่ตรงกลาง แล้วก็ใส่สีพื้นหลัง ปรับพื้นที่ให้พอดีกับรูปแบบต่าง ๆ เนอะ ขนาดที่ต้องทำ คือ 512x512 อันนี้ set purpose
เป็น maskable
ในไฟล์ manifest, 192x192, 180x180 และ 128x128
{
...
"icons": [
{
"sizes": "512x512",
"type": "image/png",
"src": "https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-512-maskable.png?v=1689501092180",
"purpose": "maskable"
},
{
"sizes": "192x192",
"type": "image/png",
"src": "https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-192-maskable.png?v=1689501322372",
"purpose": "any"
},
{
"sizes": "180x180",
"type": "image/png",
"src": "https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-180-maskable.png?v=1689501870404",
"purpose": "any"
},
{
"sizes": "128x128",
"type": "image/png",
"src": "https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-192-maskable.png?v=1689501322372",
"purpose": "any"
}
],
...
}
ตรวจสอบ Manifest ของเรา
เมื่อเราเปลี่ยน logo และอะไรต่าง ๆ ในไฟล์ manifest ของเราแล้ว มาตรวจสอบดูหน่อยดีกว่าว่าเป็นยังไงบ้าง
ก่อนอื่น เปิด Developer Tool แล้วไปที่ tab Application แล้วไปดูที่ Manifest ในนั้นมีข้อมูล 4 ส่วน คือ
- Identity บอกข้อมูลเกี่ยวกับ PWA ของเราคร่าว ๆ
- Presentation เริ่มแสดงหน้าไหน สีอะไร และ display เป็นแบบไหน
- Protocol Handler อันนี้ไม่รู้แหะ
- Icons ดูหน้าตา icon ทุกขนาดที่เราใส่ไว้
และเราตรวจสอบดูการทำงานของ service worker ได้ โดยดูตรง Service Worker นะ
ปล. วิธีการเปิด developer tools
- คลิกขวา จากนั้นเลือก Inspect ตัว browser ก็จะเปิด developer tool มาให้เราแล้ว
- ไปที่สามจุดด้านขวามือ -> More Tools -> Developer Tools ก็ได้เช่นกัน
- ใช้ key ลัด สำหรับ mac จะเป็น option + command + i
ลบส่วนที่ไม่ใช้ออก
ก่อนจะลงมือทำ ของไม่ใช้ก็พยายามเคลียร์ออกก่อน
- หน้าเว็บ
index.html
ลบส่วนdiv id="install-nudge”
ออก แล้วข้างในส่วนที่เป็น content ลบออกเหลือแค่ header text ก็พอ เพราะเราจะนำมาใช้งานต่อ - ไฟล์
public/index.js
อันนี้เหลือแค่ส่วน app setup พอ เพราะอันอื่นจะมีเรื่องของ badge notification, push notification, แสดงการหมุนจอ, หน้า install แอพของเรา ซึ่งเราไม่ได้ใช้แหละ - ลบ
public/install.html
ออก - ลบรูป install-desktop.png กับ install-ios.png ออก เพราะเราลบหน้าเว็บออกแล้ว
- ที่
public/style.css
ลบตั้งแต่ line 209 ลงไป เพราะไม่ได้ใช้อะไร
เปลี่ยนหน้าเว็บกัน
เราได้อิงตัว design จากตัว Excel คือพอใส่แต่ละ field เสร็จ มันต้องคำนวณให้เหมือน Excel เลย แล้วหน้าตาแทบจะเหมือนกันเลย คือ เราให้ตัว label อยู่ซ้าย และส่วน TextField อยู่ขวา มีเส้นคั่นแต่ละส่วน และเราจะปรับแต่งหน้าตรงนี้ให้สวยงามน่าใช้ ด้วย CSS นั่นเอง เดี๋ยวเรามาทำทีละส่วนกัน
โครงสร้างตัว HTML หลัก ๆ เป็นแบบนี้เนอะ
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
</body>
</html>
มาแก้ส่วน head
กันก่อนเลย
title
: คือส่วนแสดงชื่อเว็บเรา ดังนั้นเปลี่ยนเป็นชื่อเว็บตามที่เราแก้ในไฟล์ manifest
<title>Position Sizing Calculator</title>
<meta property="og:title" content="Position Sizing Calculator" />
description
: บอกว่าเว็บเราคืออะไร กรอกตามใน manifest ที่เราแก้ไว้เช่นกัน
<meta name="description" content="Calculator for trade cryptocurrency future, formular from Crypto Teller" />
<meta name="og:description" content="Calculator for trade cryptocurrency future, formular from Crypto Teller" />
icon
: ก็ icon ของเว็บเราอ่ะ เวลาเปิดหน้าเว็บเราจะเห็นอันนี้บน tab เปลี่ยนตรงนี้ตามที่เราใส่ใน manifest อีกเช่นกัน
<link rel="icon" href="https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-180-maskable.png?v=1689501870404" />
ต่อมาส่วน body
ส่วนแสดงผลหน้าเว็บ
เพิ่มส่วน header ของเว็บ
ใส่เพื่อบอกว่าเว็บนี้คืออะไร พร้อมรูป ซึ่งรูปที่เราแสดงนั้น ก็เอามาจากรูป logo จาก manifest นี่แหละ มาแปะด้านบน
<img id="imgLogo" alt="logo" src="https://cdn.glitch.global/d1fcae68-a5e4-40eb-aac9-5bfad9facbfe/icon-128-maskable.png?v=1689501325168">
<h1 id="textHeader">Position Sizing Calculator</h1>
ส่วน css เราจะเพิ่มการใส่สีของตัว header text และใส่ขนาดรูปที่เราต้องการลงไป กำหนดเป็น id
เพราะเราใช้แค่เฉพาะสองอันนี้อ่ะ
#textHeader {
color: #862B0D;
}
#imgLogo {
width: 180px;
height: 180px;
}
เพิ่มส่วนการทำงานหลักของเว็บนี้
เราต้องการให้แต่ละแถว แสดง text ข้างหน้าว่า field นี้คืออะไร พร้อม TextField ด้านหลัง ดังนั้นเราจะต้องสร้าง class ใหม่ที่ชื่อ item
ให้มันจัดวางแบบ flex และตบให้มันห่างกันอย่างสวยงาม
ตัวอย่าง คือ ตรงกรอกชื่อเหรียญ อันนี้มีแค่ text และ TextField ปกติเลย
<div class="item">
<p class="textLabel">Coin: </p>
<input type="text" id="inputCoinMame" class="inputTextField" placeholder="Enter coin name" value="">
</div>
อันนี้เราทำเป็น class บน css ไว้ เพราะใช้หลายที่เนอะ
/* show input row */
.content .item {
display: flex;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
flex-direction: row;
align-items: baseline;
justify-content: space-between;
}
.content .textLabel {
color: #000000;
font-weight: 400;
}
.inputTextField {
width: 200px;
margin-top: 0rem;
display: block;
border-radius: 8px;
padding-left: 16px;
padding-right: 16px;
}
พร้อมด้วยเส้นคั่น ที่เอาไว้แบ่ง session ซึ่งใช้หลายส่วน
<hr class="divider">
เลยทำเป็น class บน css ไว้เช่นกัน
.divider {
width: 100%;
height: 4px;
background: #FAF3F0;
}
ส่วนถัดไป จะเป็นส่วนที่ให้ user ใส่ค่าได้ และเป็นส่วนที่แสดงผลการคำนวณ เลยไม่ให้ user ใส่ค่า โดยเราใส่ disabled
ลงไป
<!-- Input & Calculate Loss per order -->
<div class="item">
<p class="textLabel">Start Fund: </p>
<input type="number" id="inputStartFund" class="inputTextField" placeholder="Enter start fund" value="">
</div>
<div class="item">
<p class="textLabel">Risk % per order: </p>
<input type="number" id="inputRiskPerOrder" class="inputTextField" placeholder="Enter risk % per order" value="">
</div>
<div class="item">
<p class="textLabel">Loss per order: </p>
<input id="resultLossPerOrder" class="resultTextField" disabled>
</div>
การคำนวณในส่วนหลัง เราอยากให้บอก infomation นิดนึงว่า ช่องนี้ใส่อะไร เลยใช้ Tooltip มาช่วย โดยการสร้าง class ที่ชื่อว่า tooltip ข้างในใส่ text เหมือนเดิม แต่เพิ่ม span ตอนที่เม้าส์ไปใกล้ ๆ เพื่อบอก information เนอะ
<!-- Input for calculate All -->
<div class="item">
<div class="tooltip">
<p class="textLabel">Max Loss:</p>
<span class="tooltiptext">จำนวนเงินที่เสียได้ต่อ 1 order</span>
</div>
<input type="number" step="0.01" id="inputMaxLoss" class="inputTextField" placeholder="Enter max loss" value="">
</div>
<div class="item">
<div class="tooltip">
<p class="textLabel">Leverage:</p>
<span class="tooltiptext">( Spot=1 )</span>
</div>
<input type="number" step="0.01" id="inputLeverage" class="inputTextField" placeholder="Enter leverage" value="" onchange="calculateAll();">
</div>
<div class="item">
<div class="tooltip">
<p class="textLabel">Entry price:</p>
<span class="tooltiptext">ราคาเข้าซื้อ</span>
</div>
<input type="number" step="0.01" id="inputEntryPrice" class="inputTextField" placeholder="Enter entry price" value="">
</div>
<div class="item">
<div class="tooltip">
<p class="textLabel">Stop loss price:</p>
<span class="tooltiptext">ราคาที่ยอมแพ้</span>
</div>
<input type="number" step="0.01" id="inputStopLossPrice" class="inputTextField" placeholder="Enter stop loss price" value="">
</div>
อันนี้ css เนอะ
/* hover */
.tooltip {
position: relative;
display: inline-block;
text-align: center;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 150px;
background-color: #192733;
color: #FFFFFF;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 2;
margin-left: -60px;
padding: 8px;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
เราลองอ่านจากนี้ แล้วลองทำตามแหละ
โค้ดหน้าเว็บส่วน HTML และ css
เพิ่มส่วนการคำนวณตามสูตรกัน
เพิ่มไฟล์ใหม่ นามว่า calculate.js
สร้าง function เกี่ยวกับการคำนวณต่าง ๆ ตามสูตรใน Excel เลย
เราจะทำ function เล็ก ๆ เพื่อนำไปใช้งาน โดยจะแบ่งเป็น 3 ส่วน คือ
- ส่วนการทำงาน จะให้ทำงานเมื่อเราใส่ค่าใน TextField แล้วให้มัน auto calculate ไปเลย
calculateLossPerOrder()
คำนวณ loss per order ด้านบน และcalculateAll()()
สำหรับการคำนวณ get take profit, amount buy และ usd ที่ใช้
/* Auto Calculate */
function calculateLossPerOrder() {
var startFund = getElementValue("inputStartFund");
var riskPercentPerOrder = getElementValue("inputRiskPerOrder");
var losrPerOrder = getLossPerOrder(startFund, riskPercentPerOrder);
setField("resultLossPerOrder", losrPerOrder);
}
function calculateAll() {
var maxLoss = getElementValue("inputMaxLoss");
var leverage = getElementValue("inputLeverage");
var entryPrice = getElementValue("inputEntryPrice");
var stopLossPrice = getElementValue("inputStopLossPrice");
var getTakeProfit3x = getTakeProfit(entryPrice, stopLossPrice, 3);
var getTakeProfit5x = getTakeProfit(entryPrice, stopLossPrice, 5);
var amountBuy = getAmountBuy(maxLoss, entryPrice, stopLossPrice);
var usdUses = getUsdUses(amountBuy, entryPrice, leverage);
setField("resultTakeProfit3x", getTakeProfit3x);
setField("resultTakeProfit5x", getTakeProfit5x);
setField("resultAmountBuy", amountBuy);
setField("resultUsdUses", usdUses);
}
- ส่วน HTML ที่ใช้ซํ้า ๆ ทำเป็น function ซะเลย มี
setField()
เอาค่าที่ได้ไปแสดงผลใน TextField ที่เราต้องการ และgetElementValue()
ดึงค่าที่ user พิมพ์เข้ามา นำไปใช้ต่อ
/* HTML */
function setField(id, value) {
document.getElementById(id).value = value;
}
function getElementValue(id) {
var element = document.getElementById(id);
return element.value;
}
- สูตรการคำนวณ เราจะ implement สูตรการคำนวณไว้ตรงนี้ สามารถ reuse และ test ได้ (แต่ไม่ทำหรอกนะ test น่ะ 55555)
getLossPerOrder()
อันนี้เอามาจากใน Excel คือเอา Start fund มาคิดเป็นเปอร์เซ็นต์getTakeProfit()
อันนี้เอามาจาก Excel เช่นกันgetAmountBuy()
จำนวนเหรียญ crypto ที่ซื้อ = เงินที่เราเสียได้ / abs(ราคาเข้าซื้อ - ราคา stop loss) ซึ่ง abs คือ absolute ไม่ว่าลบออกมาเป็นค่าบวก หรือค่าลบ จะ return เป็นค่าบวกเสมอgetUsdUses()
จำนวน USDT ที่ซื้อ = (จำนวนเหรียญ crypto ที่ซื้อ * ราคาเข้าซื้อ) / leverage
/* Formular */
function getLossPerOrder(startFund, riskPercentPerOrder) {
return (startFund / 100) * riskPercentPerOrder;
}
function getTakeProfit(entryPrice, stopLossPrice, multiple) {
var diffEntryStopLoss = (entryPrice - stopLossPrice).toFixed(2);
var multipleWithDiff = (multiple * diffEntryStopLoss).toFixed(2);
return Number(entryPrice) + Number(multipleWithDiff);
}
function getAmountBuy(maxLoss, entryPrice, stopLossPrice) {
return (maxLoss / Math.abs(entryPrice - stopLossPrice)).toPrecision(4);
}
function getUsdUses(amountBuy, entryPrice, leverage) {
return (amountBuy * entryPrice / leverage).toPrecision(4);
}
รายละเอียดสูตรต่าง ๆ สามารถอ่านความเป็นมาได้ที่นี่เลย
และอย่าลืมใส่ <script src="calculate.js"></script>
ไว้ส่วน head ของ index.html
นะ
การเอา function การคำนวณไปใช้ เราใช้ function onChange()
ใส่ไว้ใน HTML tag ของ TextField ที่เราต้องการ
- function
calculateLossPerOrder()
จะให้มันทำงาน เมื่อ user ใส่ค่า Start Fund และ Risk % per order ดังนั้นจึงใส่onchange="calculateLossPerOrder();"
กับinputStartFund
กับinputRiskPerOrder
- ส่วน function
calculateAll()
ใส่onchange="calculateAll();"
กับinputMaxLoss
,inputLeverage
,inputEntryPrice
และinputStopLossPrice
Reference
อย่าลืมเรื่อง Performance
เสร็จแล้วอย่าลืมตรวจสอบ performance กันด้วยนะ เข้าไปที่ PageSpeed Insights จากนั้นกรอก url website PWA ของเรา แล้วกด Analyse จากนั้นรอสักแปปนึง ก็จะได้ผลออกมา ซึ่งผลออกมาดี เนื่องจากตัว template เขาทำออกมาดีในเรื่อง performance ต่าง ๆ เราอาจจะปรับแก้นิดหน่อยในส่วนที่เรา implement เพิ่ม เพื่อให้ค่าต่าง ๆ ดีขึ้น
ทั้งหมดเกี่ยวกับการทำ site project ที่เป็น PWA แบบไม่ต้องขึ้นโปรเจกต์เองก็จะประมาณนี้น้า
ตัวโปรเจกต์นี้สามารถไปเล่นกันได้ที่นี่เลย
ตัวโปรเจกต์นี้สามารถไปเล่นกันได้ที่นี่เลย
ปล. feature นี้ไม่สามารถใช้ custom domain ได้นะ
ติดตามข่าวสารตามช่องทางต่าง ๆ และทุกช่องทางโดเนทกันไว้ที่นี่เลย
ติดตามข่าวสารแบบไว ๆ มาที่ Twitter เลย บางอย่างไม่มีในบล็อก และหน้าเพจนะ