ฟรี · ไม่ต้องสมัคร · รองรับไฟล์ .mmd

ตัวแก้ไขไดอะแกรมสถานะ Mermaid

ไดอะแกรมสถานะแสดงว่าสิ่งหนึ่งอาจอยู่ในสถานะใดได้บ้าง และอะไรพามันจากสถานะหนึ่งไปอีกสถานะหนึ่ง เหมาะเมื่อสิ่งนั้นมีวงจรชีวิต เช่น คำสั่งซื้อ ใบกำกับภาษี หรือการเป็นสมาชิก และคำถามที่น่าสนใจคือการเปลี่ยนสถานะแบบใดที่อนุญาต ถ้าคุณกำลังอธิบายขั้นตอนที่ต้องทำ ไม่ใช่สถานะที่จะอยู่ สิ่งที่คุณต้องการคือผังงาน

วงจรชีวิตของคำสั่งซื้อออนไลน์

นี่คือกรณีที่เครื่องสถานะคุ้มค่ากับที่ทางของมัน หลังจัดส่งแล้วมีปลายทางสามแบบที่ตัดกันเอง และสองในนั้นย้อนกลับ สังเกตว่าตัวระบุของสถานะเป็นอักษรไทยได้ตรง ๆ เพราะไดอะแกรมสถานะยอมรับอักษรไทยในตำแหน่งตัวระบุ ต่างจากผังงาน

stateDiagram-v2
    direction LR

    [*] --> ฉบับร่าง
    ฉบับร่าง --> รอชำระเงิน: สั่งซื้อแล้ว
    รอชำระเงิน --> พร้อมจัดส่ง: ได้รับเงินแล้ว
    รอชำระเงิน --> [*]: หมดอายุใน 24 ชั่วโมง
    พร้อมจัดส่ง --> กำลังจัดส่ง: ผู้ขนส่งรับของแล้ว
    กำลังจัดส่ง --> ส่งถึงแล้ว: ผู้รับเซ็นรับ
    ส่งถึงแล้ว --> ขอคืนสินค้า: อยู่ในกำหนดคืนสินค้า
    ขอคืนสินค้า --> รอชำระเงิน: คืนเงินแล้ว
    ส่งถึงแล้ว --> [*]: พ้นกำหนดคืนสินค้า
เปิดสิ่งนี้ในตัวแก้ไข
โฆษณา

ตัวอย่างพร้อมคำอธิบาย

1. เครื่องสถานะที่เล็กที่สุด

`[*]` เป็นทั้งจุดเข้าและจุดออก จะเป็นอันไหนขึ้นอยู่กับว่ามันอยู่ข้างใดของลูกศร นี่คือโครงที่เล็กที่สุดที่คุ้มค่าจะวาด

stateDiagram-v2
    [*] --> ใช้งานอยู่
    ใช้งานอยู่ --> ปิดแล้ว
    ปิดแล้ว --> [*]
เปิดในตัวแก้ไข

2. การเปลี่ยนสถานะที่มีชื่อ

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

stateDiagram-v2
    [*] --> ยังไม่ชำระ
    ยังไม่ชำระ --> ชำระแล้ว: เก็บเงินสำเร็จ
    ยังไม่ชำระ --> หมดอายุ: เลยกำหนด
    ชำระแล้ว --> จัดส่งแล้ว: ออกจากคลัง
    จัดส่งแล้ว --> รับแล้ว: ผู้รับเซ็นรับ
    รับแล้ว --> [*]
    หมดอายุ --> [*]
เปิดในตัวแก้ไข

3. ป้ายกำกับที่อ่านง่ายกับตัวระบุที่ปลอดภัย

ถึงอักษรไทยจะใช้เป็นตัวระบุสถานะได้ แต่ถ้าชื่อสถานะมีช่องว่างคั่นวลีหรือมีตัวเลขปนอยู่ มันจะแตกออกอย่างเงียบ ๆ `state "ป้ายกำกับ" as ตัวระบุ` ปิดความเสี่ยงนั้นได้ในครั้งเดียว

stateDiagram-v2
    state "รอชำระเงิน ภายใน 24 ชั่วโมง" as waitPay
    state "พร้อมจัดส่ง" as readyShip
    state "กำลังเดินทางไปหาลูกค้า" as onTheWay

    [*] --> waitPay
    waitPay --> readyShip: ยืนยันการชำระเงินแล้ว
    readyShip --> onTheWay: ผู้ขนส่งรับของแล้ว
    onTheWay --> [*]
เปิดในตัวแก้ไข

4. สถานะประกอบและจุดตัดสินใจ

สถานะประกอบมีเครื่องสถานะของตัวเองอยู่ข้างใน ใช้เมื่อขั้นตอนหนึ่งมีชีวิตภายในที่สำคัญ ส่วน `<<choice>>` คือจุดแตกแขนงตามเงื่อนไข และต้องประกาศก่อนการเปลี่ยนสถานะที่ใช้มัน

stateDiagram-v2
    state ตรวจสอบ <<choice>>

    [*] --> กำลังดำเนินการ

    state กำลังดำเนินการ {
        [*] --> หยิบสินค้า
        หยิบสินค้า --> บรรจุหีบห่อ: หยิบครบแล้ว
        บรรจุหีบห่อ --> [*]
    }

    กำลังดำเนินการ --> ตรวจสอบ
    ตรวจสอบ --> ผ่าน: ผ่านการควบคุมคุณภาพ
    ตรวจสอบ --> ไม่ผ่าน: พบข้อบกพร่อง
    ผ่าน --> [*]
    ไม่ผ่าน --> [*]
เปิดในตัวแก้ไข

5. พื้นที่ที่ทำงานคู่ขนาน

ขีดกลางสองขีดบนบรรทัดของตัวเองแบ่งสถานะประกอบออกเป็นพื้นที่ที่ทำงานพร้อมกัน นี่คือสิ่งเดียวที่ไดอะแกรมสถานะทำได้และผังงานทำไม่ได้จริง ๆ

stateDiagram-v2
    [*] --> การสมัคร

    state การสมัคร {
        [*] --> ยังไม่ยืนยันอีเมล
        ยังไม่ยืนยันอีเมล --> ยืนยันอีเมลแล้ว: คลิกลิงก์แล้ว
        --
        [*] --> โปรไฟล์ว่าง
        โปรไฟล์ว่าง --> โปรไฟล์ครบ: ส่งแบบฟอร์มแล้ว
    }

    การสมัคร --> ใช้งานได้: ครบทั้งสองอย่าง
    ใช้งานได้ --> [*]
เปิดในตัวแก้ไข

สรุปไวยากรณ์ไดอะแกรมสถานะ

ใช้ `stateDiagram-v2` ไม่ใช่ `stateDiagram` ทั้งคู่แสดงผลได้ แต่ v2 คือเอนจินจัดวางที่ยังพัฒนาอยู่ และรับมือกับสถานะประกอบและสถานะคู่ขนานได้ดีกว่าอย่างเห็นได้ชัด

ไวยากรณ์ความหมาย
stateDiagram-v2เปิดไดอะแกรม `stateDiagram` ยังใช้ได้แต่ใช้การจัดวางแบบเก่า
[*] --> Aสถานะเริ่มต้น — จุดเข้า
A --> [*]สถานะสุดท้าย
A --> Bการเปลี่ยนสถานะที่ไม่มีชื่อ
A --> B: เหตุการณ์การเปลี่ยนสถานะที่กำกับด้วยเหตุการณ์ที่ทำให้เกิด
state "ป้ายกำกับ" as ตัวระบุป้ายกำกับที่อ่านง่ายพร้อมตัวระบุที่ไม่มีช่องว่าง
state A { ... }สถานะประกอบ ที่มีเครื่องสถานะของตัวเองอยู่ข้างใน
--ภายในสถานะประกอบ ใช้แบ่งเป็นพื้นที่คู่ขนาน
state x <<choice>>จุดแตกแขนงตามเงื่อนไข
state f <<fork>> / <<join>>แยกเป็นการเปลี่ยนสถานะคู่ขนานแล้วรวมกลับ
note right of A: ข้อความเพิ่มหมายเหตุ มี `note left of` ด้วย
direction LRจัดวางเครื่องสถานะจากซ้ายไปขวาแทนบนลงล่าง
โฆษณา

หกข้อผิดพลาดที่ทำให้ไดอะแกรมสถานะพัง

สร้างซ้ำบน Mermaid 11.12.2 สี่ข้อแรกหยุดการแสดงผล สองข้อสุดท้ายแย่กว่านั้น เพราะมันแสดงผลออกมาหน้าตาเฉยและคืนไดอะแกรมที่ไม่ได้มีความหมายอย่างที่คุณเขียน

สิ่งที่คุณเห็น

แสดงผลได้ แต่สถานะเดียวกลายเป็นหลายกล่อง

ทำไม

มีช่องว่างอยู่ในตัวระบุสถานะ ภาษาไทยเจอเรื่องนี้น้อยกว่าภาษาอื่นมาก เพราะเราไม่เว้นวรรคระหว่างคำ แต่ยังเกิดได้อยู่ดี เพราะเราเว้นวรรคคั่นวลีและเว้นรอบตัวเลขกับอักษรละติน Mermaid ไม่ปฏิเสธและไม่ถือว่าส่วนที่เหลือเป็นคำอธิบาย มันสร้างกล่องแยกให้ทุกชิ้นที่คั่นด้วยช่องว่าง โดยมีเพียงชิ้นแรกที่ต่อกับลูกศร ส่วนกลไกคำอธิบายมีอยู่จริงแต่ต้องใช้ทวิภาค เช่น `waitPay: กำลังรอเงินโอนเข้า`

วิธีแก้

ประกาศสถานะด้วย `state "ป้ายกำกับ" as ตัวระบุ` แล้วอ้างถึงมันด้วยตัวระบุเสมอ โดยเฉพาะเมื่อชื่อสถานะมีตัวเลขหรืออักษรละตินปนอยู่

ผิด
stateDiagram-v2
    [*] --> รอชำระ 24 ชั่วโมง
    รอชำระ 24 ชั่วโมง --> ปิดแล้ว
ถูก
stateDiagram-v2
    state "รอชำระ 24 ชั่วโมง" as waitPay
    [*] --> waitPay
    waitPay --> ปิดแล้ว

สิ่งที่คุณเห็น

Parse error ที่ลงท้ายด้วย: got 'INVALID'

ทำไม

มีขีดกลางอยู่ในตัวระบุสถานะ ชื่อที่มีขีดกลางเป็นสิ่งที่นึกออกได้เองเมื่อพยายามเลี่ยงช่องว่าง แต่ขีดกลางถูกอ่านว่าเป็นจุดเริ่มของลูกศรเปลี่ยนสถานะ

วิธีแก้

ใช้คำเดียวหรือขีดล่างสำหรับตัวระบุ แล้วใส่ข้อความที่อ่านได้ไว้ในป้ายกำกับที่อยู่ในเครื่องหมายคำพูด

ผิด
stateDiagram-v2
    [*] --> in-progress
    in-progress --> ปิดแล้ว
ถูก
stateDiagram-v2
    state "กำลังดำเนินการ" as inProgress
    [*] --> inProgress
    inProgress --> ปิดแล้ว

สิ่งที่คุณเห็น

Parse error ภายในสถานะประกอบ

ทำไม

สถานะประกอบที่เปิดด้วย `{` แล้วไม่เคยปิด วงเล็บปีกกาปิดต้องอยู่บนบรรทัดของตัวเอง

วิธีแก้

ปิดบล็อกให้เรียบร้อย

ผิด
stateDiagram-v2
    [*] --> ภายนอก
    state ภายนอก {
        [*] --> ภายใน
ถูก
stateDiagram-v2
    [*] --> ภายนอก
    state ภายนอก {
        [*] --> ภายใน
    }

สิ่งที่คุณเห็น

Lexical error on line N. Unrecognized text.

ทำไม

ตัวแบ่งพื้นที่คู่ขนานเขียนด้วยจำนวนขีดกลางที่ผิด ภายในสถานะประกอบและบนบรรทัดของตัวเอง มันต้องเป็นสองขีดพอดี สามขีดเป็นโทเคนคนละตัวไปเลย

วิธีแก้

ใช้ `--` เป๊ะ ๆ

ผิด
stateDiagram-v2
    state ทั้งสอง {
        [*] --> A
        ---
        [*] --> B
    }
ถูก
stateDiagram-v2
    state ทั้งสอง {
        [*] --> A
        --
        [*] --> B
    }

สิ่งที่คุณเห็น

Parse error on line 1 ที่ลงท้ายด้วย: got 'ID'

ทำไม

ส่วนต่อท้ายรุ่นที่ไม่มีอยู่จริง มีแค่ `stateDiagram` กับ `stateDiagram-v2` เท่านั้น ไม่มีอย่างอื่น `-v3` ล้มตั้งแต่บรรทัดแรก

วิธีแก้

ใช้ `stateDiagram-v2`

ผิด
stateDiagram-v3
    [*] --> ฉบับร่าง
ถูก
stateDiagram-v2
    [*] --> ฉบับร่าง

สิ่งที่คุณเห็น

แสดงผลได้ แต่จุดตัดสินใจถูกวาดเป็นสถานะธรรมดา

ทำไม

การประกาศ `<<choice>>` มาหลังการเปลี่ยนสถานะที่ใช้มัน Mermaid สร้างสถานะขึ้นทันทีที่เจอครั้งแรก และสเตอริโอไทป์ที่เติมทีหลังไม่เปลี่ยนสิ่งที่สร้างไปแล้ว

วิธีแก้

ประกาศสถานะเทียมก่อนการเปลี่ยนสถานะที่อ้างถึงมัน

ผิด
stateDiagram-v2
    [*] --> ตรวจสอบ
    ตรวจสอบ --> ผ่าน
    ตรวจสอบ --> ไม่ผ่าน
    state ตรวจสอบ <<choice>>
ถูก
stateDiagram-v2
    state ตรวจสอบ <<choice>>
    [*] --> ตรวจสอบ
    ตรวจสอบ --> ผ่าน
    ตรวจสอบ --> ไม่ผ่าน

หมายเหตุเรื่องการแสดงผล

วัดบน Mermaid 11.12.2 ซึ่งเป็นรุ่นที่เว็บนี้ใช้

ที่นี่อักษรไทยใช้เป็นตัวระบุได้ ต่างจากผังงาน

ข้อแตกต่างนี้ควรรู้เพราะใช้ประโยชน์ได้จริง อักษรไทยในตัวระบุโหนดของผังงานและในชื่อคลาสให้ `Lexical error` แต่ในตัวระบุสถานะกลับใช้ได้ ทดสอบแล้วว่า `[*] --> รอชำระ` แสดงผลได้ และตัวระบุที่ออกมาคือ `state-รอชำระ` เอนทิตีในไดอะแกรม ER ก็เช่นเดียวกัน แปลว่าข้อจำกัดด้านอักษรมีอยู่แค่สองประเภทเท่านั้น ไม่ใช่ทั้งหมด ตัวอย่างในหน้านี้จึงใช้อักษรไทยเป็นตัวระบุตรง ๆ ได้

การไม่เว้นวรรคของภาษาไทยช่วยกันกับดักช่องว่างไว้ได้เกือบหมด

เป็นข้อได้เปรียบที่แท้จริงและควรพูดถึง ในภาษาตะวันตก ภาษาเวียดนาม และภาษาอินโดนีเซีย ช่องว่างในตัวระบุสถานะทำให้สถานะเดียวแตกเป็นกล่องละคำอย่างเงียบ ๆ ภาษาไทยเขียนติดกัน ชื่ออย่าง `รอชำระเงิน` จึงเป็นโทเคนเดียวโดยธรรมชาติและไม่แตก แต่อย่าวางใจจนเกินไป เพราะเรายังเว้นวรรคคั่นวลีและเว้นรอบตัวเลขกับอักษรละติน ชื่อสถานะอย่าง `รอชำระ 24 ชั่วโมง` จึงยังแตกอยู่ดี

ความสูงเพิ่มราว 114 พิกเซลต่อสถานะ

วัดแล้ว สามสถานะให้ viewBox ราว 91×348 ส่วนสี่สิบสถานะให้ 100×4566 คือราว 114 พิกเซลต่อสถานะ เช่นเดียวกับผังงาน ความกว้างแทบไม่ขยับ เครื่องสถานะโตลงข้างล่าง ถ้าวงจรชีวิตยาวและแตกแขนงน้อย การใส่ `direction LR` ลงในไดอะแกรมคือทางแก้ตามปกติ

ทั้ง stateDiagram และ stateDiagram-v2 แสดงผลได้ และนั่นแหละคือกับดัก

มักอ่านเจอว่า «ถ้าไม่ใช้ `stateDiagram-v2` จะไม่แสดงผลอะไรเลย» ในรุ่น 11.12.2 นั่นไม่จริง คำสำคัญทั้งสองแสดงผลได้โดยไม่มีข้อผิดพลาด สิ่งที่ต่างคือคุณภาพของการจัดวาง โดยเฉพาะกับสถานะประกอบและสถานะคู่ขนาน และเมื่อใช้ตัวเก่าก็ไม่มีคำเตือนใด ๆ ปรากฏ ถ้าสถานะประกอบดูอัดแน่นหรือลูกศรวิ่งอ้อมแปลก ๆ ให้ดูก่อนว่าคุณเปิดไดอะแกรมด้วยคำสำคัญตัวไหน ก่อนจะลงมือเขียนใหม่

ป้ายกำกับเป็น HTML การส่งออก PNG จึงวาดใหม่

เช่นเดียวกับผังงาน ไดอะแกรมคลาส และ ER ป้ายกำกับของสถานะก็ถูกวาดภายใน `<foreignObject>` ในไฟล์ SVG เนื่องจากเบราว์เซอร์ปฏิเสธที่จะแปลงสิ่งนั้นเป็นภาพแรสเตอร์บนแคนวาส การส่งออก PNG ของเว็บนี้จึงวาดไดอะแกรมใหม่ด้วยป้ายกำกับข้อความ SVG ล้วนก่อน ไฟล์ PNG ออกมาถูกต้องและเต็มขนาด ส่วนการจัดวางตัวอักษรต่างจากบนจอเพียงเล็กน้อยมาก

เมื่อใดควรใช้ไดอะแกรมประเภทอื่น

ถ้าป้ายกำกับของคุณเป็นการกระทำ เช่น ตรวจสอบ ส่ง ลองใหม่ แสดงว่าคุณกำลังอธิบายกระบวนการ ไม่ใช่วงจรชีวิต และตัวเลือกที่ซื่อตรงคือผังงาน สัญญาณที่ชัดที่สุดคือคุณตอบไม่ได้ว่า «สิ่งที่อยู่ในสถานะนี้คืออะไร»

ถ้ามีหลายองค์ประกอบที่ต่างก็มีวงจรชีวิตของตัวเอง และสิ่งที่น่าสนใจคือปฏิสัมพันธ์ระหว่างกัน การทำไดอะแกรมสถานะหนึ่งอันต่อองค์ประกอบ บวกกับไดอะแกรมลำดับหนึ่งอันสำหรับปฏิสัมพันธ์ ย่อมดีกว่าเครื่องสถานะยักษ์เพียงเครื่องเดียว

ถ้าทุกสถานะเชื่อมกับทุกสถานะ ไดอะแกรมจะพันกันยุ่งไม่ว่าคุณจะวาดอย่างไร โดยทั่วไปนั่นแปลว่าสิ่งที่คุณไล่เรียงมาเป็นสถานะนั้น แท้จริงแล้วคือธงที่ประกอบกันได้อย่างอิสระ ในกรณีนั้นตารางของชุดที่ถูกต้องบอกอะไรได้มากกว่าภาพหนึ่งภาพมาก

ไดอะแกรมประเภทอื่น

เขียนโดย Dominik Malsch · อัปเดตล่าสุด:

เปิดตัวแก้ไข →