user2978798
user2978798

Reputation: 25

Canvas fix drawing points

I have create a drawing canvas. In javascript. But when i move my mouse fast i haven't a full line but a line with points. I have used an arc for this i dont know of there is a better option for painting a line

How can i fix this ??

already thanks

<script type="application/javascript" src="jquery.js"></script>
<script>

    var canvas;
    var ctx;
    var StartDraw = false;
    var dikte = 7;

$(document).ready(DoInit());



    function DoInit()
    {
         canvas = document.getElementById("canvas");
         ctx = canvas.getContext('2d');

        $(".kleur").on('click',doKleur);
        $("canvas").on('mouseup',DoUp);
        $("canvas").on('mousedown',DoDown);
        $("canvas").on('mousemove',DoMove)
        $("#dikte").on('change',doDikte);
        $(".clear").on('click',clear);
    }



    function doDikte(){
        dikte  = this.value;
    }

    function clear(){

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



    function doKleur(){
        ctx.fillStyle = this.id;


    }

    function DoDown()
    {
        StartDraw = true;
    }
    function DoUp()
    {
        StartDraw = false;
    }

    function DoDot(x,y)
    {

            ctx.beginPath();
            ctx.arc(x, y, dikte, 0, Math.PI * 2, false);

            ctx.closePath();
            ctx.fill();

    }

    function DoMove(event)
    {

        if(StartDraw)
        {

            DoDot(event.offsetX, event.offsetY)
        }

    }




</script>
<style>
    canvas
    {
        border: solid 5px red;
        border-radius: 15px;
    }
</style>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<canvas id="canvas" width="1000" height="650"></canvas>
<input class="kleur" type="button" id="blue" value="blauw">
<input class="kleur" type="button" id="green" value="groen">
<input class="kleur" type="button" id="red" value="rood">
<input class="kleur" type="button" id="black" value="zwart">
<input class="kleur" type="button" id="orange" value="oranje">
<input type="button" class="clear" value="clear">
<input type="range" id="dikte" min="1" max="35" value="7">
</body>
</html>

Upvotes: 0

Views: 174

Answers (1)

Blindman67
Blindman67

Reputation: 54026

You need to check when the mouse has just been clicked, is being held, when it released, or is just a quick click. You need to draw line segments when the mouse is being dragged, or just a point if its a quick click.

I prefer to bundle all my mouse events into one function and I create an abstract mouse object that I then use for whatever needs I have.

When I handle a mouse event, be that a move or click, whatever it is the last thing I do is save the button state. That means that next time the mouse event is called I know by checking the last and current mouse button state if the button was just clicked, is being held, or just up. You may say that the mousedown and mouseup events do that for you already, and yes they do and there is no reason for you not to use them. I just find it easier in the long run, as I can manipulate the mouse state.

So then when the mouse first goes down, record the coordinates, then when the mouse moves, draw a line from the last coordinate to the new one. When the mouse button goes up then do a quick check to see if it is just a point to draw and draw it if so, else do nothing.

Here is an example. The mouse code is at the bottom with mouse.buttonRaw being a bit field of the current mouse button state where first bit is left, second is middle, and third is right.

var mouse;
document.body.innerHTML = "Use mouse to draw on the this snippet.";
var demo = function(){

    var canvas = (function(){
        var canvas = document.getElementById("canv");
        if(canvas !== null){
            document.body.removeChild(canvas);
        }
        // creates a blank image with 2d context
        canvas = document.createElement("canvas"); 
        canvas.id = "canv";    
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight; 
        canvas.style.position = "absolute";
        canvas.style.top = "0px";
        canvas.style.left = "0px";
        canvas.style.zIndex = 1000;
        canvas.ctx = canvas.getContext("2d"); 
        document.body.appendChild(canvas);
        return canvas;
    })();
    var ctx = canvas.ctx;
    

    if(mouse !== undefined){  // if the mouse exists 
        mouse.removeMouse(); // remove previous events
    }
    var canvasMouseCallBack = undefined;  // if needed
    // my mouse handler has more functionality than needed but to lazy to clean it ATM
    mouse = (function(){
        var mouse = {
            x : 0, 
            y : 0,
            w : 0, 
            alt : false, 
            shift : false, 
            ctrl : false,
            interfaceId : 0, 
            buttonLastRaw : 0,  
            buttonRaw : 0,
            over : false,  // mouse is over the element
            bm : [1, 2, 4, 6, 5, 3], // masks for setting and clearing button raw bits;
            getInterfaceId : function () { return this.interfaceId++; }, // For UI functions
            startMouse:undefined,
            mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",")
        };
        function mouseMove(e) {
            var t = e.type, m = mouse;
            m.x = e.offsetX; 
            m.y = e.offsetY;
            if (m.x === undefined) { m.x = e.clientX; m.y = e.clientY; }

            m.alt = e.altKey;
            m.shift = e.shiftKey;
            m.ctrl = e.ctrlKey;
            if (t === "mousedown") { m.buttonRaw |= m.bm[e.which-1];
            } else if (t === "mouseup") { m.buttonRaw &= m.bm[e.which + 2];
            } else if (t === "mouseout") { m.buttonRaw = 0; m.over = false;
            } else if (t === "mouseover") { m.over = true;
            } else if (t === "mousewheel") { m.w = e.wheelDelta;
            } else if (t === "DOMMouseScroll") { m.w = -e.detail;}
            // call mouse callback if set
            if (canvasMouseCallBack) { canvasMouseCallBack(mouse); }
            e.preventDefault();
        }
        // function to add events to element
        function startMouse(element){
            if(element === undefined){
                element = document;
            }
            mouse.element = element;
            mouse.mouseEvents.forEach(
                function(n){
                    element.addEventListener(n, mouseMove);
                }
            );
            element.addEventListener("contextmenu", function (e) {e.preventDefault();}, false);
        }
        // function to remove events
        mouse.removeMouse = function(){
            if(mouse.element !== undefined){
                mouse.mouseEvents.forEach(
                    function(n){
                        mouse.element.removeEventListener(n, mouseMove);
                    }
                );
                canvasMouseCallBack = undefined;
            }
        }
        mouse.mouseStart = startMouse;
        return mouse;
    })();
    // if there is a canvas add the mouse event else add to document
    if(typeof canvas !== "undefined"){
        mouse.mouseStart(canvas);
    }else{
        mouse.mouseStart();
    }


    // for the previouse mouse state
    var lastMouseButton = 0;
    var x,y,xx,yy; //for saving line segments drawn
    // set up drawing
    ctx.fillStyle = "red";
    ctx.strokeStyle = "red";
    ctx.lineWidth = 10;
    ctx.lineJoin = "round";
    ctx.lineCap = "round";
    // set the mouse callback function. It is called for every mouse event
    canvasMouseCallBack = function(mouse){
        // is the first (left) button down and the last button state up?
        if((mouse.buttonRaw & 1) === 1 && (lastMouseButton & 1) === 0){
            x = mouse.x;  // save the mouse coordinates
            y = mouse.y;
        }else
        // is both the mouse button down and the last one down 
        if((mouse.buttonRaw & 1) === 1 && (lastMouseButton & 1) === 1){
            xx = x;  // yes move the last coordinate to the 
            yy = y;  // start of the line segment
            x = mouse.x;  // get the mouse coords for the end of the line seg
            y = mouse.y;
            ctx.beginPath();  // draw the line segment
            ctx.moveTo(x,y);
            ctx.lineTo(xx,yy);
            ctx.stroke();
        }else
        // has the mouse just been released
        if( (mouse.buttonRaw  & 1) === 0 && (lastMouseButton & 1) === 1){
            if(xx === undefined){  // if xx is undefined then no line segment 
                                   // has been drawn so need to ad just a point
                ctx.beginPath();  // draw a point at the last mouse point
                ctx.arc(x,y,5,0,Math.PI*2);
                ctx.fill();
            }
            xx = undefined;  // clear the line segment start
            
        }
        // save the last mouse start
        lastMouseButton = mouse.buttonRaw;
    }
}
// resize demo to fit window if needed
window.addEventListener("resize",demo);
// start the demo
demo();

You may also be interested in this answer that deals with drawing as well but demonstrates how to smooth a line being draw as the mouse input can be very dirty. Smooth a line

Upvotes: 1

Related Questions