You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 09:06:36