javascriptcanvaslineto

Issue with canvas straight lines


This canvas have been creating an error since I created it and I haven't found a solution after all my research. so I need a hand. I need the canvas to create a straight line but it end up creating multiple straight lines from the starting point when the mouse is moving instead of one straight line.

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]>      <html class="no-js"> <!--<![endif]-->
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="">
    </head>

    <style>
        *{
            box-sizing: border-box;
        }

        body,html{
            padding: 0;
            margin: 0;
            height: 100vh;
            width: 100vw;
        }


    </style>
    <body>
       
        <canvas>
            
        </canvas>
        
        <script>
            var colorLine = 'black'
            var fillLine = 'none'
            var prevX = ''
            var prevY = ''
            var isDrawing = false
            var snapshot;
            var canvas = document.querySelector('canvas');
            var ctx = canvas.getContext('2d');

            
            let backgroundSetUp = () => {
                
                canvas.height = window.innerHeight - 50; 
                canvas.width = window.innerWidth - 50;
                ctx.fillStyle = colorLine;
                ctx.fillStyle = fillLine
            };

            let startDrawing = e => {
                isDrawing = true
                
                prevX = e.offsetX 
                prevY = e.offsetY 
                ctx.beginPath();
                ctx.strokeStyle  = 'black'
                ctx.fillStyle = '#fff'
           
            }

            let Drawing = e => {
                if(isDrawing === false)
                return
                ctx.beginPath();
                ctx.moveTo(prevX, prevY);
                ctx.lineTo(e.offsetX, e.offsetY);
                ctx.stroke()

                
            }

            let stopDrawing = e => {
                isDrawing = false
            }






            canvas.onmousedown = ( e => {
                startDrawing(e)
            })
            canvas.onmousemove = ( e => {
                Drawing(e)
            })
            canvas.onmouseup = ( e => {
                stopDrawing(e)
            })

            backgroundSetUp()


        </script>
    </body>
</html>


Solution

  • You should clear your canvas drawing before you do another draw:

    ctx.clearRect( 0, 0, canvas.width, canvas.height );
    

    This will reset the canvas before you draw your 'corrected' line to the new mouse position. If you want to draw further lines you will need another canvas with a copy of the previous drawing, and draw it back into the output canvas instead of using clear.

    var colorLine = 'black'
    var fillLine = 'none'
    var prevX = ''
    var prevY = ''
    var isDrawing = false
    var snapshot;
    var canvas = document.querySelector('canvas');
    var ctx = canvas.getContext('2d');
    
    
    let backgroundSetUp = () => {
        canvas.height = window.innerHeight - 50; 
        canvas.width = window.innerWidth - 50;
        ctx.fillStyle = colorLine;
        ctx.fillStyle = fillLine
    };
    
    let startDrawing = e => {
        isDrawing = true
        prevX = e.offsetX 
        prevY = e.offsetY;
        ctx.beginPath();
        ctx.strokeStyle  = 'black'
        ctx.fillStyle = '#fff'
    
    }
    
    let Drawing = e => {
        if(isDrawing === false) return
        // This is where you redraw or clear the previous canvas
        ctx.clearRect( 0, 0, canvas.width, canvas.height );
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(e.offsetX, e.offsetY);
        ctx.stroke()
    }
    
    let stopDrawing = e => {
        isDrawing = false
    }
    
    
    
    
    
    
    canvas.onmousedown = ( e => {
        startDrawing(e)
    })
    canvas.onmousemove = ( e => {
        Drawing(e)
    })
    canvas.onmouseup = ( e => {
        stopDrawing(e)
    })
    
    backgroundSetUp()
    <canvas></canvas>

    Here is one with a buffer instead, allowing you to continue drawing after the first line. I have also cleaned up some of your definitions (correctly using const and let, ignoring var and using function where it makes sense to create a little more concise and clear code):

    function onResize(){
    
        canvas.height = window.innerHeight - 50; 
        canvas.width = window.innerWidth - 50;
        
        ctx.fillStyle = colorLine;
        ctx.fillStyle = fillLine;
        
    }
    function onPointerStart( e ){
      
        // Write the current state into the buffer when we start
        buffer.width = canvas.width;
        buffer.height = canvas.height;
        bufferCtx.drawImage( canvas, 0, 0 );
        
        isDrawing = true;
        prevX = e.offsetX;
        prevY = e.offsetY;
        ctx.beginPath();
        ctx.strokeStyle  = 'black';
        ctx.fillStyle = '#fff';
    
    }
    function onPointerMove( e ){
    
        if( isDrawing === false ) return;
        
        // Clear the screen, redraw the buffer into it
        ctx.clearRect( 0, 0, canvas.width, canvas.height );
        ctx.drawImage( buffer, 0, 0 );
        
        // Draw your path
        ctx.beginPath();
        ctx.moveTo(prevX, prevY);
        ctx.lineTo(e.offsetX, e.offsetY);
        ctx.stroke();
        
    }
    function onPointerEnd( e ){
    
        isDrawing = false;
        
    }
    
    const canvas = document.querySelector('canvas');
    const ctx = canvas.getContext('2d');
    
    // This will be our buffer
    const buffer = document.createElement('canvas');
    const bufferCtx = buffer.getContext('2d');
    
    let colorLine = 'black';
    let fillLine = 'none';
    let prevX = 0;
    let prevY = 0;
    let isDrawing = false;
    let snapshot;
    
    window.addEventListener( 'mousedown', onPointerStart );
    window.addEventListener( 'mousemove', onPointerMove );
    window.addEventListener( 'mouseup', onPointerEnd );
    window.addEventListener( 'resize', onResize );
    
    onResize()
    <canvas></canvas>