【问题标题】:Dynamically drawing in canvas在画布中动态绘制
【发布时间】:2018-03-28 21:01:42
【问题描述】:

我正在尝试创建一个简单的纯 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?

【问题讨论】:

标签: javascript html canvas drawing


【解决方案1】:

使用lineTo 并以arc 结束每一行以制作连续的平滑线条。

//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;
}

【讨论】:

  • 如果您在发布之前测试您的代码,它会提供更好的答案。线段也可以有圆形末端ctx.lineCap = "round",所以你不需要添加弧,也不需要ctx.closePath(),因为这只会创建另一个线段回到线的开头。 ctx.closePathbeginPath 不是相反的操作,它创建一条从最后一个路径位置回到起点的线(ctx.beginPath 之后的前一个第一个点,或前一个 ctx.moveTo
【解决方案2】:

上一个鼠标位置的线段。

而不是绘制圆弧,而是从先前的鼠标位置绘制线段到新的鼠标位置。由于您不希望从上一次绘制的末尾开始绘制线条,因此您还需要指示新线条何时开始并将之前的鼠标位置设置为当前鼠标。

为此,我添加了 3 个变量 lineStartlastXlastY

lineStart 在鼠标按下事件触发时设置为 true。在绘图函数中,如果 line start 为 true,则 lastXlastY 设置为 x,ylineStart 设置为 false。 lastX, lastY 保持上一个鼠标位置。在每次draw call结束时,它们被设置为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;
}
&lt;canvas id="myCanvas" height="400" ; width="1000" style="border: solid 1px black;"&gt;Your browser does not support canvas.&lt;/canvas&gt;

【讨论】:

    猜你喜欢
    • 2021-10-26
    • 1970-01-01
    • 2020-10-12
    • 1970-01-01
    • 2020-05-25
    • 2014-06-29
    • 2019-04-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多