444 lines
12 KiB
Markdown
444 lines
12 KiB
Markdown
|
English | [简体中文](./README.md)
|
|||
|
|
|||
|
# Introduction
|
|||
|
|
|||
|
You don't need to focus on implementation of Scratch3.0 functionality. Only use simple JavaScript language to call Scratch functions.
|
|||
|
|
|||
|
|
|||
|
## That can be implemented
|
|||
|
|
|||
|
- load project
|
|||
|
- upload project
|
|||
|
- change style
|
|||
|
- mobile scratch player
|
|||
|
- virtual keyboard
|
|||
|
- change block size
|
|||
|
- hidden block category or specific block
|
|||
|
- custom assets library
|
|||
|
- backpack API
|
|||
|
- and more……
|
|||
|
|
|||
|
### The case
|
|||
|
|
|||
|
The Teaching system is embed this project.
|
|||
|
|
|||
|
website:https://teaching.vip
|
|||
|
|
|||
|
source:http://github.com/open-scratch/teaching-open
|
|||
|
|
|||
|
### Secondary development
|
|||
|
|
|||
|
- install dependencies
|
|||
|
npm install
|
|||
|
|
|||
|
- debug
|
|||
|
npm start
|
|||
|
|
|||
|
- build for productioin
|
|||
|
npm run build:prod
|
|||
|
|
|||
|
|
|||
|
# Quickly to use
|
|||
|
|
|||
|
## use DEMO
|
|||
|
|
|||
|
After build, see `index.html` and `player.html`.
|
|||
|
|
|||
|
## Inject to page
|
|||
|
|
|||
|
|
|||
|
import `lib.min.js` and `chunks/gui.js`, scratch will render into`<div id="scratch"></div>`。
|
|||
|
|
|||
|
Do not forget to edit `window.scratchConfig`
|
|||
|
|
|||
|
|
|||
|
# Document
|
|||
|
|
|||
|
## initial config
|
|||
|
|
|||
|
Notice: The window.scratchConfig object need created before import `lib.min.js`
|
|||
|
|
|||
|
This is a complete configuration example
|
|||
|
|
|||
|
```js
|
|||
|
window.scratchConfig = {
|
|||
|
session: {
|
|||
|
token: "", // user token
|
|||
|
username: "Username" // user name
|
|||
|
},
|
|||
|
backpack:{
|
|||
|
enable: true, // enable backpack
|
|||
|
api: "/api/teaching/scratch/backpack", //backpack API
|
|||
|
},
|
|||
|
cloudData:{
|
|||
|
enable: true, //enable cloud data
|
|||
|
id: "create", //default cloud data ID
|
|||
|
api: "127.0.0.1:1234/api/websocket/scratch/cloudData" //cloud data API
|
|||
|
},
|
|||
|
projectInfo: {//project info
|
|||
|
projectName: "",
|
|||
|
authorUsername: "admin",
|
|||
|
authorAvatar: './static/avatar.png',
|
|||
|
},
|
|||
|
logo: {
|
|||
|
show: true, //is visible
|
|||
|
url: "./static/logo.png", //logo url, support base64 images
|
|||
|
handleClickLogo: () => { //handle logo click event
|
|||
|
}
|
|||
|
},
|
|||
|
menuBar: {
|
|||
|
//menu bar style
|
|||
|
style: {
|
|||
|
background: 'hsla(215, 100%, 65%, 1)',
|
|||
|
},
|
|||
|
//new project button
|
|||
|
newButton:{
|
|||
|
show: true, //is visible
|
|||
|
handleBefore(){
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
//load project from computer button
|
|||
|
loadFileButton:{
|
|||
|
show: true, //is visible
|
|||
|
handleBefore(){
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
//save project to computer button
|
|||
|
saveFileButton:{
|
|||
|
show: true, //is visible
|
|||
|
handleBefore(){
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
//turbo mode button
|
|||
|
turboModeButton:{
|
|||
|
show: true //is visible
|
|||
|
},
|
|||
|
//help button
|
|||
|
helpButton:{
|
|||
|
show: true, //is visible
|
|||
|
handleBefore:()=>{
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
//my stuff button
|
|||
|
myStuff:{
|
|||
|
show: true, //is visible
|
|||
|
url: '/myProject' //my project href
|
|||
|
},
|
|||
|
//user avatar button
|
|||
|
userAvatar:{
|
|||
|
show: true, //is visible
|
|||
|
username: '未登录', //user name
|
|||
|
avatar: './static/avatar.png', //avatar image url
|
|||
|
handleClick(){
|
|||
|
//handle click avatar button
|
|||
|
}
|
|||
|
},
|
|||
|
//custom buttons
|
|||
|
customButtons: [
|
|||
|
{
|
|||
|
show: true, //is visible
|
|||
|
buttonName: 'Share', //button label name
|
|||
|
style:{ //button style
|
|||
|
color: 'white',
|
|||
|
background: 'hsla(30, 100%, 55%, 1)',
|
|||
|
},
|
|||
|
handleClick:()=>{ //button click event
|
|||
|
window.scratch.getProjectCover(cover => {
|
|||
|
//TODO got project cover
|
|||
|
})
|
|||
|
window.scratch.getProjectFile(file => {
|
|||
|
//TODO got project file
|
|||
|
})
|
|||
|
// got project name
|
|||
|
var projectName = window.scratch.getProjectName()
|
|||
|
console.log(projectName);
|
|||
|
}
|
|||
|
},
|
|||
|
//You can add more buttons
|
|||
|
]
|
|||
|
},
|
|||
|
blocks:{
|
|||
|
// block scale
|
|||
|
scale: 0.8,
|
|||
|
// hide block catagorys (catagory code see appendix)
|
|||
|
// window.vm.emitWorkspaceUpdate()
|
|||
|
hideCatagorys:[],
|
|||
|
//hide some blocks (block code see appendix)
|
|||
|
hideBlocks:[],
|
|||
|
},
|
|||
|
stageArea:{ //stage setting
|
|||
|
fullscreenButton:{ //fullscreen button
|
|||
|
show: true,
|
|||
|
handleBeforeSetStageUnFull(){ //拦截退出全屏,返回true继续执行
|
|||
|
return true
|
|||
|
},
|
|||
|
handleBeforeSetStageFull(){ //拦截全屏,返回true继续执行
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
startButton:{ //stat button
|
|||
|
show: true,
|
|||
|
handleBeforeStart(){
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
},
|
|||
|
stopButton:{ // stop button
|
|||
|
show: true,
|
|||
|
handleBeforeStop(){
|
|||
|
//handle before click button event, return 'true' to continue
|
|||
|
return true
|
|||
|
}
|
|||
|
}
|
|||
|
},
|
|||
|
//scratch vm initialized
|
|||
|
handleVmInitialized: (vm) => {
|
|||
|
window.vm = vm
|
|||
|
},
|
|||
|
//when create project or loaded project will call this function
|
|||
|
handleProjectLoaded:() => {
|
|||
|
},
|
|||
|
//when default project loaded will call this function
|
|||
|
handleDefaultProjectLoaded:() => {
|
|||
|
},
|
|||
|
//default project url
|
|||
|
defaultProjectURL: "./static/project.sb3",
|
|||
|
//assets library setting
|
|||
|
assets:{
|
|||
|
//asset host
|
|||
|
assetHost: './static',
|
|||
|
//asset index url
|
|||
|
defaultIndex:{
|
|||
|
sprites: "./static/json_index/sprites.json",
|
|||
|
costumes: "./static/json_index/costumes.json",
|
|||
|
backdrops: "./static/json_index/backdrops.json",
|
|||
|
sounds: "./static/json_index/sounds.json"
|
|||
|
},
|
|||
|
//handle before sprites library open
|
|||
|
handleBeforeSpriteLibraryOpen(){
|
|||
|
// append assets
|
|||
|
// window.scratch.pushSpriteLibrary(Arrays)
|
|||
|
return true;
|
|||
|
},
|
|||
|
//handle before costumes library open
|
|||
|
handleBeforeCostumesLibraryOpen(){
|
|||
|
return true;
|
|||
|
},
|
|||
|
//handle before backdrops library open
|
|||
|
handleBeforeBackdropsLibraryOpen(){
|
|||
|
return true;
|
|||
|
},
|
|||
|
//handle before sounds library open
|
|||
|
handleBeforeSoundLibraryOpen(){
|
|||
|
return true;
|
|||
|
}
|
|||
|
},
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
## API
|
|||
|
|
|||
|
### ScratchVm Object
|
|||
|
|
|||
|
It's scratch-vm instance object, You can call scratch virtual machine API from outside.
|
|||
|
|
|||
|
scratch-vm APIs:
|
|||
|
|
|||
|
- vm.saveProjectSb3()
|
|||
|
- vm.loadProject(file)
|
|||
|
- vm.greenFlag()
|
|||
|
- vm.stopAll()
|
|||
|
- vm.emitWorkspaceUpdate()
|
|||
|
- ……
|
|||
|
|
|||
|
[Scratch-vm document](./doc/scratch-vm/index.html)
|
|||
|
|
|||
|
### load project
|
|||
|
|
|||
|
`window.scratch.loadProject(url, callback)`
|
|||
|
|
|||
|
You can also use vm.loadProject
|
|||
|
|
|||
|
example
|
|||
|
```
|
|||
|
window.scratch.loadProject(url, ()=>{
|
|||
|
console.log("load project finished")
|
|||
|
})
|
|||
|
|
|||
|
```
|
|||
|
|
|||
|
### get project file
|
|||
|
|
|||
|
`window.scratch.getProjectFile(callback)`
|
|||
|
|
|||
|
You can also use vm.saveProjectSb3
|
|||
|
|
|||
|
example
|
|||
|
```
|
|||
|
window.scratch.getProjectFile((file)=>{
|
|||
|
console.log(file)
|
|||
|
//upload this file to server
|
|||
|
})
|
|||
|
```
|
|||
|
|
|||
|
### get project cover
|
|||
|
|
|||
|
`window.scratch.getProjectCover(callback)`
|
|||
|
|
|||
|
example
|
|||
|
```
|
|||
|
window.scratch.getProjectCover((file)=>{
|
|||
|
console.log(file)
|
|||
|
//upload this file to server
|
|||
|
})
|
|||
|
```
|
|||
|
|
|||
|
### get project name
|
|||
|
|
|||
|
`window.scratch.getProjectName()`
|
|||
|
|
|||
|
### set project name
|
|||
|
|
|||
|
`window.scratch.setProjectName(projectName)`
|
|||
|
|
|||
|
### set player only mode
|
|||
|
|
|||
|
example
|
|||
|
```js
|
|||
|
window.scratch.setPlayerOnly(true)
|
|||
|
```
|
|||
|
|
|||
|
### fullscreen mode
|
|||
|
|
|||
|
example
|
|||
|
```js
|
|||
|
window.scratch.setFullScreen(true)
|
|||
|
```
|
|||
|
|
|||
|
### append assets library
|
|||
|
|
|||
|
You can dynamically add the asset index to the library. You need to await user to open the asset library and then call this method.
|
|||
|
|
|||
|
The parameter is an array of assets indexes. See the files in 'josn_index' folder.
|
|||
|
|
|||
|
|
|||
|
#### append sprite assets
|
|||
|
`window.scratch.pushSpritesLibrary(Arrays)`
|
|||
|
|
|||
|
#### append costumes assets
|
|||
|
`window.scratch.pushCostumesLibrary(Arrays)`
|
|||
|
|
|||
|
#### append backdrops assets
|
|||
|
`window.scratch.pushBackdropsLibrary(Arrays)`
|
|||
|
|
|||
|
#### append sounds assets
|
|||
|
`window.scratch.pushSoundLibrary(Arrays)`
|
|||
|
|
|||
|
example
|
|||
|
```js
|
|||
|
window.scratch.pushSoundLibrary(
|
|||
|
[{
|
|||
|
"name": "My Custom Sound",
|
|||
|
"tags": [
|
|||
|
"music",
|
|||
|
],
|
|||
|
"assetId": "5cb46ddd903fc2c9976ff881df9273c9",
|
|||
|
"dataFormat": "",
|
|||
|
"md5ext": "5cb46ddd903fc2c9976ff881df9273c9.wav",
|
|||
|
"sampleCount": 11840,
|
|||
|
"rate": 44100
|
|||
|
}]
|
|||
|
)
|
|||
|
```
|
|||
|
|
|||
|
#### set cloud data ID
|
|||
|
`window.scratch.setCloudId(id)`
|
|||
|
|
|||
|
# Appendix
|
|||
|
|
|||
|
## block catagory code
|
|||
|
|
|||
|
motion looks sound events control sensing operators variables myBlocks
|
|||
|
|
|||
|
## block code
|
|||
|
|
|||
|
### motion
|
|||
|
|
|||
|
motion_movesteps motion_turnright motion_turnleft motion_goto motion_gotoxy motion_glideto
|
|||
|
motion_glidesecstoxy motion_pointindirection motion_pointtowards motion_changexby motion_setx
|
|||
|
motion_changeyby motion_sety motion_ifonedgebounce motion_setrotationstyle motion_xposition motion_yposition motion_direction
|
|||
|
|
|||
|
### looks
|
|||
|
|
|||
|
looks_sayforsecs looks_say looks_thinkforsecs looks_think looks_switchbackdropto looks_switchbackdroptoandwait looks_nextbackdrop
|
|||
|
looks_switchcostumeto looks_nextcostume looks_switchbackdropto looks_nextbackdrop looks_changesizeby looks_setsizeto looks_changeeffectby
|
|||
|
looks_seteffectto looks_cleargraphiceffects looks_show looks_hide looks_gotofrontback looks_goforwardbackwardlayers looks_backdropnumbername
|
|||
|
looks_costumenumbername looks_backdropnumbername looks_size
|
|||
|
|
|||
|
### sound
|
|||
|
|
|||
|
sound_playuntildone sound_play sound_stopallsounds sound_changeeffectby sound_seteffectto sound_cleareffects
|
|||
|
sound_changevolumeby sound_setvolumeto sound_volume
|
|||
|
|
|||
|
### event
|
|||
|
|
|||
|
event_whenflagclicked event_whenkeypressed event_whenstageclicked event_whenthisspriteclicked event_whenbackdropswitchesto
|
|||
|
event_whengreaterthan event_whenbroadcastreceived event_broadcast event_broadcastandwait
|
|||
|
|
|||
|
### control
|
|||
|
|
|||
|
control_wait control_repeat control_forever control_if control_if_else control_wait_until control_repeat_until control_stop
|
|||
|
control_create_clone_of control_start_as_clone control_create_clone_of control_delete_this_clone
|
|||
|
|
|||
|
### sensing
|
|||
|
|
|||
|
sensing_touchingobject sensing_touchingcolor sensing_coloristouchingcolor sensing_distanceto sensing_askandwait sensing_answer
|
|||
|
sensing_keypressed sensing_mousedown sensing_mousex sensing_mousey sensing_setdragmode sensing_loudness sensing_timer sensing_resettimer
|
|||
|
sensing_of sensing_current sensing_dayssince2000 sensing_username
|
|||
|
|
|||
|
### operator
|
|||
|
|
|||
|
operator_add operator_subtract operator_multiply operator_divide operator_random operator_gt operator_lt operator_equals operator_and
|
|||
|
operator_or operator_not operator_join operator_letter_of operator_length operator_contains operator_mod operator_round operator_mathop
|
|||
|
|
|||
|
|
|||
|
## player virtual keyboard example
|
|||
|
|
|||
|
first import jQuery
|
|||
|
|
|||
|
```js
|
|||
|
function regKeyEvent(selector, key, keyCode) {
|
|||
|
console.log("reg key event:" + key)
|
|||
|
$(selector).on("touchstart", function(event) {
|
|||
|
vm.postIOData("keyboard", {
|
|||
|
keyCode: keyCode,
|
|||
|
key: key,
|
|||
|
isDown: true,
|
|||
|
});
|
|||
|
event.preventDefault();
|
|||
|
});
|
|||
|
$(selector).on("touchend", function() {
|
|||
|
vm.postIOData("keyboard", {
|
|||
|
keyCode: keyCode,
|
|||
|
key: key,
|
|||
|
isDown: false,
|
|||
|
});
|
|||
|
event.preventDefault();
|
|||
|
});
|
|||
|
}
|
|||
|
|
|||
|
regKeyEvent(".button_space", " ", 32)
|
|||
|
regKeyEvent(".button_down", "ArrowDown", 40)
|
|||
|
regKeyEvent(".button_up", "ArrowUp", 38)
|
|||
|
regKeyEvent(".button_left", "ArrowLeft", 37)
|
|||
|
regKeyEvent(".button_right", "ArrowRight", 39)
|
|||
|
|
|||
|
```
|