當前項目需要用到Scratch3.0的二次開發,由於Scratch是由react開發,但是本開發項目前端框架爲vue,需要實現將gui繪製的sb3文件在vue項目中播放,配置如下:
1、需要在vue項目中引入以下包:
"scratch-vm": "0.2.0-prerelease.20191119203901",
"scratch-render": "0.1.0-prerelease.20191126210304",
"scratch-storage": "1.3.2",
"scratch-svg-renderer": "0.2.0-prerelease.20191104164753",
"scratch-audio": "0.1.0-prerelease.20190925183642",
"twgl.js": "4.4.0"
2、在代碼中導入相關組件
const ScratchRender = require('scratch-render/dist/web/scratch-render');
const VirtualMachine = require('scratch-vm/dist/web/scratch-vm');
const ScratchStorage = require('scratch-storage/dist/web/scratch-storage');
const ScratchSVGRenderer = require('scratch-svg-renderer/dist/web/scratch-svg-renderer');
const AudioEngine = require('scratch-audio/src/AudioEngine.js');
3、fetch下載文件並傳入到vm引擎中
let that = this;
let url = this.$http.adornUrl('/manager/sys/oss/downloadUrl/' + this.information.id);
fetch(url, {
method: 'POST'
}).then(res => res.blob().then(blob => {
window.devicePixelRatio = 1;
var canvas = document.getElementById('test');
var audioEngine = new AudioEngine();
var render = new ScratchRender(canvas);
var vm = new VirtualMachine();
var storage = new ScratchStorage();
var mockMouse = data => vm.runtime.postIOData('mouse', {
canvasWidth: canvas.width,
canvasHeight: canvas.height,
...data,
});
vm.attachAudioEngine(audioEngine);
vm.attachStorage(storage);
vm.attachRenderer(render);
vm.attachV2SVGAdapter(new ScratchSVGRenderer.SVGRenderer());
vm.attachV2BitmapAdapter(new ScratchSVGRenderer.BitmapAdapter());
this.vm = vm;
this.bindHandleKey();
var reader = new FileReader();
//byte爲blob對象
reader.readAsArrayBuffer(blob);
reader.onload = () => {
vm.start();
vm.loadProject(reader.result)
.then(() => {
that.loadFileTrue = true;
const div = document.createElement('div');
div.id='loaded';
document.body.appendChild(div);
});
};
}));
在項目中遇到的一些問題:
1、需要監控鼠標事件,以確保可以運行帶鍵盤事件的sb3文件
// 綁定鼠標事件
bindHandleKey() {
document.addEventListener('keydown', this.handleKeyDown);
document.addEventListener('keyup', this.handleKeyUp);
},
handleKeyDown (e) {
// Don't capture keys intended for Blockly inputs.
if (e.target !== document && e.target !== document.body) return;
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
this.vm.postIOData('keyboard', {
key: key,
isDown: true
});
// Prevent space/arrow key from scrolling the page.
if (e.keyCode === 32 || // 32=space
(e.keyCode >= 37 && e.keyCode <= 40)) { // 37, 38, 39, 40 are arrows
e.preventDefault();
}
},
handleKeyUp (e) {
// Always capture up events,
// even those that have switched to other targets.
const key = (!e.key || e.key === 'Dead') ? e.keyCode : e.key;
this.vm.postIOData('keyboard', {
key: key,
isDown: false
});
// E.g., prevent scroll.
if (e.target !== document && e.target !== document.body) {
e.preventDefault();
}
},
2、通過官方scratch-render項目的測試代碼,運行項目報錯vm No audio engine present;
需要引入AudioEngine包
3、sb3的運行與停止
vm.greenFlag(); // 運行
vm.stopAll(); // 停止所有