```
<template>
<div>
<canvas
id="scratch-stage"
:width="width"
:height="height"
:style="{width:width+'px',height:height+'px'}"
></canvas>
<div v-if="showOperationButton">
<ButtonGroup>
<Button type="primary" @click="play">播放</Button>
<Button type="error" @click="stop">停止</Button>
</ButtonGroup>
</div>
</div>
</template>
<script>
//@/compentents/ScratchPlayer.vue
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");
export default {
name: "ScratchPlayer",
props: {
url: {
type: String,
default: "http://127.0.0.1:8360/static/Scratch.sb3"
},
showOperationButton: {
type: Boolean,
default: true
},
autoPlay: {
type: Boolean,
default: true
},
width: {
type: Number,
default: 480
},
height: {
type: Number,
default: 360
}
},
watch: {
url(value) {
//监听属性的变化
if (value) {
this.loadBlock(value);
}
}
},
mounted() {
this.loadBlock(this.url);
},
methods: {
play() {
this.vm.greenFlag(); //开始播放动画
},
stop() {
this.vm.stopAll(); //停止动画播放
},
loadBlock(url) {
// let url = "http://127.0.0.1:8360/static/Scratch.sb3";
fetch(url, {}).then(res =>
res.blob().then(blob => {
// console.log(res);
window.devicePixelRatio = 1;
var canvas = document.getElementById("scratch-stage");
var audioEngine = new AudioEngine();
var render = new ScratchRender(canvas);
var vm = new VirtualMachine();
var storage = new ScratchStorage();
vm.attachAudioEngine(audioEngine);
vm.attachStorage(storage);
vm.attachRenderer(render);
vm.attachV2SVGAdapter(new ScratchSVGRenderer.SVGRenderer());
vm.attachV2BitmapAdapter(new ScratchSVGRenderer.BitmapAdapter());
this.vm = vm;
// Feed mouse events as VM I/O events.
document.addEventListener("mousemove", e => {
const rect = canvas.getBoundingClientRect();
const coordinates = {
x: e.clientX - rect.left,
y: e.clientY - rect.top,
canvasWidth: rect.width,
canvasHeight: rect.height
};
this.vm.postIOData("mouse", coordinates);
});
canvas.addEventListener("mousedown", e => {
const rect = canvas.getBoundingClientRect();
const data = {
isDown: true,
x: e.clientX - rect.left,
y: e.clientY - rect.top,
canvasWidth: rect.width,
canvasHeight: rect.height
};
this.vm.postIOData("mouse", data);
e.preventDefault();
});
canvas.addEventListener("mouseup", e => {
const rect = canvas.getBoundingClientRect();
const data = {
isDown: false,
x: e.clientX - rect.left,
y: e.clientY - rect.top,
canvasWidth: rect.width,
canvasHeight: rect.height
};
this.vm.postIOData("mouse", data);
e.preventDefault();
});
// Feed keyboard events as VM I/O events.
document.addEventListener("keydown", e => {
// Don't capture keys intended for Blockly inputs.
if (e.target !== document && e.target !== document.body) {
return;
}
this.vm.postIOData("keyboard", {
keyCode: e.keyCode,
isDown: true
});
e.preventDefault();
});
document.addEventListener("keyup", e => {
// Always capture up events,
// even those that have switched to other targets.
this.vm.postIOData("keyboard", {
keyCode: e.keyCode,
isDown: false
});
// E.g., prevent scroll.
if (e.target !== document && e.target !== document.body) {
e.preventDefault();
}
});
var reader = new FileReader();
//byte为blob对象
reader.readAsArrayBuffer(blob);
reader.onload = () => {
vm.start();
vm.loadProject(reader.result).then(() => {
if (this.autoPlay) {
//自动播放
vm.greenFlag();
}
});
};
})
);
}
}
};
</script>
```
调用代码:
```
<template>
<div class="home">
<ScratchPlayer
:src="scratchFileUrl"
:width="600"
:height="480"
:autoPlay="true"
:showOperationButton="true"
/>
</div>
</template>
<script>
// @ is an alias to /src
import ScratchPlayer from "@/components/ScratchPlayer.vue";
export default {
name: "Home",
components: {
ScratchPlayer
},
data() {
return {
scratchFileUrl: "http://127.0.0.1:8360/static/Scratch.sb3"
};
}
};
</script>
```