อัพเดท 11 ฟีเจอร์ใหม่ของ Flex Message ปี 2019 อิสระที่แท้ทรูของการออกแบบข้อความใน LINE

Jirawatee
LINE Developers Thailand
6 min readAug 28, 2019

--

Flex Message คือรูปแบบหนึ่งของข้อความที่ LINE Bot สามารถส่งได้ เปิดตัวกลางปี 2018 โดยนักพัฒนาสามารถออกแบบข้อความได้อย่างอิสระ ด้วยการสร้าง payload ที่เป็น JSON แล้วส่งผ่าน Messaging API เพื่อมอบประสบการณ์ที่ดีกว่าในสื่อสารระหว่างผู้ใช้ และ Chatbot

เชื่อว่าหลายคนที่กำลังอ่านบทความนี้ น่าจะมีประสบการณ์การปั้น Flex Message มาแล้ว แต่หากยังไม่คุ้นเคย แนะนำให้อ่านบทความนี้ก่อนนะ

ในบทความนี้จะมาเผยฟีเจอร์ใหม่ของปี 2019 ที่จะทำให้ Flex Message ของคุณยืดหยุ่นกว่าเดิม ส่วนจะมีอะไรกันบ้างนั้นไปดูกันเลย

1. Bubble Size

ตอนนี้เราสามารถปรับขนาดของ bubble ได้แล้ว 5 ระดับ ผ่าน property ที่ชื่อ size ซึ่งเป็น property และอยู่ในระดับเดียว Block ต่างๆ

  • size: nano, micro, kilo, mega(default), giga
{
"type": "flex",
"altText": "Flex Message",
"contents": {
"type": "bubble",
"size": "giga",
"hero": {
// ...
}
}
}
Bubble Container
Carousel Container

หมายเหตุ: หากระบุ size ใน bubble ที่อยู่ภายใต้ Carousel Container จะต้องระบุทุก bubble ให้เป็น size เดียวกันเท่านั้น

2. Box Padding

อีกหนึ่งสิ่งที่นักพัฒนารอคอยมาตั้งแต่เปิดตัว Flex Message คือการกำหนด Padding ให้กับ Box แต่ละกล่องอย่างอิสระ ซึ่งตอนนี้ฝันของทุกคนเป็นจริงแล้ว งั้นมาดูรายละเอียดกันว่าเราจะกำหนด Padding อย่างไรได้บ้าง

Properties สำหรับ Padding

  • paddingAll: ระยะห่างภายใน Box รอบด้าน
  • paddingTop: ระยะห่างภายใน Box ด้านบน
  • paddingBottom: ระยะห่างภายใน Box ด้านล่าง
  • paddingStart: ระยะห่างภายใน Box ด้านซ้าย(จะเป็นด้านขวากรณีตั้ง direction ใน bubble เป็น rtl)
  • paddingEnd: ระยะห่างภายใน Box ด้านขวา(จะเป็นด้านซ้ายกรณีตั้ง direction ใน bubble เป็น rtl)

หน่วยใน Padding

  • Percentage: ระบุได้ตั้งแต่ 0–100% โดย % จะคำนวนจากความกว้างของ screen ของเครื่องผู้ใช้
  • Pixel: ระบุเป็น pixel เช่น 20px
  • Keyword: none, xs, sm, md, lg, xl, xxl
"body": {
"type": "box",
"layout": "vertical",
"paddingAll": "10%",
"contents": [
{
"type": "text",
"text": "The objective of ..."
}
]
}

หมายเหตุ: กรณีที่ใช้ paddingAll ร่วมกับ paddingTop, paddingBottom, paddingStart หรือ paddingEnd การแสดงผลจะยึดจากขนาดที่เราระบุเฉพาะด้านเป็นหลัก

3. Color & Background Color

เราสามารถเปลี่ยนสีพื้นหลังใน Box ได้แล้วด้วย property ชื่อ backgroundColor และที่สำคัญคือการรองรับ hexadecimal แบบ 8 หลัก(ปกติ 6 หลัก) โดย 2 หลักสุดท้ายจะมีไว้สำหรับ alpha ตามรูปแบบนี้ #RRGGBBAA ซึ่งค่า AA เรียงจากโปร่งแสงไปทึบแสงจะเริ่มจาก 00 จนถึง FF

{
"type": "box",
"backgroundColor": "#2a01ffaa",
"paddingAll": "8%",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "Hello World!"
}
]
}

หมายเหตุ: เท่าที่ทดลอง ไม่ใช่เฉพาะ backgroundColor ที่จะใช้ hexadecimal แบบ 8 หลักได้ แต่ตัว color ของตัวอักษรก็สามารถใช้ 8 หลักได้เช่นกัน

4 Box Corner

เราสามารถปรับแต่งขอบของ Box ให้โค้งมนได้แล้วด้วย property ชื่อ cornerRadius โดยจะมีหน่วย 2 รูปแบบคือ

  • Pixel: ระบุเป็น pixel เช่น 88px
  • Keyword: none(default), xs, sm, md, lg, xl, xxl
{
"body": {
"type": "box",
"paddingAll": "none",
"cornerRadius": "150px",
"layout": "vertical",
"contents": [
{
"type": "image",
"url": "https://...",
"size": "full"
}
]
}
}

หมายเหตุ: LINE สำหรับ Desktop เวอร์ชันล่าสุด(v5.18.3) รองรับการระบุค่า cornerRadius แบบ Keyword ได้เท่านั้น

5. Box Border

เราสามารถเพิ่มขอบและกำหนดสีให้กับขอบของ Box ได้แล้วด้วย property ชื่อ borderWidth และ borderColor โดยมีรายละเอียดดังนี้

หน่วยใน borderWidth

  • Pixel: ระบุเป็น pixel เช่น 2px
  • Keyword: none(default), light, normal, medium, semi-bold, bold

ค่าสีใน borderColor

ค่าสีแบบ hexadecimal แบบ 6 หรือ 8 หลัก เช่น #a201ff10 ซึ่งกรณีที่เป็น 8 หลักนั้น 2 หลักสุดท้ายจะมีไว้สำหรับ alpha

{
"type": "box",
"layout": "vertical",
"borderWidth": "medium",
"borderColor": "#a201ff10",
"contents": [
{
"type": "text",
"text": "1"
}
]
}

หมายเหตุ: เพราะของมันคู่กัน ดังนั้นการจะใช้ borderWidth และ borderColor จะต้องมาคู่กันเสมอ

6. Box Width & Height

นอกจาก Flex Message เวอร์ชันใหม่จะสามารถกำหนดขนาดของ Bubble ได้แล้ว เราก็ยังสามารถกำหนด Width และ Height ให้กับ Box ได้ด้วย property ชื่อ width และ height โดยเราสามารถกำหนดหน่วยได้ 2 รูปแบบดังนี้

  • Percentage: ระบุได้ตั้งแต่ 0–100% โดย % จะคำนวนจากความกว้างของ screen ของเครื่องผู้ใช้
  • Pixel: ระบุเป็น pixel เช่น 80px
{
"type": "box",
"layout": "vertical",
"width": "25%",
"height": "300px",
"backgroundColor": "#0000ff",
"contents": [
{
"type": "text",
"text": "W:25% H:300px"
}
]
}

7. Position & Offset

เราสามารถกำหนดตำแหน่งในการแสดงผลให้กับ component ได้อย่างอิสระ ซึ่งมี component ที่รองรับด้วยกัน 5 ตัว ได้แก่ Box, Image, Text, Icon และ Button โดยผ่าน property ที่ชื่อว่า position และ offset

Property ของ Position

position:
- relative เป็นการอ้างอิงจาก component ก่อนหน้า (default)
- absolute เป็นการอ้างอิงจากตำแหน่ง top left ของ parent

เมื่อเราเลือกใช้ position แล้ว จะมี properties ที่จะมาช่วยกำหนดระยะห่างให้กับ component ภายใน parent นั่นก็คือ offset จะมีอยู่ 4 ด้าน

Properties สำหรับ Offset

  • offsetTop: ระยะห่างภายนอกด้านบน สามารถเป็นค่าติดลบได้
  • offsetBottom: ระยะห่างภายนอกด้านล่าง สามารถเป็นค่าติดลบได้
  • offsetStart: ระยะห่างภายนอกด้านซ้าย(จะเป็นด้านขวากรณีตั้ง direction ใน bubble เป็น rtl) สามารถเป็นค่าติดลบได้
  • offsetEnd: ระยะห่างภายนอกด้านขวา(จะเป็นด้านซ้ายกรณีตั้ง direction ใน bubble เป็น ltr) สามารถเป็นค่าติดลบได้

หน่วยใน Offset

  • Percentage: ระบุได้ตั้งแต่ 0–100% โดย % จะคำนวนจากความกว้างของ screen ของเครื่องผู้ใช้
  • Pixel: ระบุเป็น pixel เช่น 20px
  • Keyword: none, xs, sm, md, lg, xl, xxl
// ตัวอย่าง Position ที่เป็น Relative
{
"type": "box",
"position": "relative",
"offsetTop": "-24px",
"offsetStart": "25%",
"paddingStart": "32%",
"paddingEnd": "32%",
"layout": "vertical",
"contents": [
{
"type": "button",
"action": {
"type": "uri",
"label": "Apply Now!",
"uri": "https://hackth.line.me"
}
}
]
}
ตัวอย่าง Position ที่เป็น Relative
// ตัวอย่าง Position ที่เป็น Absolute
{
"type": "box",
"position": "absolute",
"offsetTop": "25%",
"offsetBottom": "60%",
"offsetStart": "50%",
"offsetEnd": "20%",
"layout": "vertical",
"contents": [
{
"type": "button",
"action": {
"type": "uri",
"label": "Apply Now!",
"uri": "https://hackth.line.me"
}
}
]
}
ตัวอย่าง Position ที่เป็น Absolute

หมายเหตุ:

  1. เนื่องจาก position ประเภท relative จะอ้างอิง component ก่อนหน้า ดังนั้น offsetTop และ offsetStart จะเป็น property ที่เมื่อกำหนดค่าจะเห็นผลเท่านั้น
  2. component จะถูกซ่อน หากมีการระบุค่า offset ให้ออกนอก parent
  3. ลำดับในการ render จะเรียงจากโครงสร้างบนลงล่างของ JSON ดังนั้น ในกรณีมีการแสดงผลที่ตำแหน่งเดียวกัน component ที่อยู่ด้านล่างจะแสดงทับ component ตัวที่อยู่ด้านบน ตามโครงสร้างใน JSON นั่งเอง

8. Bubble Action

เราสามารถกำหนด Action ทั้ง Message, Uri, Postback และ Datetime Picker ให้กับ Bubble ทั้งก้อนได้แล้ว โดยใครยังไม่คุ้นเคยกับ Action ทั้ง 4 สามารถไปอ่านบทความด้านล่างนี้ได้

ส่วนโครงสร้างของ Bubble ที่มี Action อยู่จะมีโครงสร้างแบบนี้

"type": "bubble",
"direction": "ltr",
"size": "giga",
"styles": {},
"action": {},
"header": {},
"hero": {},
"body": {},
"footer": {}

หมายเหตุ: Action ที่อยู่ภายใน Bubble จะทำงานตามปกติ เฉพาะพื้นที่ที่ไม่มี Action อยู่จะสามารถคลิกได้เมื่อมีการกำหนด Action ที่ Bubble ดังนั้นไม่ต้องเป็นห่วงครับ

9. Text Style

เราสามารถกำหนดรูปแบบการแสดงผลของข้อความภายใน Flex Message ได้มากขึ้น จากเดิมที่เราไม่สามารถกำหนดรูปแบบของข้อความได้เลย

  • style: normal, italic โดยค่าเริ่มต้นคือ normal
  • decoration: none, underline, line-through โดยค่าเริ่มต้นคือ none
  • contents: Array ของ span
{
"type": "text",
"style": "italic",
"decoration": "underline",
"text": "The objective of ...",
"wrap": true
}

ยัง…ยัง…ยังไม่หมด ยังมีทีเด็ดอีกตัว นั่นคือการประกาศเปิดตัว Span ซึ่งเป็น component ตัวใหม่ลำดับที่ 9 ที่จะมาช่วยให้ข้อความในบรรทัดเดียวกันมีความหลากหลายในการแสดงผลขึ้นมา แต่ก่อนอื่นมาดูองค์ประกอบกันหน่อยว่ามีอะไรให้เราเล่นบ้าง

Span

  • type: span (required)
  • text: ข้อความ (required)
  • color: ค่าสีแบบ hexadecimal แบบ 6 หรือ 8 หลัก
  • size: xxs, xs, sm, md, lg, xl, xxl, 3xl, 4xl, 5xl โดยค่าเริ่มต้นจะเป็น md
  • weight: regular or bold โดยค่าเริ่มต้นคือ regular
  • style: normal, italic โดยค่าเริ่มต้นคือ normal
  • decoration: none, underline, line-through โดยค่าเริ่มต้นคือ none
{
"type": "text",
"text": "...",
"wrap": true,
"contents": [
{
"type": "span",
"text": "The objective of...",
"style": "italic"
},
{
"type": "span",
"text": "to enhance their...",
"color": "#a201ff",
"size": "sm",
"weight": "bold"
},
{
"type": "span",
"text": "create an impact...",
"color": "#0000ff",
"size": "xs",
"decoration": "underline"
}
]
}

หมายเหตุ:

  1. ข้อความใน Span จะแสดงแทนที่ข้อความของ Text ซึ่งเป็น parent component
  2. ถ้า property wrap ของ Text ซึ่งเป็น parent component คือ true จะทำให้ข้อความใน Span ขึ้นบรรทัดใหม่ หรือสืบทอดคุณสมบัติมาด้วย
  3. ค่าเริ่มต้นของ property ใน Span ทั้ง color, style, weight, size จะสืบทอดคุณสมบัติจาก Text ซึ่งเป็น parent component แต่สามารถ overwrite ใน Span ได้

10. Box in Hero block

ตามที่ทราบกันว่าก่อนหน้านี้ เราสามารถมี component ภายใน Hero block ได้แบบเดียวก็คือ Image แต่จากนี้ไปเราจะสามารถใส่ component ที่เป็น Box เข้าไปได้ด้วย นั่นก็หมายความว่าภายใน Box เราจะมี component อื่นๆใส่เข้าไปก็ย่อมได้

"hero": {
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Box in Hero block"
}
]
}

11. Filler Property

Component ว่างเปล่าที่มีไว้สำหรับเติมช่องว่างระหว่าง component ซึ่งก่อนหน้านี้ component ประเภทนี้จะไม่มี property ภายใน และค่า flex หรืออัตราส่วนความกว้างของ filler จะถูก fix ไว้ที่ 1 เท่านั้น แต่…ตอนนี้คุณสามารถกำหนด flex ให้กับ filler ได้แล้วนะ

"body": {
"type": "box",
"layout": "horizontal",
"contents": [
// ...
{
"type": "filler",
"flex": 3
},
// ...
]
}

รู้หมือไร่?

  1. Property ใหม่ในปี 2019 ทั้งหมดจะเป็นแบบ Optional คือไม่ระบุก็ได้
  2. Padding เกิดมาเพื่อเพิ่มความยืดหยุ่นและแทนที่ Component ที่ชื่อ Spacer ดังนั้นเปลี่ยนมาใช้ padding ตั้งแต่วันนี้ชีวิตดีกว่าแน่นอน เพราะ…Spacer จะถูกยกเลิกในอนาคต
  3. แอป LINE สำหรับ Android และ iOS ตั้งแต่ v9.8.0 เป็นต้นไปจะแสดงผล Flex Message แบบใหม่นี้เป็น Native แต่ถ้าต่ำกว่าจะแสดงผลเป็น WebView
  4. แอป LINE สำหรับ Desktop ตั้งแต่ v5.17 เป็นต้นไป จะสามารถแสดงผล Flex Message ได้ แต่หากต่ำกว่าจะแสดงข้อความจาก property ชื่อ Alt แทน
  5. LINE Bot Designer เวอร์ชันล่าสุด v1.3.4 รองรับฟีเจอร์ใหม่ๆในบทความนี้แล้ว หรือจะออกแบบบน Browser ด้วย Flex Message Simulator ก็ทำได้เช่นกัน

สรุป

เรียกได้ว่าอัพเดทล่าสุดทั้ง 11 ฟีเจอร์ใหม่ของ Flex Message ปี 2019 นี้ เข้ามาช่วยให้การพัฒนาข้อความใน LINE ให้สะดวกและยืดหยุ่นขึ้นมากกว่าเดิม แถมรองรับทั้งมือถือ, iPad และ Desktop ได้อีกต่างหาก

สุดท้ายนี้ก็หวังว่าบทความนี้จะช่วยให้นักพัฒนาสามารถสร้าง Message ใน LINE ที่เคยคิดว่าเป็นไปไม่ได้ด้วยการเขียนโค้ดให้เป็นไปได้นะครับ วันนี้ขอตัวลาไปก่อนแล้วพบกันใหม่บทความหน้า ราตรีสวัสดิ์นักพัฒนาชาวไทย

--

--

Jirawatee
LINE Developers Thailand

Technology Evangelist at LINE Thailand / Google Developer Expert in Firebase