其它 API
现在你已经熟悉了怎么编写自定义扩展,我们将会分享一些更多的 API。 这些 API 在沙箱和非沙箱扩展中都有效。它们都可以一起使用。
color1, color2, color3
这三个属性分别决定了积木的颜色、积木输入的颜色、以及每个扩展积木下拉菜单的颜色。一般来讲,color1
应当最明亮,color2
要稍微深一些,color3
应当颜色最深。它们应当被设置为十六进制颜色代码 (如 #808080
)。
class ColorExample {
getInfo() {
return {
id: 'colorexample',
name: '积木颜色示例',
// 故意选了点很糟糕的色,这样你才能看得更清楚
color1: '#ff0000', // 纯红
color2: '#00ff00', // 纯绿
color3: '#0000ff', // 纯蓝
blocks: [
{
opcode: 'reporter',
blockType: Scratch.BlockType.REPORTER,
text: '字符串 [STRING] 布尔值 [BOOLEAN] 可嵌入返回值菜单 [MENU] 不可嵌入返回值菜单 [FIELD]',
arguments: {
STRING: {
type: Scratch.ArgumentType.STRING,
defaultValue: '1'
},
BOOLEAN: {
type: Scratch.ArgumentType.BOOLEAN
},
MENU: {
type: Scratch.ArgumentType.STRING,
menu: 'MENU'
},
FIELD: {
type: Scratch.ArgumentType.STRING,
menu: 'FIELD'
}
}
},
],
menus: {
MENU: {
acceptReporters: true,
items: ['item 1', 'item 2']
},
// 这里使用 acceptReporters: false 只是为了示例。
// 在实际使用中,如果不想恶心用户或者只设置固定选择,建议不要这样设置。
FIELD: {
acceptReporters: false,
items: ['item 1', 'item 2']
}
}
};
}
reporter() {
return '这个积木啥也不干';
}
}
Scratch.extensions.register(new ColorExample());
不同的积木颜色模式 (比如 高对比度, 深色模式 以及任何 "插件" 预设) 是基于这些值自动生成的。
docsURI
docsURI 在积木列表的开头添加了一个按钮,允许打开一个页面让人们进一步了解你的扩展怎么用。
class HelloDocs {
getInfo() {
return {
id: 'hellodocs',
name: '你好 扩展文档!',
docsURI: 'https://furryr.github.io/turbowarp-docs-cn/development/extensions/docsURI-demo',
blocks: [
{
opcode: 'hello',
blockType: Scratch.BlockType.REPORTER,
text: 'Hello!'
}
]
};
}
hello() {
return Math.random();
}
}
Scratch.extensions.register(new HelloDocs());
disableMonitor
Scratch 将会自动地在每个没有输入的返回值及目前添加一个复选框用于显示变量监视器。注意在 TurboWarp 中,这对布尔值积木也有效。若需要禁用此功能,请将积木的 disableMonitor 设置为 true。
请注意,即使设置了 disableMonitor,这个积木仍然能被别有用心的人用于监视器。
class DisableMonitorExample {
getInfo() {
return {
id: 'disablemonitorexample',
name: '禁止监视变量示例',
blocks: [
{
opcode: 'monitorable',
blockType: Scratch.BlockType.REPORTER,
text: '这个积木可以被监视'
},
{
opcode: 'unmonitorable',
blockType: Scratch.BlockType.REPORTER,
text: '但这个就不行了捏',
disableMonitor: true
},
]
};
}
monitorable() {
return Math.random();
}
unmonitorable() {
return Math.random();
}
}
Scratch.extensions.register(new DisableMonitorExample());
Scratch.Cast
Scratch 用于处理诸如类型转换或比较的方式有一些特殊的地方。比起手动实现这些行为,你可以使用 Scratch.Cast.* API。
class CastingExample {
getInfo() {
return {
id: 'castexample',
name: '类型转换示例',
blocks: [
{
opcode: 'toNumber',
blockType: Scratch.BlockType.REPORTER,
text: '[INPUT] 作为数字',
arguments: {
INPUT: {
type: Scratch.ArgumentType.STRING,
defaultValue: '3.0'
}
}
},
{
// opcode "toString" 应该可以用,但是它在 JavaScript 中有特殊用途,
// 所以用它可能比较危险,在前面加个前缀好了。
opcode: 'castToString',
blockType: Scratch.BlockType.REPORTER,
text: '[INPUT] 作为字符串',
arguments: {
INPUT: {
type: Scratch.ArgumentType.STRING,
defaultValue: 'Hello'
}
}
},
{
opcode: 'toBoolean',
blockType: Scratch.BlockType.BOOLEAN,
text: '[INPUT] 作为布尔值',
arguments: {
INPUT: {
type: Scratch.ArgumentType.STRING,
defaultValue: '1'
}
}
},
{
opcode: 'compare',
blockType: Scratch.BlockType.REPORTER,
text: '[A] 与 [B] 比较的结果',
arguments: {
A: {
type: Scratch.ArgumentType.STRING,
defaultValue: '3'
},
B: {
type: Scratch.ArgumentType.STRING,
defaultValue: '5'
}
}
}
]
};
}
toNumber({INPUT}) {
return Scratch.Cast.toNumber(INPUT);
}
castToString({INPUT}) {
return Scratch.Cast.toString(INPUT);
}
toBoolean({INPUT}) {
return Scratch.Cast.toBoolean(INPUT);
}
compare({A, B}) {
const comparison = Scratch.Cast.compare(A, B);
// You need to use < 0, > 0, or === 0 here.
// Do not use === 1 or === -1! That will not work in some cases.
if (comparison === 0) {
return '相等';
} else if (comparison > 0) {
return 'A 更大';
} else if (comparison < 0) {
return 'B 更小';
}
}
}
Scratch.extensions.register(new CastingExample());
hideFromPalette
有时候你可能想要从积木区隐藏一个积木,但你又不想移除它,这个时候 hideFromPalette 会很有用。它有助于让你的扩展 向前兼容。有着这个属性的积木会从积木区隐去,但已经存在于项目中的积木将保持原样。
比如,加载这里的第一个扩展,然后用它的积木保存一个项目:
class HideFromPaletteExample {
getInfo() {
return {
id: 'hidefrompaletteexample',
name: 'hideFromPalette 示例',
blocks: [
{
opcode: 'hidden',
blockType: Scratch.BlockType.REPORTER,
text: '示例积木 (visible)'
},
]
};
}
hidden() {
return '积木还是可见的捏';
}
}
Scratch.extensions.register(new HideFromPaletteExample());
然后再换掉之前那个扩展而加载这个扩展,然后加载之前的项目:
class HideFromPaletteExample {
getInfo() {
return {
id: 'hidefrompaletteexample',
name: 'hideFromPalette 示例',
blocks: [
{
opcode: 'hidden',
blockType: Scratch.BlockType.REPORTER,
text: '示例积木 (已隐藏)',
hideFromPalette: true
},
]
};
}
hidden() {
return '这个积木被从积木区隐藏了,但还能用';
}
}
Scratch.extensions.register(new HideFromPaletteExample());
注意到积木的副本仍然有用,但它不在积木区中显示了。
filter
一些积木可能只能在角色或者只能在舞台中运行。对于这些积木,你可以将 filter 属性设置为一个仅包含 Scratch.TargetType.STAGE
或 Scratch.TargetType.SPRITE
的数组,来让它只在那种类型的角色中可见。
请注意,仍然有办法无视过滤器限制而获取积木,比如使用背包或者积木剪贴板。你的积木还应当使用 util.target.isStage
确认当前角色是否为舞台。
class FilterExample {
getInfo() {
return {
id: 'filterexample',
name: '过滤器示例',
blocks: [
{
opcode: 'all',
blockType: Scratch.BlockType.COMMAND,
text: '角色和舞台都能用',
},
{
opcode: 'sprites',
blockType: Scratch.BlockType.COMMAND,
text: '只在角色能用',
filter: [Scratch.TargetType.SPRITE]
},
{
opcode: 'stage',
blockType: Scratch.BlockType.COMMAND,
text: '只在舞台能用',
filter: [Scratch.TargetType.STAGE]
},
{
opcode: 'none',
blockType: Scratch.BlockType.COMMAND,
text: '都不能用(那拿来干嘛?)',
// NOTE: 如果你只是想要表示这个积木已经被废弃,那就使用 hideFromPalette: true 而不是 filter: []
filter: []
}
]
};
}
all() {
return 0;
}
sprites() {
return 0;
}
stage() {
return 0;
}
none() {
return 0;
}
}
Scratch.extensions.register(new FilterExample());
图标
对于向你的扩展添加图标,有三种不同的方式:
- 扩展的 menuIconURI。这会设置在积木区分类中显示的图像。如果没有设置则会回落到 blockIconURI。如果 blockIconURI 也没有被设置,那么会回落到以扩展积木颜色填充的圆圈。
- 扩展的 blockIconURI。这会成为没有覆盖这个选项的积木的默认图像。
- 积木的 blockIconURI。这会覆盖扩展设置的 blockIconURI。
上述三个字段应当为内联的 Data URL。SVG 是最好的选择,不过大小至少为 64x64 的 PNG 和 JPG 图片也不错。图标应当是方形的。
// 来自 Box2D 扩展: https://github.com/TurboWarp/extensions/blob/master/extensions/box2d.js
const blocksIcon = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiDQoJIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHhtbG5zOmE9Imh0dHA6Ly9ucy5hZG9iZS5jb20vQWRvYmVTVkdWaWV3ZXJFeHRlbnNpb25zLzMuMC8iDQoJIHg9IjBweCIgeT0iMHB4IiB3aWR0aD0iNDBweCIgaGVpZ2h0PSI0MHB4IiB2aWV3Qm94PSItMy43IC0zLjcgNDAgNDAiIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgLTMuNyAtMy43IDQwIDQwIg0KCSB4bWw6c3BhY2U9InByZXNlcnZlIj4NCjxkZWZzPg0KPC9kZWZzPg0KPHJlY3QgeD0iOC45IiB5PSIxLjUiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iIzE2OUZCMCIgc3Ryb2tlLXdpZHRoPSIzIiB3aWR0aD0iMTQuOCIgaGVpZ2h0PSIxNC44Ii8+DQo8cmVjdCB4PSIxLjUiIHk9IjE2LjMiIGZpbGw9IiNGRkZGRkYiIHN0cm9rZT0iIzE2OUZCMCIgc3Ryb2tlLXdpZHRoPSIzIiB3aWR0aD0iMTQuOCIgaGVpZ2h0PSIxNC44Ii8+DQo8cmVjdCB4PSIxNi4zIiB5PSIxNi4zIiBmaWxsPSIjRkZGRkZGIiBzdHJva2U9IiMxNjlGQjAiIHN0cm9rZS13aWR0aD0iMyIgd2lkdGg9IjE0LjgiIGhlaWdodD0iMTQuOCIvPg0KPC9zdmc+";
// 来自 画笔+ 扩展: https://github.com/TurboWarp/extensions/blob/master/extensions/penplus.js
const dangoIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABeCAYAAADc6BHlAAAAAXNSR0IArs4c6QAABItJREFUeF7tncuN2zAQhu0SctmCAuSQDnLZAlLCAjkG2BJSwF62gxwWSEG5pIQEFJYKRQ5f8+BzfLSoMfV/8yIl2/db+PrrvXUHxti3/LGJobeUndR5Sx9zRUmJWTquVCyF8a4UKOzj89Pt5em5VMxj3Idf34Pxfz5+y9nYHoQV4PR+I777ioGABM+pHQGyNYRqABjhfTAAiG0hRAH4ns8hvIIIc0RRcZUQ307Fi4btIiELQFJ8hXALevNLK9pC/N0h+CF/Amgp/s4QFECudxY+DtaAHt6/axQoAGEPz5kP1gE9vR+IguXb0tEBGCZLQ7gAGMH7jeI7Lc6GBOBB0AjIFRKJ404UKAAJgXM2dwLQdfUbA7ETAKPBAWGUIgwUYpfTUilpmCJccPsyFixTA+kOgCC8D2RKEN0AQMI//n7L1ebz+MvDpyUiostK2Be/RnhIdQDGNNHQFAC38C6MSEQMDyLYDZXqhCTFT4CYD4BUO+oCoKacXKHwomFoCOAdMe4oaCm+hTMLBPFbkj3EnwkCFJ5sWxM9xTcQZoiCWH5kgdAbwAwQsgAoRdkCkC66FUV5uIKcmhDpIa0RvH+GWpDzCDSEUbx/9DSUA3BuVbthnmtTR/J+IApKrjmX1diO10wG/ApT7psxvfP/SgDstdR8Me82IABzHTWOx+btkCHKRIpAKIA0PwoAyHIARQG0BXBJU6OIP3InxB0BQZ3oDSFx54w7JaNqxZIAKkXvemtzKQAp4b/8/BH10NfPX1PeK6XR8ZmSxo+C3CoFQeKnRI8pHoEhppOYYfuwlzQAX3iM6BAMAISIViJG3y/o/88fVDxuUlPJpMR35yANYloALcS3IDwIrJqxGgO8VywKXABcaScVfVIQpgTQWnzJSJAGYObOGgW9xJeC0AIAKwQLoEXaKeiOyPqRDRR2LZdNOmxr2tv7JaKgFYBLFGAXaL29f3YAJAijeD8AgeTEpJML048/DHXPYGAApC2dHgCCLWv7Rqo2jJJ+uNNQTwBBSoIiykJRAMh8U3ha0f1lY6tX+5lpSdGOjD6xUFjMsCQMBYCRlH7OCUUB0MXEWFAAGNWYzzkgaAQwq1phbigAXNvTIxbhGJNmAFxxYxG3LQDJNBR7OgKCoAAqclfJ0MyjKUHtccaTsgjp5JILYx4jloasoKn/T7CRwOX9pE0kZmFLzYm0o66gPgAzMfen/A2EnQGc+0ec7WgOgA/B8RZyBiEbKHVdxnFdoiACgawf2QCjsDWm2CH4RRhKRQAEsn5kAzWqMY69bNhxpaMeEGYFcNYCC3VWCDMDWALC7ACmh7ACAJuFWOpCakUsUZhXAhBEQ019yG1FWFvcEFYDAEYDsvtytbk+2ef93aO17/35XZG2RYOQFzDCacU3+wtWtyIQVgcQcwIjJuba2SFgJjGCZ/ecAysEBYBDyQZBAeAABB0XtjtSAHgALBAUAA0AGYICoAMgQVAAPADQEBQAHwAMhLsC4AVQBMHdslAA/ACyEBwAGgEy+h9WwcWav2GnESBIwIcAfJRGgKz+YST4u67/APKrBHxjStmdAAAAAElFTkSuQmCC";
const colorIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF4AAABeCAYAAACq0qNuAAAAAXNSR0IArs4c6QAABTFJREFUeF7t3b2KFEEUBeAecBVkk8nERBSMBEGMTDcxN/IhfATDRdinMDSaV5gn8REEo40MlBqoobrmVtWtqvtzWnYzd3tmer46ffrOr7tlOz9/mbu6Y27nuhniTnKBe+Gg7ivKzmhhlxbH/X577UAT+smnD81EP3r9vLnN/d2huc2yLOYO1jdYBOdA54Ic+PwyjYUw87C6IRJ8BDuFHIFPL19ZBHUX9RtYluUCfRY84s3Cx+spLICqjeaVq4FLw3ssgAa8OrgWvOUCSMOv0KUqpTSWSFVN6fqJChLzEruivMu10QOWNny4DS18CXjTlEtONZwBv1I/U3ZTF/ZIuRe8dPpn4N2Srn1yrR0JUtUzCu+ObtXx1CJI4I/AQ6B7wkvUTi88DLo3/Cz+MLzFuNiaOizGydY+ZLXD9mRvmE4wCOgIiS+MmixT1kaI6EjwRO00XZsboKKjwffiP8C3Srzj7z1934I/TzEove75yJWzBlx8FjwiOmLVECfbom8N/pz26xfPlj/vX3IW3HQbhHGS8ciWNC7Br9DTK0daAET4xx/fnbh+33xN2S6cu+HDtaHgI8FH8Kg9Al9Me35YeS8AAnwOnhrV8KnEs+HjjXgtgCf8/d1htz/eVt+Y1QPfje6J7wVfS3neCiX8PPHD8B4LYA3fA97qehI+jI+zPxb1YwU/Al7o+rO3GrzF9GMBP4uejZYk/HTNlI4SrfRrwkuA1+omTfwJXqJmrBZAA14SvFY3pvDS9SMJrwVOpP5kHuHVakYz/VLw2ujUUwhu8BLj5yy8BXip51fwmv3eGk9HTsCj8JbgpZ6HgR/p/154L3Cq56Hge+unB94bPZ/nIeG5C8CBRwAvJd58omn1ffr3WvfX4JHAqRNsSDw0fC39FDwi+KbhqQXI4ZHR81l+M4mn6ifCo4P/F4lPF+Dq+5ee04X7tumLIptMfBC8un663Pz4dsI8/vrpjsrZgU3DB/D4E+Hjv9EXYJPwKXgJHj39m4On0ANynvj0cEdM/2bgS+C1xOddi7QAOXzYV/VXnzgnn9XEknR56bK1xCOmP4HfwT1X00p5CsqFRzn5QsL3gPdUDXW0eNUPHPwIeuvk2qo2D/wifNhZy1ehRsFnE+/R//lb+Vxec50Fl4S36v8SvNlkI4U+WzXW3Z/WTLhts/fVSIJrJF67fprw0j2vAa4NL10/1Fu1Vd+0qomuUTVa9ZOnPa8asZ7XBrdKvFT9sOFH68YK3AN+tH7UPxFijW5VNbP1w4U/1w039R7gnonvqZ+eD5+x4T3BUeBb9dML38RHQPesGqp+wu/S539S9P3xNnzSezVBdn2yGwUcLfFU/Yx8sjtez+odZmjoiImPcIe3n89rQaWdmuPzo+iEv3/zqnR0uf6+94UQq51N4E+f/s5rhg2Pio8In6a99n+PtL4oaHWiRUs+GjwXnZP4B/iOfpKGh8VHSnwPOjfxF1MOSuWgwPei98LDJR8BfgR9Ch5h0vGGz9C7PDlTDTnbx1961o4n/Ax61wpl+quvhPLC94KfRZ+BX/W9V+14wEugz8K741vDS6FLwLviW8JLokvBX8z5VtVjAS8NHrFGpprag2jTk642vBa6dOLJ5GumXwueABe3kk58ejRcfAup9NgpDW8BrlU1VA2pLYAUvCW4JfzF5CP1qHcWvgAuXitUGjWrhpX+mUUYga9gm4BbJ776fA+1QpzzAQe+Ae3mYJ340iha/Trw2vw6+Df3++2+AwSc1iJA3VeonWmkl7sgm7hP/wDwgcxktVR5CQAAAABJRU5ErkJggg==";
class IconsExample {
getInfo() {
return {
id: 'iconsexample',
name: '图标示例',
menuIconURI: blocksIcon, // 积木区分类图标 URI
blockIconURI: dangoIcon, // 积木图标 URI
blocks: [
{
opcode: 'defaultIcon',
blockType: Scratch.BlockType.REPORTER,
text: '默认图标 (见上) 的返回值积木 [INPUT]',
arguments: {
INPUT: {
type: Scratch.ArgumentType.STRING,
defaultValue: '0'
}
}
},
{
opcode: 'overriddenIcon',
blockType: Scratch.BlockType.COMMAND,
text: '覆盖图标的命令积木 [INPUT]',
blockIconURI: colorIcon,
arguments: {
INPUT: {
type: Scratch.ArgumentType.STRING,
defaultValue: '0'
}
}
}
]
};
}
defaultIcon() {
return 0;
}
overriddenIcon() {
}
}
Scratch.extensions.register(new IconsExample());
内联图像
你还可以通过一个类型为 IMAGE
的参数在积木内的任何位置添加一个图像。和其它图像一样,这应当为一个内联的 Data URL。SVG 是最好的选择,不过大小至少为 64x64 的 PNG 和 JPG 图片也不错。图标应当是方形的。
另外,如果你将 flipRTL
设置为 true
,那么当编辑器使用从右往左书写的语言时,图像就会被水平翻转。
// 来自 画笔+ 扩展: https://github.com/TurboWarp/extensions/blob/master/extensions/penplus.js
const dangoIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABeCAYAAADc6BHlAAAAAXNSR0IArs4c6QAABItJREFUeF7tncuN2zAQhu0SctmCAuSQDnLZAlLCAjkG2BJSwF62gxwWSEG5pIQEFJYKRQ5f8+BzfLSoMfV/8yIl2/db+PrrvXUHxti3/LGJobeUndR5Sx9zRUmJWTquVCyF8a4UKOzj89Pt5em5VMxj3Idf34Pxfz5+y9nYHoQV4PR+I777ioGABM+pHQGyNYRqABjhfTAAiG0hRAH4ns8hvIIIc0RRcZUQ307Fi4btIiELQFJ8hXALevNLK9pC/N0h+CF/Amgp/s4QFECudxY+DtaAHt6/axQoAGEPz5kP1gE9vR+IguXb0tEBGCZLQ7gAGMH7jeI7Lc6GBOBB0AjIFRKJ404UKAAJgXM2dwLQdfUbA7ETAKPBAWGUIgwUYpfTUilpmCJccPsyFixTA+kOgCC8D2RKEN0AQMI//n7L1ebz+MvDpyUiostK2Be/RnhIdQDGNNHQFAC38C6MSEQMDyLYDZXqhCTFT4CYD4BUO+oCoKacXKHwomFoCOAdMe4oaCm+hTMLBPFbkj3EnwkCFJ5sWxM9xTcQZoiCWH5kgdAbwAwQsgAoRdkCkC66FUV5uIKcmhDpIa0RvH+GWpDzCDSEUbx/9DSUA3BuVbthnmtTR/J+IApKrjmX1diO10wG/ApT7psxvfP/SgDstdR8Me82IABzHTWOx+btkCHKRIpAKIA0PwoAyHIARQG0BXBJU6OIP3InxB0BQZ3oDSFx54w7JaNqxZIAKkXvemtzKQAp4b/8/BH10NfPX1PeK6XR8ZmSxo+C3CoFQeKnRI8pHoEhppOYYfuwlzQAX3iM6BAMAISIViJG3y/o/88fVDxuUlPJpMR35yANYloALcS3IDwIrJqxGgO8VywKXABcaScVfVIQpgTQWnzJSJAGYObOGgW9xJeC0AIAKwQLoEXaKeiOyPqRDRR2LZdNOmxr2tv7JaKgFYBLFGAXaL29f3YAJAijeD8AgeTEpJML048/DHXPYGAApC2dHgCCLWv7Rqo2jJJ+uNNQTwBBSoIiykJRAMh8U3ha0f1lY6tX+5lpSdGOjD6xUFjMsCQMBYCRlH7OCUUB0MXEWFAAGNWYzzkgaAQwq1phbigAXNvTIxbhGJNmAFxxYxG3LQDJNBR7OgKCoAAqclfJ0MyjKUHtccaTsgjp5JILYx4jloasoKn/T7CRwOX9pE0kZmFLzYm0o66gPgAzMfen/A2EnQGc+0ec7WgOgA/B8RZyBiEbKHVdxnFdoiACgawf2QCjsDWm2CH4RRhKRQAEsn5kAzWqMY69bNhxpaMeEGYFcNYCC3VWCDMDWALC7ACmh7ACAJuFWOpCakUsUZhXAhBEQ019yG1FWFvcEFYDAEYDsvtytbk+2ef93aO17/35XZG2RYOQFzDCacU3+wtWtyIQVgcQcwIjJuba2SFgJjGCZ/ecAysEBYBDyQZBAeAABB0XtjtSAHgALBAUAA0AGYICoAMgQVAAPADQEBQAHwAMhLsC4AVQBMHdslAA/ACyEBwAGgEy+h9WwcWav2GnESBIwIcAfJRGgKz+YST4u67/APKrBHxjStmdAAAAAElFTkSuQmCC";
const colorIcon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF4AAABeCAYAAACq0qNuAAAAAXNSR0IArs4c6QAABTFJREFUeF7t3b2KFEEUBeAecBVkk8nERBSMBEGMTDcxN/IhfATDRdinMDSaV5gn8REEo40MlBqoobrmVtWtqvtzWnYzd3tmer46ffrOr7tlOz9/mbu6Y27nuhniTnKBe+Gg7ivKzmhhlxbH/X577UAT+smnD81EP3r9vLnN/d2huc2yLOYO1jdYBOdA54Ic+PwyjYUw87C6IRJ8BDuFHIFPL19ZBHUX9RtYluUCfRY84s3Cx+spLICqjeaVq4FLw3ssgAa8OrgWvOUCSMOv0KUqpTSWSFVN6fqJChLzEruivMu10QOWNny4DS18CXjTlEtONZwBv1I/U3ZTF/ZIuRe8dPpn4N2Srn1yrR0JUtUzCu+ObtXx1CJI4I/AQ6B7wkvUTi88DLo3/Cz+MLzFuNiaOizGydY+ZLXD9mRvmE4wCOgIiS+MmixT1kaI6EjwRO00XZsboKKjwffiP8C3Srzj7z1934I/TzEove75yJWzBlx8FjwiOmLVECfbom8N/pz26xfPlj/vX3IW3HQbhHGS8ciWNC7Br9DTK0daAET4xx/fnbh+33xN2S6cu+HDtaHgI8FH8Kg9Al9Me35YeS8AAnwOnhrV8KnEs+HjjXgtgCf8/d1htz/eVt+Y1QPfje6J7wVfS3neCiX8PPHD8B4LYA3fA97qehI+jI+zPxb1YwU/Al7o+rO3GrzF9GMBP4uejZYk/HTNlI4SrfRrwkuA1+omTfwJXqJmrBZAA14SvFY3pvDS9SMJrwVOpP5kHuHVakYz/VLw2ujUUwhu8BLj5yy8BXip51fwmv3eGk9HTsCj8JbgpZ6HgR/p/154L3Cq56Hge+unB94bPZ/nIeG5C8CBRwAvJd58omn1ffr3WvfX4JHAqRNsSDw0fC39FDwi+KbhqQXI4ZHR81l+M4mn6ifCo4P/F4lPF+Dq+5ee04X7tumLIptMfBC8un663Pz4dsI8/vrpjsrZgU3DB/D4E+Hjv9EXYJPwKXgJHj39m4On0ANynvj0cEdM/2bgS+C1xOddi7QAOXzYV/VXnzgnn9XEknR56bK1xCOmP4HfwT1X00p5CsqFRzn5QsL3gPdUDXW0eNUPHPwIeuvk2qo2D/wifNhZy1ehRsFnE+/R//lb+Vxec50Fl4S36v8SvNlkI4U+WzXW3Z/WTLhts/fVSIJrJF67fprw0j2vAa4NL10/1Fu1Vd+0qomuUTVa9ZOnPa8asZ7XBrdKvFT9sOFH68YK3AN+tH7UPxFijW5VNbP1w4U/1w039R7gnonvqZ+eD5+x4T3BUeBb9dML38RHQPesGqp+wu/S539S9P3xNnzSezVBdn2yGwUcLfFU/Yx8sjtez+odZmjoiImPcIe3n89rQaWdmuPzo+iEv3/zqnR0uf6+94UQq51N4E+f/s5rhg2Pio8In6a99n+PtL4oaHWiRUs+GjwXnZP4B/iOfpKGh8VHSnwPOjfxF1MOSuWgwPei98LDJR8BfgR9Ch5h0vGGz9C7PDlTDTnbx1961o4n/Ax61wpl+quvhPLC94KfRZ+BX/W9V+14wEugz8K741vDS6FLwLviW8JLokvBX8z5VtVjAS8NHrFGpprag2jTk642vBa6dOLJ5GumXwueABe3kk58ejRcfAup9NgpDW8BrlU1VA2pLYAUvCW4JfzF5CP1qHcWvgAuXitUGjWrhpX+mUUYga9gm4BbJ776fA+1QpzzAQe+Ae3mYJ340iha/Trw2vw6+Df3++2+AwSc1iJA3VeonWmkl7sgm7hP/wDwgcxktVR5CQAAAABJRU5ErkJggg==";
class InlineImagesExample {
getInfo() {
return {
id: 'inlineimagesexample',
name: '内嵌图像示例',
blocks: [
{
opcode: 'reporter',
blockType: Scratch.BlockType.REPORTER,
text: '一些文本 [IMAGE] 更多文本',
arguments: {
IMAGE: {
type: Scratch.ArgumentType.IMAGE,
dataURI: dangoIcon
}
}
},
{
opcode: 'command',
blockType: Scratch.BlockType.COMMAND,
blockIconURI: colorIcon,
text: '一些文本 [IMAGE] 更多文本',
arguments: {
IMAGE: {
type: Scratch.ArgumentType.IMAGE,
dataURI: dangoIcon,
flipRTL: true
}
}
}
]
};
}
reporter() {
return '示例积木';
}
command() {
}
}
Scratch.extensions.register(new InlineImagesExample());
分割线
如果你的扩展有一大堆积木,你可能想要在两组积木间留出一些空隙。要这样做,请在积木列表中添加 "---"
:
class SeparatorExample {
getInfo() {
return {
id: 'separatorexample',
name: '分割线示例',
blocks: [
{
opcode: 'block1',
blockType: Scratch.BlockType.COMMAND,
text: '第一组'
},
{
opcode: 'block2',
blockType: Scratch.BlockType.COMMAND,
text: '也是第一组的',
},
'---',
{
opcode: 'block3',
blockType: Scratch.BlockType.COMMAND,
text: '第二组'
},
'---',
{
opcode: 'block4',
blockType: Scratch.BlockType.COMMAND,
text: '第三组',
},
]
};
}
block1() {}
block2() {}
block3() {}
block4() {}
}
Scratch.extensions.register(new SeparatorExample());
译者注:有些 Gandi IDE 扩展使用了非标准的 "---类别名"
用于实现和 Scratch.BlockType.LABEL
等同的功能。这样做只能在 Gandi IDE 使用,并且 Scratch 从来没有定义过这样的用法。
在扩展开发中,请避免这种写法,而换用通用的 Scratch.BlockType.LABEL
。
终止积木
若你不想在某个积木下面再让用户添加积木,请在积木上添加 isTerminal: true
。
虽然积木的样子很像 "停止这个脚本" 和 "停止全部脚本",但行为却和它们两者却大相径庭。举个例子,如果这个积木被放置在循环的末尾,循环会继续运行,除非有什么额外的代码能够停止当前线程。添加 isTerminal
只能避免用户在积木后面再连接积木。
class TerminalExample {
getInfo() {
return {
id: 'terminalexample',
name: '终止积木示例',
blocks: [
{
opcode: 'terminalBlock',
blockType: Scratch.BlockType.COMMAND,
isTerminal: true,
text: '下面可就接不了积木了!'
}
]
};
}
terminalBlock() {
}
}
Scratch.extensions.register(new TerminalExample());
下一步
然后,让我们来看看 怎么制作类似于 "当接收到" 或者 "当计时器大于" 的积木。