使用 WebSocket 实现你画我猜实时绘图

0 点赞
0 条评论
2005 次浏览
发布于 10 个月前

你画我猜大家应该都玩过,一个人画,其他人猜,首先分析整体架构部分:


可以看到,整体架构非常简单,仅仅是一台服务器和两个客户端。

  • WebSocket服务器:提供绘图同步功能,使用nodejs写成。

  • 绘图画布:进行绘图的区域,将绘制的数据传输到猜图画布中。

  • 猜图画布:同步自绘图画布,将接收的绘图数据绘制到画布中。

1、服务端代码

// 导入WebSocket模块:
const WebSocket = require('ws');

// 引用Server类:
const WebSocketServer = WebSocket.Server;

// 实例化:
const wsInstance = new WebSocketServer({
  port: 9999
});

wsInstance.on('connection', ws => {
  console.log(`[SERVER] connection()`);
  ws.on('message', function (message) {
    console.log(`[SERVER] Received: ${message}`);

    wsInstance.clients.forEach((client) => {
      client.send(message)
    })
  })
});

2、绘制页面代码

<template>
  <canvas
    ref="drawBoard"
    width="700"
    height="400"
    @mousedown="onCanvasMousedown"
    @mousemove="onCanvasMousemove"
    @mouseup="onCanvasMouseup"
    style="border: 1px solid #000;"
  />
</template>
<script type="text/javascript">
  export default {
    data() {
      return {
        stageInfo: {
          top: 0,
          left: 0,
          right: 0,
          bottom: 0
        },
        wsInstance: null,
        canvasContext: null,
        isDraw: false
      }
    },
    methods: {
      init() {
        this.wsInstance = new WebSocket('ws://localhost:9999')
        this.$nextTick(() => {
          const canvasInstance = this.$refs.drawBoard
          this.canvasContext = canvasInstance.getContext('2d')
          this.stageInfo = canvasInstance.getBoundingClientRect()
        })
      },
      onCanvasMousedown(event) {
        const {canvasContext, stageInfo, wsInstance} = this
        if (!canvasContext) return false

        const beginX = event.pageX - stageInfo.left
        const beginY = event.pageY - stageInfo.top

        const strokeStyle = '#' + '0123456789abcdef'.split('').map((v, i, a) => i > 5 ? null : a[Math.floor(Math.random() * 16)]).join('')

        const lineWidth = (Math.random() * 10 + 1).toFixed(0)

        canvasContext.strokeStyle = strokeStyle
        canvasContext.lineWidth = lineWidth

        canvasContext.beginPath()
        canvasContext.moveTo(beginX, beginY)
        this.isDraw = true

        const params = {
          methods: [{
            name: 'beginPath'
          }, {
            name: 'moveTo',
            data: [beginX, beginY]
          }],
          attrs: [{
            name: 'strokeStyle',
            data: strokeStyle
          }, {
            name: 'lineWidth',
            data: lineWidth
          }]
        }
        wsInstance.send(JSON.stringify(params))
      },
      onCanvasMousemove(event) {
        const {isDraw, canvasContext, stageInfo, wsInstance} = this
        if (!isDraw) return false
        if (!canvasContext) return false

        const endX = event.pageX - stageInfo.left
        const endY = event.pageY - stageInfo.top
        canvasContext.lineTo(endX, endY)
        canvasContext.stroke()

        const params = {
          methods: [{
            name: 'lineTo',
            data: [endX, endY]
          }, {
            name: 'stroke'
          }]
        }
        wsInstance.send(JSON.stringify(params))
      },
      onCanvasMouseup() {
        this.isDraw = false
      }
    },
    created() {
      this.init()
    }
  }
</script>
<style lang="scss" type="text/scss" rel="stylesheet/scss">
</style>

3、猜图页面代码

<template>
  <canvas
    ref="drawBoard"
    width="700"
    height="400"
    style="border: 1px solid #000;"
  />
</template>
<script type="text/javascript">
  export default {
    data() {
      return {
        canvasContext: null,

        isDraw: true
      }
    },
    methods: {
      draw(methods = [], attrs = []) {
        const {canvasContext} = this
        if (!canvasContext) return false

        attrs.length && attrs.forEach(({name, data}) => {
          canvasContext[name] = data
        })
        methods.length && methods.forEach(({name, data}) => {
          const canvasAction = canvasContext[name]
          if (canvasAction) canvasAction.apply(canvasContext, data || [])
        })
      },
      init() {
        const {$nextTick, draw} = this
        const wsInstance = new WebSocket('ws://localhost:9999')
        $nextTick(() => {
          const canvasInstance = this.$refs.drawBoard
          const canvasContext = canvasInstance.getContext('2d')

          this.canvasContext = canvasContext

          wsInstance.onmessage = ({data}) => {
            const {methods, attrs} = JSON.parse(data) || {}

            draw(methods, attrs)
          }
        })
      }
    },
    created() {
      this.init()
    }
  }
</script>
<style lang="scss" type="text/scss" rel="stylesheet/scss">
</style>


源码地址:https://github.com/imingdev/guess-draw

版权所属:开发日记
转载时必须以链接形式注明原始出处及本声明。
"赞助我们,我们才能做的更多&更好"
赞助支持
还没有评论
写下你的评论...