【问题标题】:How to draw outside of an HTML canvas element?如何在 HTML 画布元素之外绘制?
【发布时间】:2015-09-22 16:00:46
【问题描述】:

我有一个 HTML 画布元素,并实现了一个画笔,它可以捕捉画布元素的 mousedownmousemovemouseup 事件。这一切都适用于在画布上绘图。但是,我认为我不喜欢如果您的鼠标在笔划中途离开画布,您将无法继续绘图。它只是切断它。在我看来,这对这个人非常无情,而且对用户不太友好。

如果您打开 Microsoft Paint 并开始使用画笔或椭圆或其他东西进行绘制,只要您从画布内开始,您就可以将鼠标拖动到屏幕上的任意位置,然后在任意位置重新进入画布。例如,它还可以很容易地在角落绘制四分之一圆,因为您可以将椭圆工具拖到屏幕外。我希望这是有道理的。

无论如何,我想知道是否有一种方法可以使用 HTML5 画布实现这一点,或者我将如何着手实现这类事情。用户将永远不必真正看到那里绘制的任何东西;它主要只是一个可用性功能。

编辑:很多这些解决方案的一个问题是如何处理坐标。目前我的画布在屏幕中间,画布的左上角是(0, 0),右下角是(500, 500)。坐标的平移工作也要考虑在内。

Edit2:我发现显然你可以很好地绘制画布边界。例如,您可以提供负的宽度、高度和坐标,canvas 元素会很好地处理它。所以基本上解决方案可能只涉及捕获文档的mousemovemouseup 并仅翻译xy 以从画布的左上角开始。

【问题讨论】:

  • 能否在窗口本身上捕获鼠标事件,然后委托给画布?
  • 也许尝试发布一个您目前拥有的示例。如果我们不必首先重新创建自己的“损坏”示例,那么提供帮助会更容易。
  • 也许你也可以让画布元素在窗口的全宽和全高,并且画布内的绘图区域稍微小一些?
  • @AidasBendoraitis:这也是个好主意。让我快速尝试一下。
  • @zero298:你能告诉我怎么做吗?

标签: javascript jquery html canvas bounds


【解决方案1】:

这是您在重新进入画布时可以继续绘图的一种方法:

  • 创建一个全局变量并在鼠标按下时将该变量设置为 true
  • 为 mouseup 添加一个全局事件,这样你就可以捕捉到是否有人在外面这样做 画布,如果是的话,将全局变量设置为false,画布元素的mouseup当然也需要设置相同的变量
  • 在鼠标移动时,在绘制之前检查全局变量是否为真

要在画布“外部”绘制,例如角落中的四分之一圆,我会将所有事件作为全局处理程序移动到文档级别,并在单击时捕获画布元素并传递其客户端坐标以使用文档坐标进行计算.

【讨论】:

    【解决方案2】:

    这里是一个非常粗略的初稿,关于如何在窗口而不是画布上监听鼠标事件以便能够连续绘制:

    var logger = document.getElementById("logger"),
      mState = document.getElementById("mState"),
      mX = document.getElementById("mX"),
      mY = document.getElementById("mY"),
      cX = document.getElementById("cX"),
      cY = document.getElementById("cY"),
      c = document.getElementById("canvas"),
      ctx = c.getContext("2d");
    
    var mouse = {
      x: 0,
      y: 0,
      state: ""
    };
    
    function printCanvasLocation() {
      var b = c.getBoundingClientRect();
      cX.innerHTML = b.top;
      cY.innerHTML = b.left;
    }
    
    function setState(mouseE, state) {
      mouse.x = mouseE.clientX;
      mouse.y = mouseE.clientY;
    
      mX.innerHTML = mouseE.clientX;
      mY.innerHTML = mouseE.clientY;
      if (state) {
        mState.innerHTML = state;
        mouse.state = state;
      }
    }
    
    window.addEventListener("mousedown", function(mouseE) {
      setState(mouseE, "down");
    });
    
    window.addEventListener("mouseup", function(mouseE) {
      setState(mouseE, "up");
    });
    
    window.addEventListener("mousemove", function(mouseE) {
      var offset = c.getBoundingClientRect();
    
      var fix = {
        x1: (mouse.x - offset.left),
        y1: (mouse.y - offset.top),
        x2: (mouseE.clientX - offset.left),
        y2: (mouseE.clientY - offset.top)
      };
    
      if (mouse.state === "down") {
        ctx.moveTo(fix.x1, fix.y1);
        ctx.lineTo(fix.x2, fix.y2);
        ctx.strokeStyle = "#000";
        ctx.stroke();
      }
      setState(mouseE);
    });
    
    window.addEventListener("resize", function() {
      printCanvasLocation();
    });
    
    printCanvasLocation();
                .center {
    
                  text-align: center;
    
                }
    
                canvas {
    
                  background-color: lightblue;
    
                }
    <main>
      <div class="center">
        <canvas id="canvas" width="128" height="128">If you can see me, you should update your browser</canvas>
      </div>
      <div id="logger" role="log">
        <span>State: </span><span id="mState">Unknown</span>
        <span>X: </span><span id="mX">Unknown</span>
        <span>Y: </span><span id="mY">Unknown</span>
        <span>Canvas X: </span><span id="cX">Unknown</span>
        <span>Canvas Y: </span><span id="cY">Unknown</span>
      </div>
    </main>

    【讨论】:

    • 您的Canvas XCanvas Y 是倒退的,但反响很好!我想这样就可以了。
    • @AndreyK 我不明白你的意思。如果您的意思是使用 CSS 或其他方式旋转画布,我会假设您需要对从鼠标事件获得的坐标应用相同的矩阵乘法。
    【解决方案3】:

    一种解决方案是让画布成为窗口的大小,并用它来缩放它的大小。画布可以大部分是透明的。

    我确信还有一种方法可以让鼠标事件等先通过画布,然后再传递到后面的元素,如果需要的话。 (参见:“js 事件冒泡和捕获”。)

    但是你将拥有绝对的控制权,并且能够在任何地方绘制任何东西。

    【讨论】:

      猜你喜欢
      • 2022-01-10
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2018-08-20
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      • 2016-08-23
      相关资源
      最近更新 更多