如何在 DEV 的离线页面上创建绘图交互

2025-05-24

如何在 DEV 的离线页面上创建绘图交互

由于越来越多的人注意到DEV 的离线页面,我想我会做一个关于如何复制它的代码的快速教程!

Canvas 是用 JavaScript 创建图形的——我们可以用它构建有趣的交互式工具。我通常使用P5.js来创建类似的交互式艺术作品,这使得 Canvas API 更容易使用。不过,我们希望离线页面尽可能独立且轻量,因此离线页面不需要使用任何外部代码。

我们首先需要<canvas>在 HTML 中创建一个标签。你还需要添加 CSS 来设置canvas占用空间——所以要给它设置高度和宽度。我制作了一个 Codepen 模板,其中包含一些入门级 CSS 供我们使用:

现在,开始讲 JavaScript!

我们要做的第一件事是选择 HTML 中已经存在的 Canvas 元素,以便与它进行交互。我们还必须为 Canvas 的上下文创建一个变量。我们将使用 2D 上下文,因为我们的绘图只是二维的:

const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d')
Enter fullscreen mode Exit fullscreen mode

我们还需要在 JavaScript 中设置画布的大小,以便我们的图像不会扭曲:

canvas.setAttribute('width', window.innerWidth)
canvas.setAttribute('height', window.innerHeight)
Enter fullscreen mode Exit fullscreen mode

现在我们需要添加一些事件监听器。对于绘图应用,我们需要添加以下内容:

  • 'mousedown' - 当用户按下鼠标时,我们想要开始绘制

  • 'touchstart' - 当用户使用手机时,我们再次开始绘制

  • 'mousemove' - 当用户移动鼠标时,我们希望从鼠标的先前位置到当前位置绘制一条线

  • 'touchmove' - 与上面相同,但当用户使用手机时

  • 'mouseup' - 当用户停止按下时,我们希望停止绘制

  • 'mouseleave'-当用户的鼠标离开该区域时,我们也希望停止绘制

  • 'touchend' - 当用户在手机上停止按下时,我们再次停止绘制

因此,我们需要三个事件处理函数来响应上述事件。我们先从startPaint每次人物开始绘画时运行的函数开始。

我们可以像在 JavaScript 中添加任何其他元素一样添加事件监听器:


function startPaint (e) {

}

canvas.addEventListener('mousedown', startPaint)
canvas.addEventListener('touchstart', startPaint)
Enter fullscreen mode Exit fullscreen mode

我们希望该startPaint函数能做几件事:

  • 首先,我们需要一个变量来跟踪我们当前是否正在绘制,以便处理程序仅在我们当前正在绘制时起作用。我们需要在每次开始绘制时都mousemove设置该变量。true

  • 然后,我们需要获取用户点击位置的坐标。我们需要跟踪这些坐标,以便当用户移动鼠标时,我们可以从当前点移动到下一个点。


let x, y, isPainting;

function getCoordinates(event) {
  // check to see if mobile or desktop
  if (["mousedown", "mousemove"].includes(event.type)) {
    // click events
    return [event.pageX - canvas.offsetLeft, event.pageY - canvas.offsetTop];
  } else {
    // touch coordinates
    return [
      event.touches[0].pageX - canvas.offsetLeft,
      event.touches[0].pageY - canvas.offsetTop
    ];
  }
}

function startPaint(e) {
  // change the old coordinates to the new ones*
  isPainting = true;
  let coordinates = getCoordinates(e);
  x = coordinates[0];
  y = coordinates[1];
}
Enter fullscreen mode Exit fullscreen mode

然后,我们需要处理用户何时移动鼠标进行绘制。这里我们需要:

  • 检查我们是否正在绘画(即鼠标按下)

  • 我们需要获取新的鼠标坐标

  • 我们需要从旧坐标到新坐标画一条线

  • 我们需要将旧坐标设置为新坐标,以便我们的下一个“绘制”从当前点开始

function drawLine(firstX, firstY, secondX, secondY) {
  // set the attributes of the line
  context.strokeStyle = "black";
  context.lineJoin = "round";
  context.lineWidth = 5;

  context.beginPath();
  context.moveTo(secondX, secondY);
  context.lineTo(firstX, firstY);
  context.closePath();

  // actually draw the path*
  context.stroke();
}

function paint(e) {
  if (isPainting) {
    let [newX, newY] = getCoordinates(e);
    drawLine(x, y, newX, newY);

    // Set x and y to our new coordinates
    x = newX;
    y = newY;
  }
}

canvas.addEventListener("mousemove", paint);
canvas.addEventListener("touchmove", paint);
Enter fullscreen mode Exit fullscreen mode

现在,我们只需在松开鼠标时停止绘图!


function exit() {
  isPainting = false;
}

canvas.addEventListener("mouseup", exit);
canvas.addEventListener("mouseleave", exit);
canvas.addEventListener("touchend", exit);
Enter fullscreen mode Exit fullscreen mode

现在,这是一个可以改变颜色并可以调整页面大小的完成版本!

我喜欢用代码创作艺术作品,尤其是那些可以与人互动的作品。如果你想了解更多,我还有一些关于这个主题的文章,如果你感兴趣的话!

文章来源:https://dev.to/aspittel/how-to-create-the-drawing-interaction-on-dev-s-offline-page-1mbe
PREV
我要回归 DEV 社区
NEXT
回到老问题:我最终如何编写数独求解算法