preface

First of all, this question was asked by a pretty little sister in the afternoon of June 6th, 2019.At that time, the answer was not very good. After going back in the evening, I had a rest and then began to implement it

Then began to check online to see what the idea of implementation no, the result of baidu turned over a few articles is not found what I want, I want a native implementation, because I can harvest something from it, as soon as possible to improve the front-end system, entry front end.

Since there is no reference, may be temporarily not found, then first according to my current thinking to write one. After really encountered, and then see how to achieve, contrast, and then learn.


Thinking to comb

  • First of all, communication needless to say, I guess this multiplayer game is definitely Websocket communication (and maybe better).
  • The drawing technology implementation must also be canvas
    • Thought 1: two core technologies have been determined, so now we start to draw this step, think about how to move the mouse (mobile terminal is the screen touch, I first try the IDEA of PC terminal) can show the effect on the drawing board?
    • Thought 2: How do I record this information? (Because that’s what webSocket sends)

Thought 1: How do I draw content on canvas

  • It must be closely related to listening for events. The idea is to constantly trigger events when the mouse moves under the inner canvas point, and then render the path based on the coordinate position in the event
  • But it turns out that canvas doesn’t listen for response events that move after the mouse is down (it probably does, but I can’t find it)
  • There is a simple curve to save the country: bind the mouse movement event in the mouse down event, and then unregister the mouse movement event in the mouse up event

      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <canvas id="canvas" width="500" height="500" style="border: 1px solid #999;"></canvas>


    <script>
        
        let canvas = document.getElementById('canvas')
        let cxt = canvas.getContext('2d')

        // Triggered when the mouse is pressed in the Canvas area
        canvas.onmousedown = (e) = > {

            cxt.strokeStyle = "#3d7e9a"
            cxt.beginPath() // Start setting the path
            cxt.moveTo(e.clientX, e.clientY) // Path origin
            
            // Mouse movement events
	   canvas.onmousemove = (e) = > {
                cxt.lineTo(e.clientX, e.clientY) // Path end
                cxt.stroke() // Output path outline (hollow)}}Trigger when the mouse is raised in the Canvas area
        canvas.onmouseup = (a)= > {
            canvas.onmousemove = null
        }
        
    </script>

</body>
</html>
Copy the code

Implementation effect (Gif Gif) 💝


Thought 2: How do I record this information? (No, I need to record what information)

  • I thought about what information I should record 🤔, which other apis probably don’t, and what I can see is that I can get information about every point in the movement
  • If you write down the coordinates of every point, and send this, it should be fine
  • After practice, I found that it is almost impossible to record the information sent from each point. One is that the number is increasing, and the other is that should we empty the canvas and redraw it every time? I’m stupid too!
  • 🔥 and then to think of another way, is when the mouse is pressed, to lift this period of time to move the point, are recorded, and then when the mouse is lifted and then send data, so that each time the data is smaller, and then other users there do not have to empty the canvas
  • The concrete implementation is as follows, the following has the ➕ symbol, indicating that is the new content
<! -- 🔥 practice -->


      
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>

    <canvas id="canvas" width="400" height="400" style="border: 1px solid #999;"></canvas>
    <! -- ➕ impersonates another user -->
    <canvas id="canvas2" width="400" height="400" style="border: 1px solid blue;"></canvas>

    <script>
        
        let canvas = document.getElementById('canvas')
        let cxt = canvas.getContext('2d')
        let dotArr = [] // ➕ stores the location information of the moving point between each press and lift

        // Triggered when the mouse is pressed in the Canvas area
        canvas.onmousedown = (e) = > {

            cxt.strokeStyle = "#3d7e9a"
            cxt.beginPath() // Start setting the path
            cxt.moveTo(e.clientX, e.clientY) // Path origin
            
            // ➕ first empty the array, then record the first position data as the path origin coordinates
            dotArr.length = 0;
            dotArr.push({x: e.clientX,y: e.clientY})
            
            // Mouse movement events
	   canvas.onmousemove = (e) = > {
                cxt.lineTo(e.clientX, e.clientY) // Path end
                cxt.stroke() // Output path outline (hollow)
                
                // ➕ records information about each point in the movement
                dotArr.push({x: e.clientX,y: e.clientY})
	   }
	   
        }
        
        Trigger when the mouse is raised in the Canvas area
        document.onmouseup = (a)= > {
            canvas.onmousemove = null
            
            // ➕ pretend to send the data and let the second diagram start drawing
            renderCanvas()
        }
        
        // ➕ one-to-many publish subscription, suitable for publish subscriber model, here is one first
        function renderCanvas() {
            
            let canvas2 = document.getElementById('canvas2')
            let cxt2 = canvas2.getContext('2d')

            cxt2.beginPath() // Start setting the path
            cxt2.moveTo(dotArr[0].x, dotArr[0].y) // Path origin

            for (let i = 1, len = dotArr.length; i < len; i++) {
                cxt2.lineTo(dotArr[i].x, dotArr[i].y) // Path focus
                cxt2.stroke() // Output path outline (hollow)}}</script>

</body>
</html>
Copy the code

Implementation effect (Gif Gif) 💝


Thought 3: How to implement the Websocket part

Writing in the…


Thinking four: if the user draws for an hour, what will be the problem, how to solve it?


Thought 5: Can you think of any other possible problems? Or possible optimizations?


Thought 6: Can I use tensorflow. js to implement a simple AI that recognizes what I’m drawing? (This is not the same as the original question, but purely out of personal interest, can try)


Thought 7: Problems encountered

  • Problems with point location and viewport location (visual solution)
  • If the mouse moves out of the canvas and then releases the mouse, the canvas can’t listen to it, so it can’t cancel the event (✅ mouse lift event is bound to document to solve this problem).

Afterword.

After almost all the implementation, I’m going to pull out the reusable module, save the next time to write again

This article belongs to personal notes, if possible do not recommend ah, or very embarrassing

I found out the Nuggets have a draw me guess implementation article, go back and read it tonight