什么是blockly?
blockly是google发布的可视化编程工具,是一个基于web技能构建的库;blockly的目的是帮助客户创建app,使得用户(app的利用者)编程就像搭积木一样的有趣、随意马虎上手,大名鼎鼎的scratch便是一款利用类似技能的少儿编程工具。blockly有几个特点:
如果把blockly看作一个黑盒,它的输入便是用户拖放的代码块的组合,输出便是翻译出的JavaScript/python/PHP/Lua/Dart代码。
(图片来自网络侵删)blockly能做什么?
近期事情的紧张任务是针对公司的自动化测试框架进行改造,目前我司自动化测试便是利用python+selenium的办法进行自动化测试,测试职员须要利用原生的python代码进行测试用例的编写,对编程技能哀求较高,我希望通过引入blockly为测试职员供应一个可视化的、搭建积木式的编写测试用例的GUI接口,降落自动化测试的上手门槛。
blockly上手示例
条件条件:须要对HTML、CSS、JavaScript有基本的理解
google官方供应的上手示例教程,这个示例是通过blockly创建一个大略的创造音乐的app,首先下载如下示例代码:git clone https://github.com/google/blockly-samples.git
本示例代码路径如下:
getting-started-codelab
starter-code:为示例的初始代码;complete-code:为示例完成后的代码,如果自己编写期间碰着卡壳的地方,可以和官方供应的完成代码进行对照。每个目录都包含同样的目录和文件:
scripts/main.js - app的主逻辑代码music_maker.js - 一个小型的用来播放声音的库sounds/ - 声音文件styles/ - CSS样式文件index.html - 首页浏览器打开starter-code/index.html,显示如下界面(如果首次打开不能完全显示,可能是网络缘故原由,考试测验刷新浏览器试试)starter-code首页
编辑模式:
点击edit进行编辑模式,按照提示点击下方的任意数字进行代码编辑
编辑模式
点击任意一个数字之后,将显示一篇空缺区域,这里便是我们须要利用blockly进行编码的地方
点击数字进行代码编辑
编辑index.html,在如下两行script代码之前增加一行代码,引入blockly库,
<script src="https://unpkg.com/blockly"></script> <!-- 这一行是增加的代码 --><script src="scripts/music_maker.js"></script><script src="scripts/main.js"></script>
blockly将引入四个模块:
Blockly core: 紧张的核心代码,紧张定义了block UI及逻辑Built-in block definitions: 常用的积木块定义如循环, 逻辑, 数据, 和字符串操作The JavaScript generator: 将积木块天生JavaScript代码English language files: 积木块的提示措辞利用英语创建blockly事情区:事情区包括代码块编辑区和工具箱两部分
blocky事情区
编辑index.html在id="blocklyDiv"的div元素中增加如下xml构造:
<xml id="toolbox" style="display: none"> <block type="controls_repeat_ext"> <value name="TIMES"><shadow type="math_number"><field name="NUM">5</field></shadow> </value> </block></xml>
编辑scripts/main.js,在代码的末了添加如下代码
Blockly.inject('blocklyDiv', { toolbox: document.getElementById('toolbox'), scrollbars: false });
现在刷新浏览器,点击edit进入编辑模式,点击任意数字,可以创造显示了blockly工具去,工具箱有一个代码块
toolbox工具箱有一个代码块
创建定制的代码块本示例是一个创建音乐的app,我们须要创建一个能够播放声音的代码块,通过下拉菜单的办法选择不同的声音文件。
scripts目录下创建一个js文件,命名为sound_blocks.js,并在index.html首页中引入该js文件
<script src="https://unpkg.com/blockly"></script><script src="scripts/music_maker.js"></script><script src="scripts/sound_blocks.js"></script> <!--这是增加的代码行--><script src="scripts/main.js"></script>
然后在sound_blocks.js中添加如下代码
Blockly.defineBlocksWithJsonArray([ { "type": "play_sound", "message0": "Play %1", "args0": [ { "type": "field_dropdown", "name": "VALUE", "options": [ ["C4", "sounds/c4.m4a"], ["D4", "sounds/d4.m4a"], ["E4", "sounds/e4.m4a"], ["F4", "sounds/f4.m4a"], ["G4", "sounds/g4.m4a"], ["A5", "sounds/a5.m4a"], ["B5", "sounds/b5.m4a"], ["C5", "sounds/c5.m4a"] ] } ], "previousStatement": null, "nextStatement": null, "colour": 355 }]);
以上js代码定义了类型为play_sound的代码块,还须要把它加入到html页面中才能显示
<div id="blocklyDiv" style="height: 480px; width: 400px;"> <xml id="toolbox" style="display: none"> <block type="controls_repeat_ext"> <value name="TIMES"> <shadow type="math_number"> <field name="NUM">5</field> </shadow> </value> </block> <block type="play_sound"></block> <!-- 这是新增加的代码行 --> </xml> </div>
再次刷新浏览器,打开工具箱创造多了一个赤色的代码块,该代码块可以用来播放sounds目录的声音文件
play_sound代码块
保存/加载事情区现在构建好了须要的代码块,已经可以在代码编辑区进行编写了,接下来须要做的是保存和加载功能。
编辑scripts/main.js,save方法中增加如下代码,改代码实现用户点击保存是将事情区的代码块保存为xml格式
function save(button) { // 增加的代码行 button.blocklyXml = Blockly.Xml.workspaceToDom(Blockly.getMainWorkspace()); }
保存成功后,下次进入点击数字进入事情区还须要将事情区的代码块加载出来,连续编辑main.js,增加如下方法
// 增加的代码 --- startfunction loadWorkspace(button) { let workspace = Blockly.getMainWorkspace(); workspace.clear(); if (button.blocklyXml) { Blockly.Xml.domToWorkspace(button.blocklyXml, workspace); } }// 增加的代码 --- endfunction enableBlocklyMode(e) { document.body.setAttribute('mode', 'blockly'); currentButton = e.target; loadWorkspace(currentButton); // 这一行是增加的代码 }
现在考试测验刷新浏览器,点击edit进入编辑模式,点击指天命字进行代码块编辑后点击save保存,然后再次返回后事情区仍旧保留了上次编辑的代码块。
保存事情区
天生JavaScript代码编辑scripts/sound_blocks.js,增加如下代码
Blockly.JavaScript['play_sound'] = function(block) { let value = '\'' + block.getFieldValue('VALUE') + '\''; return 'MusicMaker.queueSound(' + value + ');\n';};
这段代码的会将play_sound代码块天生如下js代码"MusicMaker.queueSound('Sounds/c4.m4a');"(注:这里展示的代码以C4选项为例)。
运行天生的JavaScript代码编辑scripts/main.js,handlePlay方法中增加如下代码
function handlePlay(event) { // 增加的代码 -- start loadWorkspace(event.target); let code = Blockly.JavaScript.workspaceToCode(Blockly.getMainWorkspace()); code += 'MusicMaker.play();'; try { eval(code); } catch (error) { console.log(error); } // 增加的代码 -- end}
现在music maker的app就全部完成,重新刷新浏览器,点击edit进入编辑模式,然后点击不同的数字进行编程,可以根据代码块的提示设置播放什么声音,播放的次数,编辑完成后点击Done就进入运行模式,此时点击相应的数字就会播放音乐了,还是蛮好玩的,快试试吧。
二、blockly——事情区
下载blockly首先须要获取blockly代码,官方文档中获取blockly代码有npm、github、Unpkg等多种办法。本文利用github,访问blockly github仓库链接https://github.com/google/blockly并下载,下载后的blockly代码目录构造如下:
blockly代码目录构造
注:上手阶段只需关注图中赤色标注的三个文件和目录,个中msg目录暂时只用到msg/js目录中的措辞包,本文采取msg/js/zh-hans.js,表示为代码块利用的措辞为中文。
项目目录构造新建目录名为blockly-demo的文件夹,增加index.html,将已经下载的blockly代码也复制到该目录下,如下图:
blockly-demo项目目录构造
导入根本模块利用自己喜好的编辑器,添加如下代码,利用blockly须要引入blockly_compressed.js、blocks_compressed.js、msg/js/zh-hans.js三个根本模块,个中blockly_compressed.js为核心脚本,blocks_compressed.js为核心图形代码块集,zh-hans.js为措辞模块,本例利用中文。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>blockly demo</title></head><body> <!-- 导入blockly根本模块 --> <script src="./blockly/blockly_compressed.js"></script> <script src="./blockly/blocks_compressed.js"></script> <script src="./blockly/msg/js/zh-hans.js"></script></body></html>
创建事情区现在,通过浏览器打开index.html文件会显示一片空缺,什么都不会发生,要利用blockly须要首先创建事情区,事情区是blockly的核心,下图便是一个范例的事情区的样子,由工具箱和图形代码编辑区两部分组成。
事情区=工具箱+编辑区
要创建事情区首先须要创建一个空缺的div元向来承载,其余通过嵌入xml来表示工具箱,由于xml不能在浏览器中正常渲染,因此须要设置为不可见,编辑index.html增加如下代码
<!-- 空缺div元素,用来承载事情区 --><div id="blocklyDiv" style="height: 480px; width: 600px;"></div><!-- 工具箱 block表示为一种代码块 这里有7个代码块--><xml id="toolbox" style="display: none"> <block type="controls_if"></block> <block type="controls_repeat_ext"></block> <block type="logic_compare"></block> <block type="math_number"></block> <block type="math_arithmetic"></block> <block type="text"></block> <block type="text_print"></block></xml>
接下来便是调用blockly供应的api来天生事情区了,编辑index.html在页面的末了增加js脚本,Blockly.inject方法用来注入事情区到id为blocklyDiv的DOM元素中,也便是传入的第一个参数,第二个参数为键值对的字典形式的配置参数,这里传入的参数为id为toolbox表示的工具箱的信息。
<script> var workspace = Blockly.inject('blocklyDiv', {toolbox: document.getElementById('toolbox')});</script>
index.html的完全代码参考
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>blockly demo</title></head><body> <div id="blocklyDiv" style="height: 480px; width: 600px;"></div> <xml id="toolbox" style="display: none"> <block type="controls_if"></block> <block type="controls_repeat_ext"></block> <block type="logic_compare"></block> <block type="math_number"></block> <block type="math_arithmetic"></block> <block type="text"></block> <block type="text_print"></block> </xml> <script src="./blockly/blockly_compressed.js"></script> <script src="./blockly/blocks_compressed.js"></script> <script src="./blockly/msg/js/zh-hans.js"></script> <script> var workspace = Blockly.inject('blocklyDiv', {toolbox: document.getElementById('toolbox')}); </script></body></html>
此时浏览器再次打开或者刷新已打开的index.html,页面显示如下图,试试拖放工具箱中的代码块到编辑区,此时我们就完成了一个固定大小的事情区的创建。
完成事情区的注入
三、blockly——可调度大小的事情区
本文在基于这篇文章的根本上演示如何创建一个动态变革的blockly事情区。
1.创建html页面区域首先须要指定一个html元向来放置blockly事情区,事情区须要根据该元素的坐标和尺寸动态调度布局,该元素可以利用div、table等元素,唯一的哀求是须要指定id。至于CSS须要根据自己的运用设计进行性调度,本文以占满屏幕的div元素作为示例,编辑index.html代码,增加如下代码:
<div id="blocklyArea" style="min-height: 100vh;"></div>
2.注入blockly接下来便是调用blockly的inject方法来向html页面注入事情区代码,和可视化编程工具blockly——事情区一文中的代码是一样的
<div id="blocklyDiv" style="position: absolute"></div><xml id="toolbox" style="display: none"> <block type="controls_if"></block><block type="controls_repeat_ext"></block><block type="logic_compare"></block><block type="math_number"></block><block type="math_arithmetic"></block><block type="text"></block><block type="text_print"></block></xml><script src="./blockly/blockly_compressed.js"></script><script src="./blockly/blocks_compressed.js"></script><script src="./blockly/msg/js/zh-hans.js"></script><script> var blocklyArea = document.getElementById('blocklyArea'); var blocklyDiv = document.getElementById('blocklyDiv'); var workspace = Blockly.inject(blocklyDiv, {toolbox: document.getElementById('toolbox')}); </script>
3.定位末了一步的目的是监听浏览器窗口大小变革韶光,一旦窗口有变革就打算blocklyArea的坐标和尺寸,然后动态调度blockly事情区的尺寸和坐标已适配窗口的变革,干系部分的代码如下:
<script> var blocklyArea = document.getElementById('blocklyArea'); var blocklyDiv = document.getElementById('blocklyDiv'); var workspace = Blockly.inject(blocklyDiv, {toolbox: document.getElementById('toolbox')});// ------------------定位部分代码 start------------------- var onresize = function(e) { // 打算blocklyArea元素的绝对坐标和尺寸 var element = blocklyArea; var x = 0; var y = 0; do { x += element.offsetLeft; y += element.offsetTop; element = element.offsetParent; } while (element); // 将blocklyDiv定位到blocklyArea区域上 blocklyDiv.style.left = x + 'px'; blocklyDiv.style.top = y + 'px'; blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; Blockly.svgResize(workspace); //重新渲染事情区 };// 监听浏览器窗口的resize事宜,触发onresize方法 window.addEventListener('resize', onresize, false); // 初次打开页面须要打算一次blocklyArea元素的坐标和尺寸并渲染事情区 onresize(); Blockly.svgResize(workspace); // ------------------定位部分代码 end------------------- </script>
浏览器打开index.html,可以看到blockly事情区填满了全体屏幕,考试测验调度浏览器窗口大小,事情区尺寸也会随之而变革
尺寸动态变革的事情区
完全的代码参考:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>blockly demo</title></head><body> <div id="blocklyArea" style="min-height: 100vh;"></div> <div id="blocklyDiv" style="position: absolute"></div> <xml id="toolbox" style="display: none"> <block type="controls_if"></block> <block type="controls_repeat_ext"></block> <block type="logic_compare"></block> <block type="math_number"></block> <block type="math_arithmetic"></block> <block type="text"></block> <block type="text_print"></block> </xml> <script src="./blockly/blockly_compressed.js"></script> <script src="./blockly/blocks_compressed.js"></script> <script src="./blockly/msg/js/zh-hans.js"></script> <script> var blocklyArea = document.getElementById('blocklyArea'); var blocklyDiv = document.getElementById('blocklyDiv'); var workspace = Blockly.inject(blocklyDiv, {toolbox: document.getElementById('toolbox')}); var onresize = function(e) { // 打算blocklyArea元素的绝对坐标和尺寸 var element = blocklyArea; var x = 0; var y = 0; do { x += element.offsetLeft; y += element.offsetTop; element = element.offsetParent; } while (element); // 将blocklyDiv定位到blocklyArea区域上 blocklyDiv.style.left = x + 'px'; blocklyDiv.style.top = y + 'px'; blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; Blockly.svgResize(workspace); }; window.addEventListener('resize', onresize, false); onresize(); Blockly.svgResize(workspace); </script></body></html>
四、blockly——工具箱
blockly工具箱支持xml和json两种办法定义,本文利用xml演示,json办法创建工具箱可参考google官网文档https://developers.google.cn/blockly/guides/configure/web/toolbox。
创建分组的工具箱工具箱便是可供用户利用的代码块,默认显示在事情区的左侧,如果代码块较多的话最好能分类组织,工具箱的代码通过在index.html中id为toolbox的xml代码进行定义,blcokly会解析xml并注入到页面图形化的工具箱代码DOM,如下图的工具箱包含了掌握、逻辑两个种别。
对应的xml定义代码如下,个中category定义了一个分类,block定义了代码块,type指定的种别都是blockly默认供应的,定义代码在./blockly/blocks目录下
<xml id="toolbox" style="display: none"> <category name="掌握"> <block type="controls_if"></block> <block type="controls_whileUntil"></block> <block type="controls_for"> </category> <category name="逻辑"> <block type="logic_compare"></block> <block type="logic_operation"></block> <block type="logic_boolean"></block> </category> </xml>
工具箱还可以多层嵌套定义,如下xml定义的工具箱效果如下:
<xml id="toolbox" style="display: none"> <category name="核心"> <category name="掌握"> <block type="controls_if"></block> <block type="controls_whileUntil"></block> </category> <category name="逻辑"> <block type="logic_compare"></block> <block type="logic_operation"></block> <block type="logic_boolean"></block> </category> </category> <category name="数学"> <block type="math_constant"></block> <category name="算术"> <block type="math_arithmetic"></block> <block type="math_number"></block> </category> <category name="三角"> <block type="math_single"></block> <block type="math_trig"></block> </category> </category> </xml>
设置分组颜色
工具箱分组种别还可以指定颜色,通过colour属性进行设定,colour值的范围是0~360,如下xml代码天生的工具箱效果如下:
动态类别的代码块
<xml id="toolbox" style="display: none"> <category name="逻辑" colour="20"> <block type="controls_if"></block> <block type="controls_whileUntil"></block> <block type="controls_for"> </category> <category name="掌握" colour="200"> <block type="logic_compare"></block> <block type="logic_operation"></block> <block type="logic_boolean"></block> </category></xml>
blockly供应的工具箱中有两类有着分外的行为,分别是变量和函数,它们的xml定义中拥有custom属性,分别为VARIABLE和PROCEDURE,代码及显示效果如下:
<xml id="toolbox" style="display: none"> <category name="变量" custom="VARIABLE"></category> <category name="函数" custom="PROCEDURE"></category> </xml>
个中变量分组中点击创建变量并按照提示输入变量名称后会天生如下三个代码块:
函数分组中包含三个代码块,前两个为方法定义,一个方法带有返回值,第三个为条件返回的代码块,通过这三个代码块我们可以编写新的方法来天生新的代码块,如下定义一个inc方法会天生一个新的代码块inc,该方法将输入的x变量增加1并返回,新天生的代码块又可以作为代码块进行利用:
带缺省值的代码块
有些代码块希望拥有缺省值,如下代码天生工具箱效果如下:
<xml id="toolbox" style="display: none"> <block type="logic_boolean"></block> <block type="math_number"> <field name="NUM">42</field> </block> <block type="math_arithmetic"> <field name="OP">ADD</field> <value name="A"> <shadow type="math_number"> <field name="NUM">1</field> </shadow> </value> <value name="B"> <shadow type="math_number"> <field name="NUM">1</field> </shadow> </value> </block> </xml>
个中:
logic_boolean不须要事先设置,默认值为真(true);math_number通过field设置缺省值42;math_arithmetic利用field、value,加上shadow blocks实现了缺省值的设置。五、blockly——天生代码
blockly通过拖动可视化的代码块来实现编程,普遍的运用处景是少儿编程,不过官方流传宣传blockly不是玩具,它可以实现繁芜的编程任务;代码块只是供应了可视化的接口,终极实行的还是代码,blockly支持天生多种措辞的代码,如JavaScript, Python, PHP, Lua, Dart,除此之外blockly拥有高度可定制化的特性,你还可以完备定制天生自己的所需的任何措辞。本文以天生python措辞为例进行演示,目前利用的内置的block。
定义工具箱通过xml办法定义两个种别为文本和列表的工具箱,代码(index.html)及渲染的工具箱如下:
<xml xmlns="https://developers.google.com/blockly/xml" id="toolbox" style="display: none"> <category name="文本" colour="%{BKY_TEXTS_HUE}"> <block type="text"></block> <block type="text_join"></block> <block type="text_append"> <value name="TEXT"> <shadow type="text"></shadow> </value> </block> <block type="text_length"> <value name="VALUE"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_isEmpty"> <value name="VALUE"> <shadow type="text"> <field name="TEXT"></field> </shadow> </value> </block> <block type="text_indexOf"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> <value name="FIND"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_charAt"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> </block> <block type="text_getSubstring"> <value name="STRING"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> </block> <block type="text_changeCase"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_trim"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_print"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_prompt_ext"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> </category> <category name="列表" colour="%{BKY_LISTS_HUE}"> <block type="lists_create_with"> <mutation items="0"></mutation> </block> <block type="lists_create_with"></block> <block type="lists_repeat"> <value name="NUM"> <shadow type="math_number"> <field name="NUM">5</field> </shadow> </value> </block> <block type="lists_length"></block> <block type="lists_isEmpty"></block> <block type="lists_indexOf"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_getIndex"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_setIndex"> <value name="LIST"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_getSublist"> <value name="LIST"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_split"> <value name="DELIM"> <shadow type="text"> <field name="TEXT">,</field> </shadow> </value> </block> <block type="lists_sort"></block> </category> </xml>
天生python
blockly/generators目录下的文件为天生的代码部分的代码,实际利用时引用blockly/python_compressed.js供应的压缩版本即可
<script src="./blockly/blockly_compressed.js"></script> <!--blockly的核心代码--><script src="./blockly/blocks_compressed.js"></script> <!--代码块定义--><script src="./blockly/python_compressed.js"></script> <!--天生python代码--><script src="./blockly/msg/js/zh-hans.js"></script> <!--中文措辞支持-->
天生python代码便是一条语句:
var code = Blockly.Python.workspaceToCode(workspace);
监听事宜,实时刷新代码blockly事情区天生代码的效率很高,为ms级,因此无需担心频繁更新代码导致性能问题,常日的做法是监听工具的change事宜来实时天生代码,这里以在掌握台输出为例:
function myUpdateFunction(event) { var code = Blockly.Python.workspaceToCode(workspace); // 将事情区代码块天生代码 console.log(code); // 掌握台显示天生的代码}workspace.addChangeListener(myUpdateFunction); // 监听事情区改变事宜
浏览器打开index.html,向事情区中放置一些代码,掌握台将会实时打印天生代码,如下是建立python列表的代码块及天生的代码:
点击紫色代码块中的蓝色按钮可以持续增加列表的项目,天生的代码也会相应的更新
index.html完全的代码如下:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <title>blockly demo</title></head><body> <div id="blocklyArea" style="min-height: 100vh;"></div> <div id="blocklyDiv" style="position: absolute"></div> <xml xmlns="https://developers.google.com/blockly/xml" id="toolbox" style="display: none"> <category name="文本" colour="%{BKY_TEXTS_HUE}"> <block type="text"></block> <block type="text_join"></block> <block type="text_append"> <value name="TEXT"> <shadow type="text"></shadow> </value> </block> <block type="text_length"> <value name="VALUE"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_isEmpty"> <value name="VALUE"> <shadow type="text"> <field name="TEXT"></field> </shadow> </value> </block> <block type="text_indexOf"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> <value name="FIND"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_charAt"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> </block> <block type="text_getSubstring"> <value name="STRING"> <block type="variables_get"> <field name="VAR">{textVariable}</field> </block> </value> </block> <block type="text_changeCase"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_trim"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_print"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> <block type="text_prompt_ext"> <value name="TEXT"> <shadow type="text"> <field name="TEXT">abc</field> </shadow> </value> </block> </category> <category name="列表" colour="%{BKY_LISTS_HUE}"> <block type="lists_create_with"> <mutation items="0"></mutation> </block> <block type="lists_create_with"></block> <block type="lists_repeat"> <value name="NUM"> <shadow type="math_number"> <field name="NUM">5</field> </shadow> </value> </block> <block type="lists_length"></block> <block type="lists_isEmpty"></block> <block type="lists_indexOf"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_getIndex"> <value name="VALUE"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_setIndex"> <value name="LIST"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_getSublist"> <value name="LIST"> <block type="variables_get"> <field name="VAR">{listVariable}</field> </block> </value> </block> <block type="lists_split"> <value name="DELIM"> <shadow type="text"> <field name="TEXT">,</field> </shadow> </value> </block> <block type="lists_sort"></block> </category> </xml> <script src="./blockly/blockly_compressed.js"></script> <script src="./blockly/blocks_compressed.js"></script> <script src="./blockly/python_compressed.js"></script> <script src="./blockly/msg/js/zh-hans.js"></script> <script> var blocklyArea = document.getElementById('blocklyArea'); var blocklyDiv = document.getElementById('blocklyDiv'); var workspace = Blockly.inject(blocklyDiv, { media: './blockly/media/', toolbox: document.getElementById('toolbox'), grid: {spacing: 20, length: 3, colour: '#ccc', snap: true}, zoom: {controls: true, wheel: true, startScale: 1.0, maxScale: 3, minScale: 0.3, scaleSpeed: 1.2, pinch: true}, trashcan: true }); var onresize = function(e) { // 打算blocklyArea元素的绝对坐标和尺寸 var element = blocklyArea; var x = 0; var y = 0; do { x += element.offsetLeft; y += element.offsetTop; element = element.offsetParent; } while (element); // 将blocklyDiv定位到blocklyArea区域上 blocklyDiv.style.left = x + 'px'; blocklyDiv.style.top = y + 'px'; blocklyDiv.style.width = blocklyArea.offsetWidth + 'px'; blocklyDiv.style.height = blocklyArea.offsetHeight + 'px'; Blockly.svgResize(workspace); }; window.addEventListener('resize', onresize, false); onresize(); Blockly.svgResize(workspace); function myUpdateFunction(event) { var code = Blockly.Python.workspaceToCode(workspace); console.log(code); } workspace.addChangeListener(myUpdateFunction); </script></body></html>