如何使用Vue与Socket.IO实时刷新Canvas中对象的位置?
问题描述
我用Vue.js和Socket.IO开发2D乒乓球游戏,Canvas里的黑色矩形想跟随鼠标移动。控制台显示坐标正确,但矩形只有页面刷新时才会变化,按钮移动功能正常(本次未使用)。
Vue组件代码(BlockGame.vue)
<template> <div> <canvas @mousemove="mouseMove" ref="game" width="640" height="480" style="border: 1px solid black;"> </canvas> <p style="display: flex; justify-content: space-around;"> <button v-on:click="move('right')">Right</button> <button v-on:click="move('left')">Left</button> <button v-on:click="move('up')">Up</button> <button v-on:click="move('down')">Down</button> </p> </div> </template> <script> import io from "socket.io-client"; export default { name: 'BlockGame', data() { return { socket: {}, context: {}, position: { x: 0, y: 0 } } }, created() { this.socket = io("http://localhost:3000"); }, mounted() { this.context = this.$refs.game.getContext("2d"); this.socket.on("position", data => { this.position = data; console.log(data); this.context.clearRect(0, 0, this.$refs.game.width, this.$refs.game.height) console.log("mounted pos:" + this.position.x, this.position.y); this.context.fillRect(this.position.x, this.position.y, 20, 20); }); }, methods: { move(direction) { this.socket.emit("move", direction); }, mouseMove() { this.socket.emit("mouseMove", event.clientX, event.clientY) console.log("event pos:" + event.clientX, event.clientY); console.log("position pos:" + this.position.x, this.position.y); } } } </script> <style scoped> </style>
服务器代码(app.js)
const Express = require("express"); const Http = require("http").Server(Express); const SocketIo = require("socket.io")(Http, { cors: { origin: "http://localhost:8080", methods: ["GET", "POST"] } }); var position = { x: 200, y: 200 } SocketIo.on("connection", socket => { socket.emit("position", position) socket.on("move", data => { switch(data) { case "left": if (position.x - 5 < 0) position.x = 0; else position.x -= 5; SocketIo.emit("position", position); break; case "right": if (position.x + 5 >= 620) position.x = 620; else position.x += 5; SocketIo.emit("position", position); break; case "up": if (position.y - 5 < 0) position.y = 0; else position.y -= 5; SocketIo.emit("position", position); break; case "down": if (position.y + 5 >= 460) position.y = 460; else position.y += 5; SocketIo.emit("position", position); break; } }) socket.on("mouseMove", (mousePosx, mousePosy) => { position.x = mousePosx; console.log("mousePosx:" + mousePosx) position.y = mousePosy; console.log("mousePosy:" + mousePosy) console.log("POSITIONposx:" + position.x) console.log("POSITIONposy:" + position.y) }) }); Http.listen(3000, () => { console.log("Listening at: 3000..."); })
解决方案
1. 服务器端:更新位置后广播给客户端
mouseMove事件处理中,只更新了服务器的position变量,但没有像move事件那样推送新位置给客户端。修改服务器代码的mouseMove部分:
socket.on("mouseMove", (mousePosx, mousePosy) => { position.x = mousePosx; console.log("mousePosx:" + mousePosx) position.y = mousePosy; console.log("mousePosy:" + mousePosy) console.log("POSITIONposx:" + position.x) console.log("POSITIONposy:" + position.y) // 新增:广播更新后的位置给所有客户端 SocketIo.emit("position", position); })
2. 客户端:修复鼠标事件参数问题
当前mouseMove方法未接收事件对象,直接使用event会导致全局变量污染或报错。修改Vue组件的mouseMove方法:
mouseMove(event) { // 接收事件参数 this.socket.emit("mouseMove", event.clientX, event.clientY) console.log("event pos:" + event.clientX, event.clientY); console.log("position pos:" + this.position.x, this.position.y); }
额外优化:修正Canvas坐标偏移
event.clientX/Y是相对于浏览器视口的坐标,可能存在偏移。改用event.offsetX/Y获取相对于Canvas自身的坐标:
mouseMove(event) { this.socket.emit("mouseMove", event.offsetX, event.offsetY) console.log("event pos:" + event.offsetX, event.offsetY); console.log("position pos:" + this.position.x, this.position.y); }
内容的提问来源于stack exchange,提问作者elaachac
相关产品推荐
相关产品推荐

