[blockly 系列] 第 1 篇 环境搭建

·  阅读 3843

blockly 是 google 用于可视化编程的开源库,可以以积木式编程的方式开发程序,没错,就是传说中的通过拖拽写代码。听起来很离谱但在某些场合有着不可替代的作用,也有一定的商业价值,比如 MIT 与 google 合作出品的 Scratch,通过拖拽的方式生成动画,是青少年学习编程的重要工具,国内在 Scratch 基础上进行优化的编程猫,听说 B 轮融资了1.2亿。

为什么会研究一下 blockly, 来源于公司项目中一个需求--给用户提供一个开发者平台,通过对预定义组件的拖拽和排序来生成可应用于移动端跨平台的小程序,本着高涨的学习热情与求知欲(呵呵呵。。。),所以有了这系列文章,一切从一个 demo 开始吧。

环境搭建

学习 blockly 之前, 首先需要从 github 克隆 google/blockly 源码到本地,官方提供了很多 demo 来供我们学习使用,先看一下源码目录结构(只展示一级目录),对搭建环境需要用到的库做了注释。

ps: 这个目录是不是看起来还挺漂亮,此处应该留下链接 mddir

|-- blockly
    |-- .eslintignore
    |-- .eslintrc.json
    |-- .gitignore
    |-- .jshintignore
    |-- .npmrc
    |-- .travis.yml
    |-- blockly_accessible_compressed.js
    |-- blockly_accessible_uncompressed.js
    |-- blockly_compressed.js // 核心库
    |-- blockly_uncompressed.js
    |-- blocks_compressed.js // 核心库
    |-- build.py
    |-- dart_compressed.js
    |-- gulpfile.js
    |-- javascript_compressed.js // js代码生成器
    |-- LICENSE
    |-- lua_compressed.js
    |-- package.json
    |-- php_compressed.js
    |-- python_compressed.js
    |-- README.md
    |-- .github
    |-- accessible
    |-- appengine
    |-- blocks
    |-- core
    |-- externs
    |-- generators
    |-- i18n
    |-- local_build
    |   |-- local_build.sh
    |-- media
    |-- msg
    |   |-- zh-hans.js // 简体中文语言包
    

新建一个 index.html 文件,通过引入外部资源方式移入 js 文件,像这样下面这样我们就完成了环境的搭建,在实际项目中可能需要在 vue | react 这样的前端框架中使用 blockly,这个可以后边详细讨论,无论如何,我们先完成一个最简单的示例。

    <script src="./static/blockly_compressed.js"></script>
    <script src="./static/blocks_compressed.js"></script>
    <script src="./static/javascript_compressed.js"></script>
    <script src="./static/msg/js/zh-hans.js"></script>

定义一个 block (可视化代码块)

搭建好环境,我们就可以进入开发了,比如先输出一个 'hello world'。blockly 中使用 xml 定义一个 block,可以通过标签方式引入到工作区, 比如 <block type="hello"></block> 这样就引入了一个 name 为 hello 的代码块,下面的代码展示了 hello 这个 block 是如何定义的,自定义代码块是使用 blockly 的核心,由于内容比较多就放到下一篇详细介绍。

// 通过 js 定义一个代码块
Blockly.Blocks['hello'] = {
  init: function() {
    this.appendDummyInput()
    .appendField("输出")
    .appendField(new Blockly.FieldTextInput("hello world"), "say_content");
    this.setInputsInline(true);
    this.setPreviousStatement(true, null);
    this.setNextStatement(true, null);
    this.setColour(230);
 this.setTooltip("");
 this.setHelpUrl("");
  }
};


定义一个 block 有两种方式 js | json , 既然 js 可以搞定,为毛又搞个 json? 下面是官方给的解释,可以看出通过 json 格式 定义一个 block 可以实现跨平台,不仅可以用在web, 还可以用在 Android and iOS。另外 json 格式被设计用来简化开发时具有不同单词排序语言的本地化程序,我的理解是阿拉伯语之类的语言是从右往左书写的,json 能简单点吧,下面是通过 json 定义一个代码块。

Blockly has two ways of defining blocks: JSON objects and JavaScript functions. The JSON format is cross-platform so that the same code may be used to define blocks on web, Android, and iOS. Additionally, the JSON format is designed to simplify the localization process when developing for languages with different word orderings. The JSON format is the preferred method of defining blocks.

// 通过 json 定义一个代码块
{
  "type": "hello",
  "message0": "输出 %1",
  "args0": [
    {
      "type": "field_input",
      "name": "say_content",
      "text": "hello world"
    }
  ],
  "inputsInline": true,
  "previousStatement": null,
  "nextStatement": null,
  "colour": 230,
  "tooltip": "",
  "helpUrl": ""
}

解析自定义 block 为可执行代码

定义好了一个 block 是时候看一下它长什么样子了,下图:看起来像积木一样可以拼接与拖拽。

此刻从图中已经可以看明白这个 block 大概要做些什么事情,但它现在还不是一个代码块,需要我们解析为可执行代码来告诉机器,所以紧接着要做的就是写一段代码并导出,下面这段 js 代码在控制台打印出字符串 'hello world'。

// hello 是自定义代码块的名称
Blockly.JavaScript['hello'] = function (block) {
    this.text_say_content = block.getFieldValue('say_content');
    // TODO: Assemble JavaScript into code variable.
    var code = `console.log(this.text_say_content}`;
    return code;
};

添加 block 到工具箱 (toolbox)

工具箱类似左侧菜单栏,代表着一个 block 初始时放在什么地方,toolbox 以 xml 结构表示,也可以通过 Blockly Developer Tools(可视化生成 block 与 toolbox 的工具) 工具来生成,先来看看它的结构和怎么用来包含自定义代码块。

<xml id="toolbox" style="display: none">
    <block type="hello"></block>
</xml>

生成工作区

生成了 block, toolbox 最后要做的就是把它注入到当前文档的 dom 节点中,通过下面代码生成工作区,将 blockly 工具箱注入到 id="blocklyDiv" 的 div 标签中。

// html
<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>

// js
this.demoWorkspace = Blockly.inject('blocklyDiv',  
    {media: './static/media/', toolbox: document.getElementById('toolbox')}
    );

最终效果

下图中左侧灰色区域展示了工具箱与一个代码块,右侧展示了拖拽到工作区的代码块

获取合成代码

最终的工作区必然是由众多积木(代码块)搭建而成,虽然栗子中目前只有一个代码块,但不管搭建了多少积木,获取合成代码的方法是一样的

// latestCode 就是最终合成代码
this.latestCode = Blockly.JavaScript.workspaceToCode(this.demoWorkspace);

做一个演示

给文档添加两个按钮和方法,分别用来展示和执行合成的代码

写在最后

代码已上传到了Github, 可点击查看效果 blockly-demo, 下一篇将重点介绍自定义代码块与工具箱的生成,以及 Blockly Developer Tools (如果这个链接打不开,请不要怀疑网络和检查网线,原因你懂得。。。) 工具的使用。

分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改