精华内容
下载资源
问答
  • BlocklyDuino 是一个基于 Web 的 Arduino 可视化编程工具。基于 Google 的 Blockly 开发。
  • 音频可视化编程工具

    2020-09-24 17:06:00
    Cycling 74 Max for Mac又称为Max 8,是一款Mac平台上的可视化编程工具,可满足从事音频,视觉媒体人士的创作需求。Max 8能够帮助大家制作编辑视频与音乐,支持 MIDI 设备和流行音频硬件,无限制音频项,包含基本的 ...

    Cycling 74 Max for Mac又称为Max 8,是一款Mac平台上的可视化编程工具,可满足从事音频,视觉媒体人士的创作需求。Max 8能够帮助大家制作编辑视频与音乐,支持 MIDI 设备和流行音频硬件,无限制音频项,包含基本的 DSP 构建块。软件支持VST、Audio Units 和 Max for Live 设备,可以与其他设备一起制作各类媒体文件。

    Max是一种视觉编程语言,可满足从事音频,视觉媒体和物理计算工作的艺术家,教育者和研究人员的特殊需求。该软件还支持多通道音频,能够实时从摄像头、数字化仪以及内置硬件输入,新版本的Cycling74 max8分析了杂乱补丁以及处理了更多可优化的内容,如大型补丁的加载速度将提高4倍,复杂的UI操作响应速度更快,当然除了这些整体改进之外,这款应用还显著增强了特定的实时用例,包括coll对象(速度提高了60倍),抖动纹理到矩阵复制,jit.world矩阵输出和更新的物理引擎等等。

    探索声音可能性的新景观

    使用MC,对象和跳线包含多个音频通道。MC将改变您对声音设计,效果处理和混合的想象。这可能是Max曾经拥有过的最能扩展思维的药物。

    MC建立在您已经与Max合作的基础上。

    只需键入mc。在任何MSP对象名称之前使用多通道跳线连接MC对象混音到任意数量的音频输出

    使用MC,具有100声道音频的音色看起来像具有单个声道的音色一样简单。以很少的对象操纵如此多的音频通道和操作的能力将打开以前隐藏的思想世界。

    您对Max的爱...

    同时编辑多个Gen实例具有可选可视化模式的多通道信号探头

    通过将MIDI和MPE分配给各个通道流来构建和弦合成器

    具有多个自动曲线的分层声音

    体验明显更快的性能

    对于Max 8,我们分析了真实的,混乱的补丁程序,以发现我们可以优化的内容。启动应用程序后,您会注意到差异。

    前所未有地建立自己的视觉效果

    Vizzie是我们用于交互式视频的80多个高级模块的集合。它已经是学习抖动的理想启动板,但现在可以开始认真使用了。

    Vizzie现在由OpenGL驱动,以显着提高性能和灵活性。通过将Vizzie模块与OpenGL Jitter功能混合使用,可以扩展到2D之外。

    与NodeJS联手

    使用NodeJS构建自定义服务器或直接从您的Max补丁程序运行小型应用程序。通过对庞大的NPM库的支持,Node for Max将您的补丁程序连接到数千种可能性中。从您的Max补丁中启动Node应用程序,然后对其进行控制并与之交互。

    支持您的创意流程的优化

    Max 8提供更流畅和优化的修补体验。除了增加响应能力之外,您还会注意到许多周到的改进。一些要点:

    一步将物体移入或移出跳线分组管理对象使用重新设计的Max控制台过滤和时间戳事件

    通过事件探测立即了解您的补丁选择颜色主题以自定义Max界面使用解锁时操作在编辑和播放之间无缝移动

     

    Max 8是一款出色的图形化音乐与视频程序编辑软件,这款软件具有100声道音频的音色看起来像具有单个声道的音色一样简单,使得大家的音乐制作变得更为高效。

    文章素材来源于网络,转载请备注软件地址:http://ll006.cn/?XBEHf9

    展开全文
  • ESP8266 可视化编程工具,界面简单易用!!!!!!!!
  • 简易可视化编程工具

    万次阅读 2017-06-02 00:46:57
    原文Dethe 是一个极客老爸,具有审美趣味的程序员,导师,以及可视化编程工具Waterbear的作者。他联合创办了温哥华手工制作教育沙龙并且满心希望机器纸折兔能火遍全球。在基于块(block-based)的编程语言中,你通过...

    Dethe 是一个极客老爸,具有审美趣味的程序员,导师,以及可视化编程工具Waterbear的作者。他联合创办了温哥华手工制作教育沙龙并且满心希望机器纸折兔能火遍全球。

    在基于块(block-based)的编程语言中,你通过拖动和连接代表程序不同部分的块来进行编程。而在一般的编程语言中,你是通过键入字符来编程的。

    学习编程可能很困难,因为一般编程语言对于拼写错误是零容忍的。大部分的编程语言都是大小写敏感的,并且语法比较晦涩,哪怕是少写一个分号都会拒绝运行程序。更有甚者,大部分的编程语言是基于英语的并且语法不能本地化。

    相反,基于块的语言可以完全消除语法错误,你的程序仅仅可能发生逻辑错误。块语言也更加直观,你可以在块列表中看到所有的程序构件和语言库。更有甚者,块可以被本地化任意的人类语言而不用改变编程语言的含义。
    The Blockcode IDE in use

    基于块的语言历史悠久,比较著名的有Lego MindstormsAlice3DStarLogo,还有Scratch。还有一些在Web上可以访问的:BlocklyAppInventorTynker以及更多

    本章的代码基于开源项目Waterbear,这不是一个语言,而是将其他现存语言包装成块语法的工具。该包装器的作用包括以上提到的几点:消除语法错误,方便本地化。除此之外,可视化的代码有时更加容易阅读和调试,还不会打字的儿童也能使用块。(可以更进一步地在块上放置图标,也可以加上文字,提供给学前儿童使用,然而这个功能我们先不考虑)。

    该语言选择使用的龟图(turtle graphics)可以追溯到Logo语言,这是一个特地教导儿童编程的语言。许多基于块的语言都包括了龟图,该主题很适合用于一个类似被严格限制的项目。

    如果想事先体验一下基于块的语言是怎么样的,可以到作者的Github进行实验。

    目标和结构

    通过本章的代码我希望能实现几点。首先,我要为龟图(turtle graphics)实现一个块语言,通过简单的拖放块,你可以编写程序创建图案,我想通过简单的HTML,CSS和JavaScript来实现。其次,我要展示如何将块构想成为一个框架,服务于其他语言而不仅仅是简单的龟语言(turtle language)。

    为了做到这点,我将turtle language相关部分全部封装到了一个文件(turtle.js),这样我就可以轻易替换成其他文件。除此之外的任何代码都不是特定于turtle language;其他的代码全部用来处理块(blocks.jsmenu.js)或者是通用的web工具(util.js,drag.js,file.js)。这是目标,然后为了使得工程尽量小型化,一些工具不是足够通用而与块相关。

    在编写一个块语言时,让我惊奇的是,语言就是它自己的IDE。你不能使用自己喜欢的编辑器;IDE的设计要和块语言同步进行。这样有利有弊。好处是所有人都使用一致的环境从而避免的关于编辑器优劣的争论。坏处是会影响构建语言。

    脚本的本质

    和任何其他语言的脚本一样,一个Blockcode脚本就是一系列的操作。对于Blockcode脚本来说,其中包含了一些HTML元素,脚本迭代执行每个HTML元素对应的JavaScript函数。一些块包含(负责执行)其他的块,还有一些块包含一些传递给函数的数值。

    在大部分(基于文本)的语言中,一个脚本的执行会经历多个阶段:一个词法分析器将文本解析为tokens,语法分析器将tokens组织成抽象语法树,然后根据语言的不同,可能会编译为机器码或者输入到解析器中。这是一个简化的描述;事实上可能会有更多步骤。对于Blockcode,块的布局本身就代表了抽象语法树,因为我们可以免去词法分析和语法分析阶段。我们使用访问者模式(Visitor pattern)来迭代每个块并执行每个块预定义的函数来运行整个程序。

    我们完全可以添加额外的步骤来将Blockcode变得更像一般的语音。除了简单的调用Javascript函数外,我们还可以将turtle.js替换为一个能产生字节码的块语言,运行于其他的虚拟机。或者产生C++代码用以编译运行。存在能够生成Java字节码的块语言(作为Waterbear项目的一部分),用于Arduino编程和为Raspberry Pi上运行的Minecraft编写脚本。

    Web应用

    为了让更多的人使用该工具,我们使用了Web。该工具使用HTML,CSS和JavaScript编写,因为可以运行在大部分的浏览器和平台。

    现代Web浏览器是一个强大的平台,提供了构建伟大软件的丰富工具。如果一些实现变得太过复杂,这就释放了一种信号,那就是我没有按照web的方式来做,如果可能我就会试着使用浏览器工具来做得更好。

    web应用和传统桌面应用或者服务器应用的一个重大的区别就是它没有main函数或者其他的入口。也没有显式地循环,因为这些已经被浏览器内置了。我们所有的代码都在加载的时候被分析和执行,在这个过程中我们可以对感兴趣的事件注册监听器用来和用户互动。在初次执行后,所有后续的互动都在相应事件中注册的回调中进行,要么是类似鼠标移动的事件,或者是设置的定时器。浏览器并没有暴露主要的线程(仅仅是共享的工作线程)。

    代码分析

    贯穿本项目始终,我都试着使用了最佳实践。每个JavaScript文件都被包含在一个函数中,从而避免变量泄露到全局环境中。如果需要暴露变量给其他文件,那么每个文件中根据文件名只定义单个global,所有需要暴露的函数都在其中。这些都在接近文件尾部进行放置,接着就是该文件定义的各种事件处理器,因而只需要看一眼文件的末尾就能知道该文件定义的事件处理器和导出的函数。

    代码是过程式的,没有采用面向对象或者函数式。我们可以使用任意一种范式来做同一件事,然而那些需要一更多的设置代码和包装代码来进行本已存在于DOM的东西。最近有个项目Custom Elements使得你可以OO的方式操作DOM,还有很多关于Functional JavaScript的文章,然而这些都需要额外的工作,因此保持过程式使得问题更简单。

    项目中有八个源文件,index.htmlblocks.css是应用的基本结构和样式因而不加讨论。还有两个JavaScript文件也不过多讨论:util.js包含了一些工具函数,file.js用于加载和保存文件并且序列化脚本。

    剩下这些文件:
    - blocks.js是块语言的抽象表示
    - drag.js实现了语言的关键交互:允许用户从可选块(菜单)中拖拽块并组装成程序(脚本)。
    - menu.js包含了一些工具代码并且负责实际地执行用户程序。
    - turtle.js定义了块语言的特定细节(turtle graphics)并且初始化特定的块。如果需要定义不同的块语言,那么就替换该文件。

    blocks.js

    每一个块由一些HTML元素组成,由CSS设置样式,由一些JavaScript时间处理器处理拖拽并且修改输入参数。blocks.js文件用于创建并管理这些元素,并且将它们组成单一的对象。当块被加入到菜单中时,绑定了一个JavaScript函数用来实现语言,因而脚本中的每个块在脚本执行的时候都要能找到其对应的函数并调用。
    An example block

    块有两种结构。一种拥有一个数值参数(具有默认值),还有一种作为其他块的容器。这些貌似很有限制,然而在一个大的系统中可以改进。在Waterbear中还有表达式块,可以作为参数进行传递;可以支持多个不同类型的值。在当前的状况下,我们试试只有一种类型的参数能干些什么。

    <!-- The HTML structure of a block -->
    <div class="block" draggable="true" data-name="Right">
        Right
        <input type="number" value="5">
        degrees
    </div>

    需要注意的是,脚本中的块和菜单中的块没有区别。只有拖拽时会判断块是从哪儿拖出来的,脚本只会运行脚本区的块,然而它们本质上是一样的结构,这就意味着从菜单中向脚本区拖动块的时候可以进行克隆。

    createBlock(name, value, contents) 函数返回一个代表块的DOM元素,并且在DOM中填充了各种内部元素,可以直接插入到document中。这可以用于向菜单区添加块,也可以用于从文件或localStorage中恢复块到脚本区。 这个函数是专为Blockcode语言编写的,如果传入的value参数有值,那么就假定这是一个数值,并且创建一个number类型的input元素。该函数被限制用于Blockcode,如果要扩展块以支持其他类型的参数,则需要更改代码。

        function createBlock(name, value, contents){
            var item = elem('div',
                {'class': 'block', draggable: true, 'data-name': name},
                [name]
            );
            if (value !== undefined && value !== null){
                item.appendChild(elem('input', {type: 'number', value: value}));
            }
            if (Array.isArray(contents)){
                item.appendChild(
                    elem('div', {'class': 'container'}, contents.map(function(block){
                    return createBlock.apply(null, block);
                })));
            }else if (typeof contents === 'string'){
                // Add units (degrees, etc.) specifier
                item.appendChild(document.createTextNode(' ' + contents));
            }
            return item;
        }

    我们有一些将块作为DOM处理的工具函数:
    - blockContents(block)返回容器块的子块。如果参数是容器块则以列表的形式返回子块,否则返回null。
    - blockValue(block) 如果块中包含一个number类型的input则返回input的值,否则返回null。
    - blockScript(block) 返回块的JSON形式,便于序列化。其后方便恢复。
    - runBlocks(blocks) 执行块数组中的所有块。

        function blockContents(block){
            var container = block.querySelector('.container');
            return container ? [].slice.call(container.children) : null;
        }
    
        function blockValue(block){
            var input = block.querySelector('input');
            return input ? Number(input.value) : null;
        }
    
        function blockUnits(block){
            if (block.children.length > 1 &&
                block.lastChild.nodeType === Node.TEXT_NODE &&
                block.lastChild.textContent){
                return block.lastChild.textContent.slice(1);
            }
        }
    
        function blockScript(block){
            var script = [block.dataset.name];
            var value = blockValue(block);
            if (value !== null){
                script.push(blockValue(block));
            }
            var contents = blockContents(block);
            var units = blockUnits(block);
            if (contents){script.push(contents.map(blockScript));}
            if (units){script.push(units);}
            return script.filter(function(notNull){ return notNull !== null; });
        }
    
        function runBlocks(blocks){
            blocks.forEach(function(block){ trigger('run', block); });
        }

    drag.js

    drag.js实现了菜单区和脚本区的交互,用于将静态的HTML块转变为动态的编程语言。用户从菜单区拖动块到脚本区来建构程序,系统执行脚本区的块。

    我们使用HTML5的拖拽功能;需要的JavaScript事件处理器在这儿定义。(关于Html5的拖拽,详情参考Eric Bidleman’s article.) 内建支持拖拽固然很棒,然而也有一些限制,例如移动端浏览器上基本不支持。

    文件开头定义了一些变量。当我们拖动时,需要在拖动的不同阶段的回调中引用它们。

        var dragTarget = null; // 正在拖动的块
        var dragType = null; // 从菜单中还是脚本中拖动?
        var scriptBlocks = []; // 脚本区中的块

    根据拖动的起始点和结束位置,drop会有不同的效果。
    * 从脚本区拖放到菜单区则删除 dragTarget (从脚本区中删除块).
    * 从脚本区拖放到脚本区则移动 dragTarget (在脚本区中移动现有块).
    * 从菜单区拖放到脚本区则复制 dragTarget (向脚本区中插入新块).
    * 从菜单拖放到菜单,不做任何事。

    dragStart(evt) 处理器中我们开始跟踪块是从菜单拖放到脚本区还是相反,或者在脚本区内移动。我们还记录下了脚本区中所有没有被拖动的块,以便后来使用。evt.dataTransfer.setData 是用来处理浏览器和其他应用程序之间的拖放,这儿没有用上,仅仅是为了绕开一个bug才使用的。

        function dragStart(evt){
            if (!matches(evt.target, '.block')) return;
            if (matches(evt.target, '.menu .block')){
                dragType = 'menu';
            }else{
                dragType = 'script';
            }
            evt.target.classList.add('dragging');
            dragTarget = evt.target;
            scriptBlocks = [].slice.call(
                document.querySelectorAll('.script .block:not(.dragging)'));
            // For dragging to take place in Firefox, we have to set this, even if
            // we don't use it
            evt.dataTransfer.setData('text/html', evt.target.outerHTML);
            if (matches(evt.target, '.menu .block')){
                evt.dataTransfer.effectAllowed = 'copy';
            }else{
                evt.dataTransfer.effectAllowed = 'move';
            }
        }

    当我们正在拖动时, 可以在dragenter, dragover, 和 dragout 事件中添加一些视觉线索,例如高亮放置区等等。其中我们只使用了 dragover

        function dragOver(evt){
            if (!matches(evt.target, '.menu, .menu *, .script, .script *, .content')) {
                return;
            }
            // Necessary. Allows us to drop.
            if (evt.preventDefault) { evt.preventDefault(); }
            if (dragType === 'menu'){
                // See the section on the DataTransfer object.
                evt.dataTransfer.dropEffect = 'copy';  
            }else{
                evt.dataTransfer.dropEffect = 'move';
            }
            return false;
        }

    当我们松开鼠标时会有一个 drop 事件,这就是见证奇迹的时刻。我们需要检查拖放的起始点,然后要么复制块,要么移动块,或者删除块。 我们使用trigger()(定义在util.js中)启动了一些自定义事件用来刷新脚本区。

        function drop(evt){
            if (!matches(evt.target, '.menu, .menu *, .script, .script *')) return;
            var dropTarget = closest(
                evt.target, '.script .container, .script .block, .menu, .script');
            var dropType = 'script';
            if (matches(dropTarget, '.menu')){ dropType = 'menu'; }
            // stops the browser from redirecting.
            if (evt.stopPropagation) { evt.stopPropagation(); }
            if (dragType === 'script' && dropType === 'menu'){
                trigger('blockRemoved', dragTarget.parentElement, dragTarget);
                dragTarget.parentElement.removeChild(dragTarget);
            }else if (dragType ==='script' && dropType === 'script'){
                if (matches(dropTarget, '.block')){
                    dropTarget.parentElement.insertBefore(
                        dragTarget, dropTarget.nextSibling);
                }else{
                    dropTarget.insertBefore(dragTarget, dropTarget.firstChildElement);
                }
                trigger('blockMoved', dropTarget, dragTarget);
            }else if (dragType === 'menu' && dropType === 'script'){
                var newNode = dragTarget.cloneNode(true);
                newNode.classList.remove('dragging');
                if (matches(dropTarget, '.block')){
                    dropTarget.parentElement.insertBefore(
                        newNode, dropTarget.nextSibling);
                }else{
                    dropTarget.insertBefore(newNode, dropTarget.firstChildElement);
                }
                trigger('blockAdded', dropTarget, newNode);
            }
        }

    dragEnd(evt) 在鼠标松开时被调用,然而是在我们处理了drop 事件之后。这儿我们可以进行一些清理,删除元素中的class,重置以便下次拖放。

        function _findAndRemoveClass(klass){
            var elem = document.querySelector('.' + klass);
            if (elem){ elem.classList.remove(klass); }
        }
    
        function dragEnd(evt){
            _findAndRemoveClass('dragging');
            _findAndRemoveClass('over');
            _findAndRemoveClass('next');
        }

    在文件menu.js 中,块被绑定了执行时需要调用的函数,也包含了实际运行脚本区块的代码。每次脚本被修改后,会自动重新运行。

    这里的菜单不是下拉式或者弹出式的,而是一个块的列表,从中你可以选择块,然后拖到脚本区。该文件就负责对菜单区进行设置,菜单区以一个提供循环功能的块(这不是turtle language的一部分)开始。

    使用一个文件收集分散的函数很有用,特别是项目还在开发的时候。保持房屋整洁的秘诀就是给杂乱的东西指定特定的地方存放,构建程序也是如此。对于归属不明确的部分,应该使用一个文件或者模块收集。当这个文件变得越来越大的时候,你就要注意了,应当将相关的函数抽取出来归并到一个单独的模块中(或者整合成一个更加通用的函数)。你不应该任由这个杂货区文件变得庞大,而仅仅将它作为一个临时放置区,直到你给其中的代码找到合理的归置之所。

    我们会较多的使用menuscript,因而保留它们的引用;没有必要每次都查找它们的DOM。我们也会用到scriptRegistry,它保存了菜单中块的脚本。我们简单的给菜单区中的块进行了命名,并进行了映射,不支持一个名字对应多个块也不支持重命名块。这种策略如果用在复杂的脚本环境中可能不够健壮。

    我们使用scriptDirty来标识脚本区是否已被修改过了,因而可以避免反复执行脚本区。

        var menu = document.querySelector('.menu');
        var script = document.querySelector('.script');
        var scriptRegistry = {};
        var scriptDirty = false;

    当我们想通知系统在下一个frame处理器中运行脚本,调用runSoon()scriptDirty设置为true。系统在每一个frame中调用run(),除非scriptDirty被设置,否则立即返回。当scriptDirty被设置为true时,运行脚本区中所有的块,并且触发事件使得特定的语言处理相关任务。这样做将块和turtle language进行了解耦,使得块可以被重用(或者也可以说语言可插拔)。

    在执行脚本的时候,我们遍历每个块,调用它的runEach(evt),该方法会在块上添加一个class(用于CSS),然后找到并调用与块绑定的函数。如果我们减慢执行速度,你将看到每个块在执行时会被高亮。

    下面的requestAnimationFrame 是浏览器提供的用作动画的函数。它接受一个函数作为参数,然后在渲染下一帧(每秒60帧)的时候使用。具体得到多少帧取决于我们能多块的处理任务。

        function runSoon(){ scriptDirty = true; }
    
        function run(){
            if (scriptDirty){
                scriptDirty = false;
                Block.trigger('beforeRun', script);
                var blocks = [].slice.call(
                    document.querySelectorAll('.script > .block'));
                Block.run(blocks);
                Block.trigger('afterRun', script);
            }else{
                Block.trigger('everyFrame', script);
            }
            requestAnimationFrame(run);
        }
        requestAnimationFrame(run);
    
        function runEach(evt){
            var elem = evt.target;
            if (!matches(elem, '.script .block')) return;
            if (elem.dataset.name === 'Define block') return;
            elem.classList.add('running');
            scriptRegistry[elem.dataset.name](elem);
            elem.classList.remove('running');
        }

    我们使用menuItem(name, fn, value, contents)向菜单中添加块,该函数接受一个普通块,然后给它绑定一个函数,并加入到菜单栏。

        function menuItem(name, fn, value, units){
            var item = Block.create(name, value, units);
            scriptRegistry[name] = fn;
            menu.appendChild(item);
            return item;
        }

    我们在此处定义repeat(block),而不是在turtle language中,因为我们希望这个函数可以在不同的语言中通用。如果我们有了if块和读写变量,这些也应该放到这里,或者是一个单独的语言转换(trans-language)模块,然而此时我们只有这一个通用的块。

        function repeat(block){
            var count = Block.value(block);
            var children = Block.contents(block);
            for (var i = 0; i < count; i++){
                Block.run(children);
            }
        }
        menuItem('Repeat', repeat, 10, []);

    turtle.js

    turtle.js是turtle块语言的实现部分。它不被其他任何代码依赖。因而这一部分可以很轻易的替换。
    这里写图片描述

    Turtle programming是图形编程的一种,由于Logo语言被大众所熟悉,简单的说就是一个携带着一只笔的龟头在屏幕上移动。你可以命令龟头收起笔(不再画线,继续移动),放下笔(移动到哪儿,笔画到哪儿),移动指定数量步,或者转向多少度。仅仅依靠这些命令和循环,就可以画出令人静态的图案。

    在这个turtle graphics版本中,我们有一些额外的块。技术上讲,我们并不需要turn rightturn left同时存在,因为拥有其中一个,那么另外一个可以使用负数完成。类似的move back也可以使用move forward加上负数解决。

    上面的图案脚本,将两个循环放入另一个循环之中,然后给每个循环添加一个move forwardturn right,然后调整参数,直到得到满意的图案。

        var PIXEL_RATIO = window.devicePixelRatio || 1;
        var canvasPlaceholder = document.querySelector('.canvas-placeholder');
        var canvas = document.querySelector('.canvas');
        var script = document.querySelector('.script');
        var ctx = canvas.getContext('2d');
        var cos = Math.cos, sin = Math.sin, sqrt = Math.sqrt, PI = Math.PI;
        var DEGREE = PI / 180;
        var WIDTH, HEIGHT, position, direction, visible, pen, color;

    reset()函数将所有的状态变量恢复到默认状态。如果我们需要支持多个龟头,可以将这些变量封装到一个对象中。deg2rad(deg)函数用于将度转化为弧度,因为作图使用的是弧度。drawTurtle()用于画龟头自身,默认是一个简单的三角形。当然你可以自定义成更加华丽的龟头。

    注意drawTurtle函数使用了我们在turtle drawing中定义的一些基本操作。有时你不想在不同的抽象层之间重用代码,然而如果定义明确,这对于代码大小和性能是至关重要的。

        function reset(){
            recenter();
            direction = deg2rad(90); // facing "up"
            visible = true;
            pen = true; // when pen is true we draw, otherwise we move without drawing
            color = 'black';
        }
    
        function deg2rad(degrees){ return DEGREE * degrees; }
    
        function drawTurtle(){
            var userPen = pen; // save pen state
            if (visible){
                penUp(); _moveForward(5); penDown();
                _turn(-150); _moveForward(12);
                _turn(-120); _moveForward(12);
                _turn(-120); _moveForward(12);
                _turn(30);
                penUp(); _moveForward(-5);
                if (userPen){
                    penDown(); // restore pen state
                }
            }
        }

    我们有个专门的块用于画一个特定半径的圆。即使你可以使用move 1 right 1然后循环360次来画圆,毕竟这太麻烦了。

        function drawCircle(radius){
            // Math for this is from http://www.mathopenref.com/polygonradius.html
            var userPen = pen; // save pen state
            if (visible){
                penUp(); _moveForward(-radius); penDown();
                _turn(-90);
                var steps = Math.min(Math.max(6, Math.floor(radius / 2)), 360);
                var theta = 360 / steps;
                var side = radius * 2 * Math.sin(Math.PI / steps);
                _moveForward(side / 2);
                for (var i = 1; i < steps; i++){
                    _turn(theta); _moveForward(side);
                }
                _turn(theta); _moveForward(side / 2);
                _turn(90);
                penUp(); _moveForward(radius); penDown();
                if (userPen){
                    penDown(); // restore pen state
                }
            }
        }

    我们主要的基本函数是moveForward,处理了一些三角函数的运算工作,并且判断笔是否收起或放下。

        function _moveForward(distance){
            var start = position;
            position = {
                x: cos(direction) * distance * PIXEL_RATIO + start.x,
                y: -sin(direction) * distance * PIXEL_RATIO + start.y
            };
            if (pen){
                ctx.lineStyle = color;
                ctx.beginPath();
                ctx.moveTo(start.x, start.y);
                ctx.lineTo(position.x, position.y);
                ctx.stroke();
            }
        }

    剩下大部分的龟头命名都可以使用上面定义的函数来轻松的实现

        function penUp(){ pen = false; }
        function penDown(){ pen = true; }
        function hideTurtle(){ visible = false; }
        function showTurtle(){ visible = true; }
        function forward(block){ _moveForward(Block.value(block)); }
        function back(block){ _moveForward(-Block.value(block)); }
        function circle(block){ drawCircle(Block.value(block)); }
        function _turn(degrees){ direction += deg2rad(degrees); }
        function left(block){ _turn(Block.value(block)); }
        function right(block){ _turn(-Block.value(block)); }
        function recenter(){ position = {x: WIDTH/2, y: HEIGHT/2}; }

    当我们需要刷新状态,clear函数可以恢复初始状态。

        function clear(){
            ctx.save();
            ctx.fillStyle = 'white';
            ctx.fillRect(0,0,WIDTH,HEIGHT);
            ctx.restore();
            reset();
            ctx.moveTo(position.x, position.y);
        }

    当脚本初次加载时,我们使用resetclear来初始化并画出龟头。

        onResize();
        clear();
        drawTurtle();

    现在可以在menu.js文件中通过Menu.item函数使用上面定义的函数,从而构建用户可以使用的块。

        Menu.item('Left', left, 5, 'degrees');
        Menu.item('Right', right, 5, 'degrees');
        Menu.item('Forward', forward, 10, 'steps');
        Menu.item('Back', back, 10, 'steps');
        Menu.item('Circle', circle, 20, 'radius');
        Menu.item('Pen up', penUp);
        Menu.item('Pen down', penDown);
        Menu.item('Back to center', recenter);
        Menu.item('Hide turtle', hideTurtle);
        Menu.item('Show turtle', showTurtle);

    总结

    为何不使用MVC?

    Model-View-Controller (MVC) 对于80年代的Smalltalk程序来说是一个好的设计选择,现在也可以用于一些Web应用,然而它不是对于所有问题都是好的选择。块语言中所有的状态(MVC中的“M”)都被块对象所持有,因而将该模式复制到Javascript中实无必要,除非对于model有其他的需求(例如编辑共享的,分布式的代码)。

    在Waterbear的早期版本中,我曾通过在JavaScript中维持model然后将之同步到DOM中,后来我发现有一半的代码和90%的bug都出于这里。消除了这种重复之后,代码变得更加简单和健壮,所有的状态都被DOM元素所持有后,使用开发者工具可以轻松查出很多bug。因此在HTML/CSS/JavaScript的基础上增加MVC的额外分层没有什么帮助。

    细微更改引发大变更

    构建一个我所从事的大型系统的小型而紧凑的版本是一个有趣的练习。在构建大型系统时,你对于改变总是很迟疑,因为这会影响到很多方面。然后在一个小型版本中,你可以尽情试验然后将所学到的东西应用到大型系统。对于我来说,大型系统就是Waterbear,而这个功能对于Waterbear的构建很有建设意义。

    小实验使得失败不再可怕

    在这个微型的块语言中,我进行了下面的试验:

    • 使用HTML5的拖拽
    • 通过直接遍历DOM并调用绑定函数的方式来运行块
    • 将实际运行的代码从HTML DOM中分离
    • 简化了拖动时的碰撞检测
    • 构建了我的微型向量(vector)和精灵(sprite)库(用于游戏块)
    • 改变脚本时实时显示结果

    试验不一定需要成功。我们总是倾向于将失败看得很严重,而不是将它视为通向成功的路径。虽然我搞定了HTML5的拖拽,然后由于在手机浏览器上不支持,所以在Waterbear中没有采用。分离代码并且通过迭代块来执行工作良好,因此我已经着手将它引入Waterbear了。

    我们真正需要构建什么

    构建一个大型系统的小型版本可以使得我们更加专注于最重要的部分。使得我们思考,有哪些功能是历史遗留而不再需要维护。总之,可以帮助大型系统进行重构。

    构建程序之路还很漫长

    在该项目中,我还有一些东西没有试验。比如添加一个能添加函数的块。实现撤销和重做功能。使块能接受多个参数。通过网络分享脚本。

    展开全文
  • liveSytle liveReload Broswer-Sync 三种可视化编程工具。 转载于:https://www.cnblogs.com/tuoxiong/p/6213500.html

    liveSytle

    liveReload

    Broswer-Sync

    三种可视化编程工具。

    转载于:https://www.cnblogs.com/tuoxiong/p/6213500.html

    展开全文
  • 无论选择My eclipse还是eclipse,在编写jsp网页的时候我们都可以使用平台自带的可视化编程工具(即拖拉组件),两个平台的工具会有些稍微的差异,但外观和效果都是大同小异。 下面我将简单介绍如何启动这些可视化...

        无论选择My eclipse还是eclipse,在编写jsp网页的时候我们都可以使用平台自带的可视化编程工具(即拖拉组件),两个平台的工具会有些稍微的差异,但外观和效果都是大同小异。

    下面我将简单介绍如何启动这些可视化编程工具。

    1、eclipse下的web page editors

    (1)一般编写JSP采用的是 (Eclipse ide for enterprise java developers)

    2、首先创建jsp文件,选择其他,找到web ->Dynamic Web Project

    3、接下来是正常的操作,输入项目的名字,选择服务器(我安装的是tomact),这些都是一般的操作,大家做完之后点击下一步即可。

     4、选中jsp文件,选择打开方式(open with),右键web page editors,即可,选择底部的“design”,上面我画横线的是不同的设计界面布局,而单击右面箭头,就可以启动拖拉组件的palette,可以直接拖拉选择

    2、My eclipse下的jsp可视化编程工具--visual  JSP designers

    上面创建项目的过程,我就不展示了,my eclipse的创建jsp文件要比eclipse创建的要方便的多,按照提示来创建即可。

     (2)接下来选择jsp文件,右键open with→MyEclipse Visual Designer即可,接下来的界面和eclipse界面相同。接下来就可以可视化编程了!

    展开全文
  • Wire是包含一组库(工件)的monorepo,可以非常轻松地为网络构建出色的快速,React灵敏的可视化编程工具。 它提供了一个核心数据处理框架和一个带有React组件的库,可以帮助您入门。 查看基础工件,以了解有关Wire...
  • 分享一个自己写的可视化编程工具

    千次阅读 2019-09-29 17:57:48
    分享一个自己参考UE4蓝图写的可视化编程工具,xVP: 下载地址:链接: https://pan.baidu.com/s/18tcynzp7TbpP6wvMT9XyIA 提取码: qkue
  • 可视化的汇编语言,集成的开发环境,简单易用!需要就来
  • 我们昨天发布了Unity 2018.1 beta 版本发布的信息,并且介绍了在这个版本...其中为配合SRP而设计的着色器可视化编程工具Shader Graph,帮助开发者、美术人员等进行可视化的着色器构建。不必手工编写代码,只要在一个
  • Blockly 是一个基于 Web 的可视化编程工具, Google 旗下的一个开源项目. 用户不需要敲代码, 可以通过拼装积木的方式构建应用程序. 目前支持生成 JavaScript, Dart 和 Python 代码. 我也跟风搭建了一个: Blocky 图形...
  • wxglade是一个用python实现的wxwidgets的界面设计工具,它是完全免费和开放源代码的,它可以产生包括python,C ,perl,XRC在内的各种输出文件,它的大本营在http://wxglade.sourceforge.net.你可以用它产生所有界面相关的...
  • Delphi7可视化编程工具迷你版(别名Delphi7编译器)比VB强大比VC简单,功能上来说比VB要强大,特别是底层内存指针方面的操作。而使用和学习的简单性来说比VC要简单!功能不输VC。这就是Delphi7的强大。传奇和CE工具都...
  • Blockly - 来自Google的可视化编程工具     Google Blockly 是一款基于Web的、开源的、可视化程序编辑器。你可以通过拖拽块的形式快速构建程序,而这些所拖拽的每个块就是组成程序的基本单元。可视化编程完成...
  • 无需写代码就能在unity3d中进行游戏开发和制作,通过流程框图进行编程开发,为美工人员提供开发游戏的机会。
  • Basic4Android是Android平台上一个简单而又强大的可视化快速安卓应用开发工具,它可被用来开发和测试数据库通信,甚至可以被用来开发2D的即时游戏。Basic4Android兼容了Google的AdMob数据库,所以开发者可以在他们...
  • 原文Dethe 是一个极客老爸,具有审美趣味的程序员,导师,以及可视化编程工具Waterbear的作者。他联合创办了温哥华手工制作教育沙龙并且满心希望机器纸折兔能火遍全球。在基于块(block-based)的编程语言中,你通过...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,903
精华内容 1,161
关键字:

可视化编程工具