今日想搞一搞scratch,使用过程中发现官方给的扩展组件中有些在国内用不了,所以就想把这个问题给修复下,方便国内用户使用。

在修复这个问题之前,现熟悉下scratch,以及如何自定义扩展。

scratch

scratch是MIT开源的少儿编程工具,提供可视化的,积木式编程,降低学习门槛,丰富创作形式。
我使用的是scratch3.0,它是由多个模块组成的,与本篇文章涉及比较紧密的是scratch-guiscratch-vm,其中scratch-gui提供了可视化的操作界面,scratch-vm是提供了运行环境和扩展模块。

自定义扩展插件

scratch-vm中的改动

扩展插件的具体实现在scratch-vm模块中的src/extensions,当前目录中已有一些官方集成的插件,比如翻译、乐高互联相关的插件,每个扩展中都有个index.js文件,这个文件就是该扩展的主要实现入口。

自定义扩展中可以使用的积木块所在getInfo()方法中定义的,看下翻译扩展中getInfo()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
getInfo () {
...
return {
id: 'translate',
name: formatMessage({
id: 'translate.categoryName',
default: 'Translate',
description: 'Name of extension that adds translate blocks'
}),
blockIconURI: blockIconURI,
menuIconURI: menuIconURI,
blocks: [
{
opcode: 'getTranslate',
text: formatMessage({
id: 'translate.translateBlock',
default: 'translate [WORDS] to [LANGUAGE]',
description: 'translate some text to a different language'
}),
blockType: BlockType.REPORTER,
arguments: {
WORDS: {
type: ArgumentType.STRING,
defaultValue: formatMessage({
id: 'translate.defaultTextToTranslate',
default: 'hello',
description: 'hello: the default text to translate'
})
},
LANGUAGE: {
type: ArgumentType.STRING,
menu: 'languages',
defaultValue: this._randomLanguageCode
}
}
},
{
opcode: 'getViewerLanguage',
text: formatMessage({
id: 'translate.viewerLanguage',
default: 'language',
description: 'the languge of the project viewer'
}),
blockType: BlockType.REPORTER,
arguments: {}
}
],
...
};
}

其中blocks对应的值就是积木块类型,opcode是具体某个积木块的实现内容,如果要修改积木块的功能就修改此方法就可以。

自定义扩展的功能在此实现之后,还需要在src/extension-support/extension-manager.js中注册,这样在编译的时候,将其自定义扩展进行编译,已注册的扩展如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const builtinExtensions = {
// This is an example that isn't loaded with the other core blocks,
// but serves as a reference for loading core blocks as extensions.
coreExample: () => require('../blocks/scratch3_core_example'),
// These are the non-core built-in extensions.
pen: () => require('../extensions/scratch3_pen'),
wedo2: () => require('../extensions/scratch3_wedo2'),
music: () => require('../extensions/scratch3_music'),
microbit: () => require('../extensions/scratch3_microbit'),
text2speech: () => require('../extensions/scratch3_text2speech'),
translate: () => require('../extensions/scratch3_translate'),
videoSensing: () => require('../extensions/scratch3_video_sensing'),
ev3: () => require('../extensions/scratch3_ev3'),
makeymakey: () => require('../extensions/scratch3_makeymakey'),
boost: () => require('../extensions/scratch3_boost'),
gdxfor: () => require('../extensions/scratch3_gdx_for'),
};

scratch-gui中的改动

scratch-vm修改结束之后,还需要在scratch-gui中导入该扩展的一些信息与入口,修改/src/lib/libraries/extensions/index.jsx文件,
首先导入自定义扩展显示图标,代码如下:

1
2
import translateIconURL from './translate/translate.png';
import translateInsetIconURL from './translate/translate-small.png';

其次在export default 代码块中增加自定义扩展的一些描述信息,需要注意的是其中的extensionId的值需要与scratch-vmbuiltinExtensions的值对应。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
name: (
<FormattedMessage
defaultMessage="Translate"
description="Name for the Translate extension"
id="gui.extension.translate.name"
/>
),
extensionId: 'translate',
collaborator: 'YuanbaLab',
iconURL: translateIconURL,
insetIconURL: translateInsetIconURL,
description: (
<FormattedMessage
defaultMessage="Translate text into many languages."
description="Description for the Translate extension"
id="gui.extension.translate.description"
/>
),
featured: true,
internetConnectionRequired: true
}

编译调试

编译调试需要具备node.js环境,安装npm install -g webpacknpm install -g webpack-dev-server
进入scratch-vm项目目录中,执行如下命令:

1
2
3
npm install
npm link
npm run watch

然后再开一个终端,进入scratch-gui目录中,执行如下命令:

1
2
3
npm install
npm link scratch-vm
npm start

没有任何错误信息之后,就可以在http://127.0.0.1:8601/地址使用scratch3.0了。

编译成桌面程序

git clone git@github.com:hunshenshi/scratch-desktop.git

cd scratch-gui
npm install
npm link

cd scratch-desktop
npm install
npm link scratch-gui
npm run dist

electron 报错
进入 electron目录,执行node install.js

Cannot find module ‘autoprefixer’”
npm install –save autoprefixer@^9.0.1

将 本地scratch-vm和scratch-gui cp到desktop中 or npm link scratch-vm scratch-blocks
npm run clean && npm run compile && npm run doBuild – –mode=dev

npm run dist # 编译后的安装包Scratch Desktop-3.8.0.AppImage和scratch-desktop_3.8.0_amd64.snap保存在scratch-desktop/dist/文件夹中。