Динамическое рисование на холсте

1

Я пытаюсь создать простую, чисто JS-программу для рисования на холсте. У меня есть приемлемое решение прямо сейчас, но если я рисую очень быстро, мое рисовальное перо не является непрерывным, и я получаю разбросанные круги, возможно, потому, что компьютер не может идти в ногу с темпом.

var draw = false;

function yesDraw() {
  draw = true;
}

function mouseCoordinates(e) {
  if (draw) {
    var x = e.offsetX;
    var y = e.offsetY;
    drawing(x, y);
  }
}

function noDraw() {
  draw = false;
}
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

function drawing(x, y) {
  ctx.beginPath();
  ctx.arc(x, y, 10, 0, 2 * Math.PI);
  ctx.fillStyle = "black";
  ctx.fill();
}
<canvas id="myCanvas" height="400" ; width="1000" onmousedown="yesDraw()" onmousemove="mouseCoordinates(event)" onmouseup="noDraw()" onmouseout="noDraw()" style="border: solid 1px black;">Your browser does not support canvas.</canvas>

Есть ли способ получить непрерывный поток чертежа и сохранить его на 100% JS?

Теги:
canvas
drawing

2 ответа

0
Лучший ответ

Линейные сегменты из предыдущей позиции мыши.

Вместо того, чтобы рисовать дуги, отрисуйте отрезки от предыдущей позиции мыши до новой. Поскольку вы не хотите, чтобы линия была нарисована с конца предыдущего розыгрыша, вам также необходимо указать, когда начинается новая строка, и установить предыдущую позицию мыши на текущую мышь.

Для этого я добавил 3 переменные lineStart, lastX и lastY

lineStart имеет значение true, когда срабатывает событие мыши. В функции рисования, если начало строки истинно, в lastX и lastY значениях установлены значения x, y и lineStart равно false. lastX, lastY удерживайте предыдущую позицию мыши. Они устанавливаются в x, y в конце каждого вызова ничьей.

Сегменты линий должны иметь свойства 2D-контекста ctx.lineWidth заданные для ширины линии. Чтобы линия была непрерывной, свойство ctx.lineCap имеет значение "round". Это добавляет полукругу к началу и концу строки.

Пройдя мимо края

Если ручка выключится, когда мышь выйдет, это раздражает, вы делаете это, потому что, если вы не потеряете события мыши, а мышь продолжает рисовать с помощью мыши.

Если вы добавите мышь в document а не в холст, вам не придется беспокоиться о том, что мышь выходит за рамки рамки. Вы по-прежнему будете получать события мыши, даже если мышь полностью связана с вкладкой и браузером.

Хотя вам придется использовать несколько иной способ получить координаты мыши, так как вы хотите по-прежнему рисовать на холсте, по крайней мере, на половину ширины линии рисования. См. Код о том, как получить координаты мыши.

const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");
const r = 10; // draw radius
ctx.lineWidth = r * 2;
ctx.lineCap = "round";
ctx.fillStyle = "black";
var draw = false;
var lineStart = true;
var lastX, lastY;
function yesDraw() { draw = true; lineStart = true }
function mouseMove(e) { 
   const bounds = c.getBoundingClientRect();
   const x = e.pageX - bounds.left - scrollX;
   const y = e.pageY - bounds.top - scrollY;
   if(draw && x > -r && x < c.width + r && y > -r && y < c.height + r){
      drawing(x,y);
   }
}
function noDraw() { draw = false }
document.addEventListener("mousemove",mouseMove);
document.addEventListener("mousedown",yesDraw);
document.addEventListener("mouseup",noDraw);
function drawing(x, y) {
  if(lineStart){
     lastX = x;
     lastY = y;
     lineStart = false;
  }
  ctx.beginPath();
  ctx.lineTo(lastX, lastY);
  ctx.lineTo(x, y);
  ctx.stroke();
  lastX = x;
  lastY = y;
}
<canvas id="myCanvas" height="400" ; width="1000" style="border: solid 1px black;">Your browser does not support canvas.</canvas>
0

Используйте lineTo и завершайте каждую линию дугой, чтобы сделать непрерывные плавные линии.

//Create Canvas
//(You can do this in HTML)
var c = document.body.appendChild(document.createElement("canvas"));
c.height = 400;
c.width = 1000;
var ctx = c.getContext("2d");
ctx.lineWidth = 20;
//Control drawing variable
var drawing = false;
c.onmousedown = c.onmouseout = c.onmouseup = function(evt) {
  drawing = (evt.type === "mousedown");
};
//Keep track of last position
var oldX = null;
var oldY = null;
/**
 * Draw the latest line
 *
 * @param {number} x
 * @param {number} y
 */
function draw(x, y) {
  if (drawing) {
    if (oldX !== null) {
      //If drawing, move to old coordinates for continual line
      ctx.beginPath();
      ctx.moveTo(oldX, oldY);
    } else {
      //Else simply move to current coordinates
      ctx.moveTo(x, y);
      ctx.beginPath();
    }
    //Draw a line
    ctx.lineTo(x, y);
    ctx.closePath();
    ctx.stroke();
    //Add an arc to the end of the line to make it smooth
    ctx.beginPath();
    ctx.arc(x, y, 0, 0, Math.PI * 2);
    ctx.closePath();
    ctx.stroke();
    //Save new coordinates as old for next draw cycle
    oldX = x;
    oldY = y;
  } else {
    //If not drawing, cut line byt setting "old" to null
    oldX = null;
    oldY = null;
  }
}
//Bind drawing
c.onmousemove = function(evt) {
  draw(evt.offsetX, evt.offsetY);
};
canvas {
  border: solid 1px black;
  background-color: #eee;
}
  • 0
    Это даст лучший ответ, если вы проверили свой код перед публикацией. Кроме того, отрезки могут иметь закругленные концы ctx.lineCap = "round" поэтому вам не нужно добавлять дугу, и нет необходимости иметь ctx.closePath() поскольку это только создаст еще один отрезок линии назад к началу линия. ctx.closePath не является противоположным действием для beginPath оно создает линию от последней позиции пути до начала (либо предыдущей первой точки после ctx.beginPath , либо предыдущего ctx.moveTo )

Ещё вопросы

Сообщество Overcoder
Наверх
Меню