Scratch3.0 二次开发——支持隐藏积木选择区域
概述
这次核心介绍如何修改 scratch-blocks 库 使其支持隐藏积木选择区域的功能
需求分析
如上图,官方 scratch 积木选择区域(flyout)是没办法伸缩或者隐藏的,这样,如果我们把整个 PC 界面移植到平板上的话,屏幕相对较小的情况下,积木编辑区域就显得很小。故,原始需求:积木选择区域(flyout)实现隐藏/显示功能,从而拓展积木编辑区域的大小。
另外,对于常规情况下,积木选择区域(flyout)默认显示会比较方便一点,只有当有需要隐藏时再通过某个按钮触发隐藏。
还有,要控制好可删除区域,如下图:
前置准备
项目构建环境依赖
启动本地服务
scratch-blocks 库中自带有测试用的页面。最好先安装 http-server,相对方便在本地启动一个 http 服务器。安装好后,在 scratch-blocks
项目的根目录下执行 http-server
就可以启动一个本地服务,直接访问 http://127.0.0.1:8080/tests/vertical_playground.html
就可以访问测试页面,如下图:
npm link
改好代码后,在 scratch-blocks
项目的根目录下执行 npm link
命令,然后在 demo-scratch-gui 项目根目录下执行npm link scratch-blocks
命令就可以将 demo-scratch-gui 中安装的远程 scratch-blocks 库,换成是本地的。
详细可以自行百度一下 npm link 的用法 O(∩_∩)O哈哈~
实现细节
思路
flyout 的 隐藏/显示
功能,最直接的就是去到 scratch-blocks 项目的源码文件中找线索,看有没有现成的接口:
- flyout_base.js
- flyout 的基础类,其它类型的 flyout 都是继承自这个类
- flyout_vertical.js
- 垂直布局 flyout 的类,scratch 有垂直和水平布局两种积木编辑方式(用得比较多是垂直,后续也只在垂直布局的基础上修改。对于水平布局,有需要的朋友可以摸索摸索一下)
- 垂直布局:
- 水平布局:
- 垂直布局:
- 垂直布局 flyout 的类,scratch 有垂直和水平布局两种积木编辑方式(用得比较多是垂直,后续也只在垂直布局的基础上修改。对于水平布局,有需要的朋友可以摸索摸索一下)
有一说一,虽然官方 scratch 几乎是 0 文档,但系统里面的接口还是有预留了挺多的,有事没事多刷刷源码,需要用到时可能会有“灵光一闪”的微妙感觉~
flyout_base.js - hide 函数,可以满足我们这次需求。但是呢,不能直接上,实现过程还是有点坑,等在下娓娓道来~
坑
一开始非常天真的以为发现了好东西——flyout_base.js - autoClose 属性。这个属性,默认值是 false
,如果设置成 true
,则在把积木从 flyout 区域拖到编辑区域时,flyout 会自动隐藏起来。
打算搭配 flyout_base.js - hide 函数 和 flyout_base.js - autoClose 属性实现这次需求,但最终做出来后会出现以下几点坑:
- scratch-blocks 项目报错,初步判断,下面错误是指在加载时少了一些数组元素,导致没法正确读取内容
- 基本可以定位到是因为使用了 autoClose 属性后,隐藏了 flyout 导致的问题
- 角色、背景两种类型的 target 切换时,flyout 没有正确显示。本来下图这种类型的积木只会在处于背景 target 时才会出现,当切换成角色 target 时就会换成运动类型的积木。结果使用了这套方案后,没法正确切换。
- flyout 中,可勾选类型的积木没法勾选
个人感觉,应该是 autoClose 属性在源码里面有坑还没解决,导致了一串连环 bug,最终放弃了这套方案,改成了下一小节中的方案
源代码
上文提到,autoClose 属性 有坑,但 hide 函数 是没问题的。接下来我们会基于 hide 函数展开
修改总览
文中没有贴完所有源码,有需要的朋友麻烦上 scratch-blocks github 库 自取,有很多关键性的注释也附在源码上面,记得看看中文类型的注释(英文的注释是官方的,中文的注释都是我自己加上去的)
实现这次需求修改的地方如下:
在 scratch-blocks 的 core/toolbox.js 文件中:
// 相关变量:
this.isHideFlyout_ = false;
this.triggerIcon_ = null;
// 相关函数;
init
createTrigger
unfoldTrigger
foldTrigger
getIsHideFlyout
setIsHideFlyout
triggerIsHideFlyout
populate_
getClientRect
setSelectedItem
setSelectedItemForPopulate
在 scratch-blocks 的 core/css.js 文件中,新增了 .blocklyToolboxTrigger
、.blocklyToolboxTriggerIcon
两个样式 class,用来处理触发按钮
另外还在 scratch-blocks 的 media 目录 下增加了两份资源文件:hide.svg、show.svg
创建隐藏/显示触发器
上文总览中提及到的:
this.isHideFlyout_ = false;
this.triggerIcon_ = null;
createTrigger
unfoldTrigger
foldTrigger
getIsHideFlyout
setIsHideFlyout
triggerIsHideFlyout
这些变量和函数都是用来创建并保存隐藏/显示触发器用的
初始化
上文总览中提及到的:init
函数,是在 scratch-blocks 的 core/toolbox.js 中对隐藏/显示触发器进行初始化,包括以下内容:
- 创建并保存对象(调用“创建隐藏/显示触发器”中的函数)
- 创建点击事件
边边角角
上文总览中提及到的:
populate_
getClientRect
setSelectedItem
setSelectedItemForPopulate
这几个函数都是用来处理边界情况,虽然是边边角角的情况,但对于整个实现来说至关重要,最好还是看看源码里面的中文注释 O(∩_∩)O哈哈~
至此,就完成了这一次的需求实现 ✿✿ヽ(°▽°)ノ✿
转载自:https://juejin.cn/post/7129289569886961677