1. 程式人生 > >模擬Scratch的視覺化指令碼編輯器(二)

模擬Scratch的視覺化指令碼編輯器(二)

本次以Markdown流程圖Flow為例,來說明Block擴充套件方法。

Created with Raphaël 2.2.0開始程式條件程式程式結束程式yesno

流程圖主要有6種Block

#開始 start
st=>start: 開始

#結束 end
e=>end: 結束

#普通操作塊 opration
op1=>opration: 第一個操作塊
op2=>opration: 第二個操作塊

#判斷塊 condition
cond1=>condition: 第一個判斷
cond2=>condition: 第二個判斷

#輸入輸出塊 inputoutput
io1=>inputoutput: 輸入輸出塊1
io2=>inputoutput: 輸入輸出塊2

#子任務塊
sub1=>subroutine: 子任務1
sub2=>subroutine: 子任務2

根據每個Block的格式,編寫描述檔案,在專案目錄/client/src/scratch/blockDefs/packages目錄下新建一個markdown目錄,在目錄中建立index.js和flow.js。
index.js檔案內容

import flow from './flow'
let blocks = []
blocks = blocks.concat(flow)
export default blocks

flow.js檔案中編寫Block定義,輸出為一個數組。以start單元為例, 先根據start語法規則** [模組名稱]=start: [標題文字]:>[超連結]**,將語法中的主要資料項轉變為section定義 START [index] TAG [模組文字] URL [超連結]

, 其中index用於Block重用,比如流程圖中某個單元Block需要在多個地方中出現,使用Scratch的表現方式只能複製多個Block,使用index表示具有相同index的多個Block其實是同一個Block,只需給第一個出現的Block填寫屬性即可,其他Block無需重複設定屬性資訊。
section定義好之後,就可以編寫Block定義檔案來,其描述資訊如下:


    {
        id: 'mk-flow-start',
        type: 'action',   // 
        shape: 'slot',
        category: 'presentation',
        draggable: true,  // 允許拖放
        state: {
          data: {
            sections: [  
              { 
                type: 'text',
                text: 'START'
              },
              {  // index
                type: 'argument',
                datatype: 'number'
              },
              {
                type: 'text',
                text: 'TAG'
              },
              { // 模組文字
                type: 'argument',
                datatype: 'string',
                data: {
                  value: '開始'
                }
              },
              {
                type: 'text',
                text: 'URL'
              },
              { // 超連結
                type: 'argument',
                datatype: 'string'
              }
            ]
          }
        }

寫好定義檔案後,修改一下包配置檔案(檔案位於專案目錄/client/src/scratch/blockDefs/index.js), 在其中引入新建的markdown包即可。

import categories from './categories'
// 載入Block包
import base from './packages/base'
import chinese from './packages/chinese'
import ml from './packages/ml'
import markdown from './packages/markdown'

export default {
  categories: categories,
  packages: [base, chinese, ml, markdown]
}

進入編輯器,就可以看見start模組(見下圖)。Block的顏色是根據category欄位來定義,可以修改改欄位來改變顏色方案。具體欄位可以檢視專案目錄/client/src/scratch/blockDefs/categories.js檔案

在這裡插入圖片描述

同理,將其餘5個Block定義編寫好(如圖)

在這裡插入圖片描述

到目前為止,只能使用編輯器進行流程圖的設計,但是並沒有生產實際的flow程式碼,需要繼續在flow.js檔案中編寫匯出函式。另外為了方便使用,額外建立來一個流程圖Block,將匯出功能放在它的上下文選單中。每次建立流程圖時,始終以這個Block作為頭部Block來建立

在這裡插入圖片描述

在Block定義中新增export屬性,是一個數組,可以提供多種匯出功能,併為匯出功能定義上下文選單資訊,其格式如下:

    export: [
          {
            menuItem: true, // 是否新增到選單上
            menuName: '匯出為MarkDown',   // 選單上顯示文字
            fmt: 'markdown',   // 匯出格式
            ext: '.md',  // 副檔名
            action: function() {  // 匯出功能實現函式
              const fmt = 'markdown'
              start = this.nextBlock()
              if (start.protoId() !== 'mk-flow-start') {
                logger.warn('MarkDown Export: first block is not <start> Block')
              }
              ...
            }
         }
      ]

在action函式中,this就是當前Block自己,可以通過this.nextBlock()來獲取下游Block,呼叫每個Block的export(fmt)來得到Block自身生成的程式碼片段,然後在根據序列結構拼接為完整的程式碼。例如start單元生成的程式碼片段為:

   st8=>start: 開始:> https://www.baidu.com

補充好export定義後,再次進入編輯器,在流程圖Block上點選右鍵,就可以看到自定義的選單項了。由於匯出程式碼比較長,可自行檢視flow.js檔案。
在這裡插入圖片描述

接下來,設計一個簡單的流程圖,測試下匯出功能。

在這裡插入圖片描述

點選“匯出為Markdown”,顯示彈出選單,輸入一個檔名,點選確定,會將生成的檔案下載到本地。
在這裡插入圖片描述

下面為匯出的程式碼為,其真實顯示圖案就是文章開頭顯示的流程圖:

   st8=>start: 開始:> https://www.baidu.com
   op9=>operation: 程式
   c10=>condition: 條件
   op11=>operation: 程式
   e12=>end: 結束
   op13=>operation: 程式
   op14=>operation: 程式
   st8->op9(bottom)->c10
   c10(no)->op14(bottom)->op11
   c10(yes, right)->op13(bottom)->op11
   op11(bottom)->e12