Reputation: 25
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
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