Вы должны проверить, когда мышь только что была нажата, проводится, когда она отпущена, или просто быстрый щелчок. Вам нужно нарисовать сегменты линии, когда мышь перетаскивается, или просто точка, если ее быстрый щелчок.
Я предпочитаю связывать все события мыши в одной функции, и я создаю абстрактный объект мыши, который затем использую для любых моих нужд.
Когда я обрабатываю событие мыши, будь то движение или клик, что бы я ни делал, это сохранить состояние кнопки. Это означает, что в следующий раз, когда вызывается событие мыши, я знаю, проверяя последнее и текущее состояние кнопки мыши, если кнопка была просто нажата, удерживается или просто вверх. Вы можете сказать, что события и mouseup
делают это для вас уже, и да, они делают, и нет причин для вас не использовать их. Мне просто легче в долгосрочной перспективе, так как я могу манипулировать состоянием мыши.
Итак, когда мышь сначала опускается, запишите координаты, затем, когда мышь перемещается, нарисуйте линию от последней координаты до новой. Когда кнопка мыши идет вверх, сделайте быструю проверку, чтобы увидеть, является ли это просто точкой для рисования и нарисуйте ее, если так, иначе ничего не делайте.
Вот пример. Код мыши находится внизу: mouse.buttonRaw
- бит поля текущего состояния кнопки мыши, где первый бит оставлен, второй - средний, а третий справа.
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();
Вы также можете быть заинтересованы в этом ответе, который имеет дело с рисованием как хорошо, но демонстрирует, как сгладить линии, как прорисовывается как вход мышь может быть очень грязно. Smooth a line
Как насчет использования линий вместо дуг? Вы можете установить 'context.lineCap = 'round'', чтобы помочь каждой отдельной линии объединиться. – markE