likes
comments
collection
share

Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能

作者站长头像
站长
· 阅读数 30

概述

Scratch3.0 二次开发系列,系列说明、Demo源码等请查看:《Scratch3.0 二次开发——开篇》

这次核心介绍如何修改 scratch-blocksscratch-vmscratch-gui 三个库,增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能。

最终效果如图:

  • 完全锁定
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • 某积木(或积木组)开启“完全锁定”后,不能移动、不能修改里面的内容、不能改变原本的积木拼接、不能新增拼接
    • 某些积木希望给学生看到,但又不想让学生修改(改后会影响到程序的运行),此时就使用“完全锁定”功能
  • 隐藏积木
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • 继承“完全锁定”的所有特性,额外增加一个隐藏功能(如果该积木处于隐藏状态,且当前用于没有查看权限,则该积木不会显示在积木编辑区)
  • 禁止删除
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • 某积木(或积木组)开启“禁止删除”后,该积木无法被删除
  • 角色一键隐藏
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • 一键使某个角色内的所有积木启动“隐藏积木”功能

需求分析

在教学场景中,老师用于授课和给学生练习的作品里面的积木逻辑可能会很复杂,包含很多角色、很多积木的拼接才能呈现出最终的效果。如此多的内容对于学生来说是一个很大的干扰(也许当前课程只学一个比较简单的知识点),因此产生了这篇文章中业务的原始需求——希望隐藏一些暂时不想给学生看到的积木或角色。

基于上述原始需求,延伸出上一节“概述”中的四大功能:完全锁定、隐藏积木、禁止删除、角色一键隐藏

前置准备

接下来的修改会涉及到scratch-blocksscratch-vmscratch-gui 三个库

scratch-blocks 项目的前置准备请参考这篇:Scratch3.0 二次开发——支持隐藏积木选择区域

另外两个库的环境准备请参考这篇:Scratch3.0 二次开发——开篇

思路 && 实现细节

这次内容比较多,具体思路和实现细节就放在一起写了。

还是老规矩,文中没有贴完所有源码,有需要的朋友麻烦上 scratch-blocksscratch-vmscratch-gui 自取,有很多关键性的注释也附在源码上面,记得看看中文类型的注释(英文的注释是官方的,中文的注释都是我自己加上去的)。下文只贴一些变量、函数名,作为源代码中的“目录”,起到总览的作用,后续看源码的时候不至于迷路 (づ ̄3 ̄)づ╭❤~

权限控制

上一节“概述”中提到,积木开启“隐藏积木”功能后或者角色开启“角色一键隐藏”功能后,对于没有权限的用户是开不到对应的积木和角色的,因此我们需要先弄一个简单的权限管理(目前只用到学生、老师两种角色,后续有需要的话可以基于这套权限控制进行扩展角色和权限内容)

scratch-blocks 项目

  1. 新增 authority.js,定义编辑区域权限值
  2. 新增 role.js,定义编辑区域角色以及角色对应的权限值
  3. blockly.js 中添加 role 属性和 setRole 函数
    • role 属性,用于记录当前用户是什么角色
    • setRole 函数,用于修改当前用户的角色

scratch-gui 项目

  1. src/models/global.js,中有 role 属性,用于记录当前用户的角色
    • 这个属性也会传递到 scratch-blocks 项目中,同步进行修改
    • PS:这里以及后续都会使用 dva 来做数据管理,详细的配置可以参考:Scratch3.0 二次开发——引入 dva
  2. src/containers/gui.jsx,新增 setRole 函数,并且在 componentDidMount 中调用
    • 目前在 url 上通过添加 ?role=teacher 参数,可以直接设置当前用户的角色
  3. src/containers/blocks.jsx
    • shouldComponentUpdate 函数中,增加 this.props.role !== nextProps.role,监听 src/models/global.jsrole 的变化
    • componentDidUpdate 函数中,如果 src/models/global.jsrole 的发生了变化,则传递到 scratch-blocks 项目中,同步修改当前用户角色—— this.ScratchBlocks.setRole(this.props.role);
  4. 新增 src/lib/authority.js,定义权限值
  5. 新增 src/lib/role.js,定义角色拥有的权限值、校验是否拥有特定权限

“禁止删除”的逻辑实现

scratch-blocks 项目

  1. 新增 core/prevent_deletion.js,用来在积木上显示“禁止删除”的标识
  2. core/block.js 中:
    • 增加 menuSetDeletable 函数,后续调用,实现禁止删除的功能
    • 增加 this.preventDeletion 属性,用于存放 PreventDeletion 的实例化对象(禁止删除 icon)

“完全锁定”的逻辑实现

scratch-blocks 项目

  1. 新增 core/locking.js,用来在积木上显示“完全锁定”的标识
    • 显示“禁止删除”的标识如下图:(这里是直接画 svg,不用引入额外的资源文件)
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
  2. core/block.js 中:(详解请看代码注释)
    • 增加 this.locking 属性
    • 增加 isLockingsetLockingmenuSetLockingsetBlocksEditable 函数
  3. core/connection.js 中:(详解请看代码注释)
    • isConnectionAllowed 函数中,添加处于锁定状态或者隐藏状态,不能链接其它积木的条件判断

“隐藏积木”的逻辑实现

scratch-blocks 项目

  1. 新增 core/invisible.js,用来在积木上显示“隐藏积木”的标识
    • 附带要新增 media/invisible.svg 资源文件
    • 显示“隐藏积木”的标识如下图:
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
  2. core/block.js 中:(详解请看代码注释)
    • 增加 this.invisible 属性
    • 增加 isInvisiblesetInvisiblemenuSetInvisible 函数
  3. core/connection.js 中:(详解请看代码注释)(同上述“完全锁定”中的代码,两个写在一起了)
    • isConnectionAllowed 函数中,添加处于锁定状态或者隐藏状态,不能链接其它积木的条件判断

添加积木右键菜单

scratch-blocks 项目

  1. msg/scratch_msgs.js 中:
    • 增加新增右键菜单的多语言版本文案(目前只加了英文、简体中文、繁体中文三种,其它语言有需要的可以自行添加)
  2. core/contextmenu.js 中:(详解请看代码注释)
    • 新增 blockDeletableOptionblockLockingOptionblockInvisibleOption 三个函数,用来注册新增的右键菜单按钮
  3. core/block_svg.js 中:(详解请看代码注释)
    • showContextMenu_ 函数中根据角色权限以及功能之间的逻辑关系,修改积木右键菜单按钮

状态初始化

所谓“状态初始化”,是指当设置了积木为“完全锁定”、“隐藏积木”、“禁止删除”时,要把这些状态保存到作品文件中,使其重新打开作品时还能保留当前设置的这些状态。这部分修改会涉及到 scratch-blocksscratch-vm 两个库。

scratch-blocks 项目

  1. core/xml.js 中:(详解请看代码注释)
    • blockToDom 函数中,添加“完全锁定”、“隐藏积木”两种状态的标识
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • domToBlockHeadless_ 函数中,根据 dom 的 attr 属性,调用相关状态逻辑,设置状态
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • 以上两步,分别是用于将“完全锁定”、“隐藏积木”、“禁止删除”状态保存到 DOM 中,以及从 DOM 中解析出当前积木的这三种状态

scratch-vm 项目

  1. src/engine/blocks.js 中:(详解请看代码注释)
    • changeBlock 函数中,添加对“完全锁定”、“隐藏积木”、“禁止删除”三种状态的处理
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
      • 这个函数应该是在 scratch-vm 项目中对于 scratch-blocks 项目中的 Blockly.Events.BlockChange 事件的监听
        • 上图 deletablelockinginvisible 实际上就是对应 scratch-blocks - core/contextmenu.jsblockDeletableOptionblockLockingOptionblockInvisibleOption 中定义的 Blockly.Events.BlockChange 事件中的 deletable
          • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
          • PS:blockLockingOptionblockInvisibleOption 函数中的 Blockly.Events.BlockChange 事件分别在其里面调用的 block.menuSetLockingblock.menuSetInvisible
      • 另外,scratch-blocks 项目和 scratch-vm 项目两个项目各自有维护自身需要的 block,这个 changeBlock 起到了将 scratch-blocks 项目的这三种状态同步给 scratch-vm 中的 block 的作用
    • blockToXML 函数中,将状态同步到 xml 的 attr属性上
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
      • PS:deletablelockinginvisible 的值有可能是 undefined,后续判断时要注意一下
  2. src/serialization/sb3.js 中:(详解请看代码注释)
    • serializeBlock 函数中,将作品文件中的值解析到 scratch-vm 的 block 对象中
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能

隐藏角色

scratch-vm 项目

  1. src/sprites/rendered-target.js 中:(详解请看代码注释)
    • 添加 this.isInvisible 属性,控制当前目标是否需要隐藏(教师角色操作隐藏角色的功能,该功能会将角色在角色列表中隐藏掉,并且该角色中的积木都添加隐藏状态);同时新增 setIsInvisible 函数用于修改该属性
    • 修改 toJSON 函数,把 this.isInvisible 属性也保存到导出的 JSON 中
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
  2. src/virtual-machine.js 中:(详解请看代码注释)
    • 新增 invisibleSprite 函数
    • 修改 installTargets 函数
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
  3. src/serialization/sb3.js 中:(详解请看代码注释)
    • 修改 serializeTargetparseScratchObject 函数,分别添加 isInvisible 属性,用来导出作品文件以及作品文件时,可以读到该数据
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
      • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能

scratch-gui 项目

  1. 在角色渲染列表,添加按钮
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
    • PS: 因为加了权限控制,跑 scratch-gui 项目后,要访问 http://localhost:8601/?role=teacher 才能看到以上按钮(通过在 url 上传 ?role=teacher 参数,识别角色)(详细可见上文 “权限控制” 小节)
    • 为了加这么一个小小的按钮,从 src/containers/target-pane.jsx 文件开始,一路改了好几个文件(官方封装了很多层,一路往下找就 ok)
      • src/containers/target-pane.jsx 中,新增了 handleInvisibleSprite 函数,用于修改角色的能否可见的状态,然后就一路往下传了
        • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能
        • Scratch3.0 二次开发——增加积木的完全锁定、隐藏积木、禁止删除功能,增加角色一键隐藏功能

至此,就完成了这一次的需求实现 ✿✿ヽ(°▽°)ノ✿