🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
``` <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> ```