【Blockly图形化积木编程二次开发学习笔记】4.自定义语言生成器

文章目录

初始化自己的语言生成器

本示例中,在.\my_generators\text_generator.js中构造了一个用于生成文本的生成器Text

js 复制代码
Blockly.Text = new Blockly.Generator('Text');

Blockly.Text.scrub_ = function(block, code) {
  var nextBlock = block.nextConnection && block.nextConnection.targetBlock();
  var nextCode = Blockly.Text.blockToCode(nextBlock);
  return code + nextCode;
};

添加积木

语法与其他语言一致

js 复制代码
Blockly.Text['hello_world'] = function(block) {
  var code = '你好,世界!';
  return '1. ' + code + '\n';
};

使用

语法与其他语言一致

js 复制代码
        <script src="./my_generators/text_generator.js"></script>
html 复制代码
            Blockly.Text.INFINITE_LOOP_TRAP = null;
            let code = Blockly.Text.workspaceToCode(workspace);   // 代码生成

示例

html 复制代码
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="./blockly/blockly_compressed.js"></script>

        <script src="./blockly/blocks_compressed.js"></script>
        <script src="./blockly/python_compressed.js"></script>

        <script src="./my_generators/text_generator.js"></script>

        <script src="./blockly/msg/js/zh-hans.js"></script>
        <script src="./blockly/demos/code/msg/zh-hans.js"></script>

        <script src="./my_blocks/my_blocks_b.js"></script>
        <script src="./my_blocks/my_blocks_g.js"></script>

        <!--代码高亮-->
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/styles/default.min.css">
        <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.7.0/build/highlight.js"></script>
        <!--行号显示-->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"></script>

        <!--Markdown 解析和编译器-->
        <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>

        <script>
            // category 栏翻译
            for (var messageKey in MSG)
            {
                if (messageKey.indexOf('cat') == 0)
                {
                    Blockly.Msg[messageKey.toUpperCase()] = MSG[messageKey];
                }
            }
        </script>

        <style>
            html, body
            {
                height: 100%;
            }

            .content
            {
                visibility: hidden;
                margin: 0;
                padding: 1ex;
                position: absolute;
                direction: ltr;
            }
        </style>
    </head>

    <body>
        <div id="blocklyDiv" style="height: 100%; width: 33%; display: inline-block; float: left;"></div>

        <xml id="toolbox" style="display: none">
            <category name="%{BKY_CATLOGIC}" colour="%{BKY_LOGIC_HUE}">
                <block type="controls_if"></block>
                <block type="logic_compare"></block>
                <block type="logic_operation"></block>
                <block type="logic_negate"></block>
                <block type="logic_boolean"></block>
                <block type="logic_null"></block>
                <block type="logic_ternary"></block>
            </category>

            <category name="%{BKY_CATLOOPS}" colour="%{BKY_LOOPS_HUE}">
                <block type="controls_repeat_ext">
                    <value name="TIMES">
                        <shadow type="math_number">
                            <field name="NUM">10</field>
                        </shadow>
                    </value>
                </block>
                <block type="controls_whileUntil"></block>
                <block type="controls_for">
                    <value name="FROM">
                        <shadow type="math_number">
                            <field name="NUM">1</field>
                        </shadow>
                    </value>
                    <value name="TO">
                        <shadow type="math_number">
                            <field name="NUM">10</field>
                        </shadow>
                    </value>
                    <value name="BY">
                        <shadow type="math_number">
                            <field name="NUM">1</field>
                        </shadow>
                    </value>
                </block>
                <block type="controls_forEach"></block>
                <block type="controls_flow_statements"></block>
            </category>

            <category name="%{BKY_CATMATH}" colour="%{BKY_MATH_HUE}">
                <block type="math_number"></block>
                <block type="math_arithmetic">
                    <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>
                <block type="math_single">
                    <value name="NUM">
                        <shadow type="math_number">
                            <field name="NUM">9</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_trig">
                    <value name="NUM">
                        <shadow type="math_number">
                            <field name="NUM">45</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_constant"></block>
                <block type="math_number_property">
                    <value name="NUMBER_TO_CHECK">
                        <shadow type="math_number">
                            <field name="NUM">0</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_round">
                    <value name="NUM">
                        <shadow type="math_number">
                            <field name="NUM">3.1</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_on_list"></block>
                <block type="math_modulo">
                    <value name="DIVIDEND">
                        <shadow type="math_number">
                            <field name="NUM">64</field>
                        </shadow>
                    </value>
                    <value name="DIVISOR">
                        <shadow type="math_number">
                            <field name="NUM">10</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_constrain">
                    <value name="VALUE">
                        <shadow type="math_number">
                            <field name="NUM">50</field>
                        </shadow>
                    </value>
                    <value name="LOW">
                        <shadow type="math_number">
                            <field name="NUM">1</field>
                        </shadow>
                    </value>
                    <value name="HIGH">
                        <shadow type="math_number">
                            <field name="NUM">100</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_random_int">
                    <value name="FROM">
                        <shadow type="math_number">
                            <field name="NUM">1</field>
                        </shadow>
                    </value>
                    <value name="TO">
                        <shadow type="math_number">
                            <field name="NUM">100</field>
                        </shadow>
                    </value>
                </block>
                <block type="math_random_float"></block>
            </category>

            <category name="%{BKY_CATTEXT}" 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="%{BKY_CATLISTS}" 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>

            <category name="%{BKY_CATCOLOUR}" colour="%{BKY_COLOUR_HUE}">
                <block type="colour_picker"></block>
                <block type="colour_random"></block>
                <block type="colour_rgb">
                    <value name="RED">
                        <shadow type="math_number">
                            <field name="NUM">100</field>
                        </shadow>
                    </value>
                    <value name="GREEN">
                        <shadow type="math_number">
                            <field name="NUM">50</field>
                        </shadow>
                    </value>
                    <value name="BLUE">
                        <shadow type="math_number">
                            <field name="NUM">0</field>
                        </shadow>
                    </value>
                </block>
                <block type="colour_blend">
                    <value name="COLOUR1">
                        <shadow type="colour_picker">
                            <field name="COLOUR">#ff0000</field>
                        </shadow>
                    </value>
                    <value name="COLOUR2">
                        <shadow type="colour_picker">
                            <field name="COLOUR">#3333ff</field>
                        </shadow>
                    </value>
                    <value name="RATIO">
                        <shadow type="math_number">
                            <field name="NUM">0.5</field>
                        </shadow>
                    </value>
                </block>
            </category>

            <sep></sep>
            <category name="%{BKY_CATVARIABLES}" colour="%{BKY_VARIABLES_HUE}" custom="VARIABLE"></category>
            <category name="%{BKY_CATFUNCTIONS}" colour="%{BKY_PROCEDURES_HUE}" custom="PROCEDURE"></category>

            <sep></sep>

            <category name="My blocks" colour="230">
                <block type="hello_world"></block>
                <block type="my_print"></block>
            </category>
        </xml>

    </body>

    <script>
        // Construct the toolbox XML, replacing translated variable names.
        // 构建 toolbox XML,替换翻译后的变量名。
        var toolboxText = document.getElementById('toolbox').outerHTML;
        toolboxText = toolboxText.replace(/(^|[^%]){(\w+)}/g,
            function(m, p1, p2) {return p1 + MSG[p2];});
        var toolboxXml = Blockly.Xml.textToDom(toolboxText);

        var workspace = Blockly.inject(
            'blocklyDiv',
            {
                toolbox: toolboxXml,

                grid:   // 栅格
                {
                    spacing: 20,
                    length: 3,
                    colour: '#ccc',
                    snap: true
                },

                move:   // 移动
                {
                    scrollbars:
                    {
                        horizontal: true,
                        vertical: true
                    },
                    drag: true,
                    wheel: false
                },

                zoom:   // 缩放
                {
                    controls: true,
                    wheel: true,
                    startScale: 1.0,
                    maxScale: 3,
                    minScale: 0.3,
                    scaleSpeed: 1.2
                },
                media: './blockly/media/',  // 图标及音效

                trashcan: true
            }
         );
    </script>

    <script>
        function show_code()
        {
            // Generate Python code and display it.
            Blockly.Python.INFINITE_LOOP_TRAP = null;
            let code = Blockly.Python.workspaceToCode(workspace);   // 代码生成
            // console.log(code);

            let display_code_obj = document.getElementById("display_code"); // 获取代码展示区对象
            display_code_obj.textContent = code;    // 更新代码展示区的内容

            // 开启代码高亮
            hljs.initHighlightingOnLoad();
            // 开启行号显示
            // hljs.initLineNumbersOnLoad ();
        }

        function show_text()
        {
            Blockly.Text.INFINITE_LOOP_TRAP = null;
            let code = Blockly.Text.workspaceToCode(workspace);   // 代码生成

            $m1.innerHTML = marked.parse(code);                   // 内容通过Markdown格式显示
        }
    </script>

    <div style="height: 100%; width: 33%; display: inline-block; float: left;">
        <button id="btn_code" style="float: left;">一键复制</button>
        <!--代码展示区-->
        <pre>
            <code class="python" id="display_code">

            </code>
        </pre>
    </div>

    <div style="height: 100%; width: 33%; display: inline-block; float: left;">
        <button id="btn_text">一键复制</button>
        <!--文本展示区-->
        <div id="$m1" class="markdown-body"></div>
    </div>

    <script>
        // 开启代码高亮
        hljs.initHighlightingOnLoad();
        workspace.addChangeListener(show_code); // 绑定 show_code 函数到 Blockly 的 change 事件来实时生成和显示代码
        workspace.addChangeListener(show_text);
    </script>

    <script type="module">
        import { convert } from 'https://cdn.jsdelivr.net/npm/html-to-text@9.0.5/+esm'  // html 转 纯文本 模块
        const options = {
            wordwrap: 130,
            // ...
        };

        const btn_code = document.getElementById('btn_code'),   // 获取 一键复制 按钮
            btn_text = document.getElementById('btn_text'),     // 获取 一键复制 按钮
            alert = document.getElementById('msg');

        let clipboard = navigator.clipboard;

        btn_code.addEventListener
        (
            'click', async () =>
            {
                let display_code_obj = document.getElementById("display_code"); // 获取代码展示区对象
                await clipboard.writeText(display_code_obj.textContent);        // 代码展示区内容赋值给剪切板
            }
        )

        btn_text.addEventListener
        (
            'click', async () =>
            {
                let text = convert($m1.innerHTML, options);     // 内容转化为纯文本
                await clipboard.writeText(text);                // 文本赋值给剪切板
            }
        )
    </script>

</html>
相关推荐
小二·12 分钟前
java基础面试题笔记(基础篇)
java·笔记·python
刚刚好ā35 分钟前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
小喵要摸鱼2 小时前
Python 神经网络项目常用语法
python
yqcoder2 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。3 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js
一念之坤3 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
天下代码客3 小时前
【vue】vue中.sync修饰符如何使用--详细代码对比
前端·javascript·vue.js
猫爪笔记3 小时前
前端:HTML (学习笔记)【1】
前端·笔记·学习·html
wxl7812273 小时前
如何使用本地大模型做数据分析
python·数据挖掘·数据分析·代码解释器
NoneCoder3 小时前
Python入门(12)--数据处理
开发语言·python