Scratch3.0 二次开发——舞台区域支持多尺寸模式
概述
Scratch3.0 二次开发系列,系列说明、Demo源码等请查看:《Scratch3.0 二次开发——开篇》
这次核心介绍如何实现舞台区域支持多尺寸模式的效果
最终效果如图:
需求分析
官方 Scratch 的舞台仅支持一种舞台尺寸(480*360
,4:3
的尺寸),如果想做一些竖屏的游戏就有点麻烦。所以,原始需求是希望舞台除了支持 4:3
的尺寸外,还需要支持 16:9
以及竖屏(大概是 3:5
的比例,具体比例可以根据各自的需要进行调整)。
ok,原始需求确定了,但对于心思缜密的程序员来说,确定原始需求只是第一步。除了原始需求之外,我们还要挖掘基于这个原始需求的边界情况:
- 舞台尺寸切换后,要把当前尺寸记录到工程文件(
.sb3 文件中的 json 文件
)中,并且再次打开工程文件时能读取到其值,而且自动将舞台尺寸切换到读取到的值- 比如,舞台尺寸默认是
4:3
,我们现在改成16:9
,并且保存当前作品。那么当我们再次打开这份作品的时候,肯定希望舞台尺寸是修改后的16:9
。嗯嗯,没毛病( ̄▽ ̄)~*
- 对应下文 “保存当前尺寸信息” 一节
- 比如,舞台尺寸默认是
- 当舞台尺寸切换后,原本在舞台上显示的内容不能乱,比如:
- 说话气泡
- 询问交互
- 取色交互
- 变量和列表
- 内容在下文 “原始需求,先实现多尺寸模式” 一节中
- 说话气泡
- 当舞台尺寸切换后,背景编辑区域的尺寸也要跟着变化,比如:
- 竖屏的尺寸
4:3
的尺寸
16:9
的尺寸
- 对应下文 “背景编辑区域跟随当前尺寸” 一节
- 当舞台尺寸切换后,背景要适配对应尺寸,比如:
- 竖屏的尺寸
4:3
的尺寸
16:9
的尺寸
- 三种尺寸下,背景都能全屏填充不留白
- 对应下文 “背景图片适配当前尺寸” 一节
ok,基本上边界情况也理清楚了,接下来干就完了

前置准备
接下来的修改会涉及到demo-scratch-render、demo-scratch-svg-renderer、demo-scratch-vm、demo-scratch-gui、demo-scratch-paint 五个库
详细的准备工作,请参考这篇:Scratch3.0 二次开发——开篇
思路 && 实现细节
这次内容比较多,具体思路和实现细节就放在一起写了。
原始需求,先实现多尺寸模式
如上图,右侧红框里面的内容就是整个舞台区域,里面分成两部分:
stage
,相当于一个容器,用来框定舞台区域的宽高canvas
,相当于画布,是真正渲染的区域
这样一来我们就好办了,把 stage
的宽高固定起来,需要修改尺寸的仅有 canvas
部分,看一下下图 dom 结构的内容就更加清晰了:
ok,接下里的内容就是围绕如何实现上述思路了。
demo-scratch-gui 项目
修改到的内容比较多,具体修改的内容对比可以参考这个:commit,建议直接 clone 项目下来查看:demo-scratch-gui
上图红框中的文件都跟这一 part 有关
挑一下相对比较重要的地方讲解一下,详情请查看源码:
- src/components/stage/stage.jsx,这个组件以及对应的 css 文件调整幅度比较大,把 DOM 结构调整了一下,核心实现上述的两点需求:
- 区分上面提到的
stage
和canvas
- 区分上面提到的
- src/containers/stage-header.jsx、src/components/stage-header/stage-header.jsx,用来增加多尺寸切换的按钮交互以及逻辑
- src/containers/stage.jsx,PS:基本上多尺寸切换的核心逻辑都在这里,其中最关键的是
resizeCanvas
和onStageNativeSizeChange
两个函数resizeCanvas
函数的作用是调节上述canvas
的 css 尺寸,使其与选择的尺寸等比例onStageNativeSizeChange
函数的作用是响应舞台尺寸改变时需要同步处理的操作
保存当前尺寸信息
看着这个需求好像很多的样子,实际上只需要在保存作品时记录当前的尺寸信息,打开作品读取并设置就 ok
demo-scratch-vm 项目
一共修改了以下文件:(红框中的文件)
其中:
- src/engine/runtime.js,在运行时中记录当前舞台的尺寸信息,供其它地方使用
- 增加静态变量:
stageNativeSize
- 修改或增加 getter/setter 方法:
STAGE_WIDTH
、STAGE_HEIGHT
、STAGE_WIDTH
、STAGE_HEIGHT
、OFFICIAL_STAGE_WIDTH
、OFFICIAL_STAGE_HEIGHT
- 增加静态变量:
- src/serialization/sb3.js,用来存储或解析作品文件(工程文件,.sb3 文件中的 json 文件)中的舞台尺寸信息
serializeTarget
函数中的 stageNativeSize 相关内容,用来将舞台尺寸信息保存到作品文件中parseScratchObject
函数中的 stageNativeSize 相关内容,用来解析作品文件中的舞台尺寸信息
- src/sprites/rendered-target.js,中
toJSON
函数,导出当前舞台的尺寸信息
demo-scratch-gui 项目
src/lib/sb-file-uploader-hoc.jsx,增加 initStageNativeSize
函数,通过本地工程文件加载工程后,用工程文件中的 stageNativeSize
(舞台尺寸信息) 设置当前舞台的 stageNativeSize
背景编辑区域跟随当前尺寸
这个需求也不麻烦,只要在切换舞台尺寸时,更换背景编辑区域的尺寸就 ok
demo-scratch-paint 项目
主要修改内容如下:
核心就是提供一个接口函数,用于在切换舞台尺寸时,更换背景编辑区域的尺寸
- src/containers/paint-editor.jsx,修改原本的
handleZoomIn
和handleZoomOut
两个函数,优化放大、缩小时的交互效果 - src/helper/view.js,提供
setSvgArtBoardWidthHeight
接口函数,用于在切换舞台尺寸时,更换背景编辑区域的尺寸
demo-scratch-gui 项目
在 src/containers/stage-header.jsx 的 onStageNativeSizeChange
函数中,调用上面 demo-scratch-paint 项目提供的 setSvgArtBoardWidthHeight
函数
背景图片适配当前尺寸
这个需求就比较复杂了,还是先理一理思路先。这个需求,明显上来说,就是当舞台尺寸切换时,背景图片要填满当前尺寸
再回顾一下这三个效果
来,接下来理解一下具体是什么含义,再来看三张图:
ok,到这里估计大家应该都已经猜到了,所谓“背景图片适配当前尺寸”,实际上就是先拿一张大图,然后再根据尺寸需要,“裁剪”出自己需要的大小
另外,如果每次切换都“裁剪”并保存一遍图片的话会很麻烦,我们可以在用户上传背景图的时候,一下子把四张图(原图、另外三种尺寸的图)都上传到图床中,文件名是文件内容的 md5
值,这样,下次切换的时候,只需要通过原图计算出各个尺寸的图,然后再做 md5
就可以直接确定图片的 url 链接,然后直接交给引擎自己加载就OK
PS:源码中因为没有加入上传图床的代码,所以这部分的内容只是保留了逻辑代码,不能完全跑通,各位可以自行实现上图图床的代码,把这部分流程衔接起来
demo-scratch-svg-renderer 项目
src/bitmap-adapter.js 文件中的 setStageNativeSize
、getBackdropResizedWidthHeight
、importBackdropBitmap
、changeBackdropBitmap
、dataUrlToFile
、adaptiveMoreStageNativeSizeBackdropBitmap
函数都是新增的,用于实现上述说的通过原图计算所有尺寸的图片
demo-scratch-gui 项目
src/containers/costume-tab.jsx 文件中的 handleCostumeUpload
函数,在用户上传背景图时,将四张图(原图、另外三种尺寸的图)都上传到图床中
src/containers/stage.jsx 中的 onStageNativeSizeChange
函数,以下内容实现的是:通过原图计算出各个尺寸的图,然后再做 md5
就可以直接确定图片的 url 链接,然后直接交给引擎自己加载
至此,就完成了这一次的需求实现
不知不觉快 3 个月过去了,这个《Scratch3.0 二次开发》专栏系列也迎来了阶段性收尾 ✿✿ヽ(°▽°)ノ✿
,希望专栏中记录的内容对大家进行 Scratch 的二次开发有一点点的帮助,如有疑问,欢迎在评论区或者 github 项目中留言 (づ ̄3 ̄)づ╭❤~
转载自:https://juejin.cn/post/7149353389170622478