【问题标题】:HTML5 Canvas Layer DisplayHTML5 画布层显示
【发布时间】:2017-06-02 00:20:56
【问题描述】:

我正在使用 HTML5 画布编写一个简单的图像处理/绘图实用程序。它目前适用于单个画布层。

我正在尝试添加“预览”功能,这样当光标在画布上移动时不会显示光标,而是显示在该位置单击鼠标的效果。例如,如果您在主画布中加载了一个图像并且选定的 globalCompositeOperation 是饱和的,您可以通过将鼠标移动到不同的部分来预览图像的外观。预览是当前工具的大小,所以如果它是一个圆形工具,半径为 5,您会看到该圆形覆盖的任何渲染效果。如果不向下单击,则只能看到预览。如果单击向下,则效果将应用于预览中显示的区域中的画布。

我的主画布上有一个用于 mousemove、mouseup 和 mousedown 的事件侦听器。这是我当前的代码(JS 和 CSS)。有两个画布标签(下面的代码中未显示)。一个是我的主画布,带有上下文ctx,另一个是鼠标预览画布,带有上下文mouseCtx。 CS 指的是一个全局的“Canvas State”对象。

代码现在可以正常运行,除了鼠标预览出现在主画布上的任何元素后面(我希望这是因为 z-index 较低)。当我点击放置一个元素时,它会出现在所有内容的前面。但是,如果我将鼠标悬停在更高的 Z 索引上,则主画布上根本不会显示任何内容。

我是否遗漏了一些愚蠢的东西,或者我实施此功能的策略是否存在?非常感谢您对正确方向的任何提示。

canvas.addEventListener('mousemove', mouseTrack);
canvas.addEventListener('mousedown', mouseTrack);
canvas.addEventListener('mouseup', mouseTrack);

function mouseTrack(e) {
  (e.type === 'mousedown') ? CS.isDrawing = true: 0;
  (e.type === 'mouseup') ? CS.isDrawing = false: 0;
  let mouseParams = {
    x: e.layerX,
    y: e.layerY,
    movArr: [e.movementX, e.movementY],
    windowArr: [e.clientX, e.clientY]
  };
  if (CS.isDrawing === false) {
    mouseCtx.clearRect(0, 0, mouseLayer.width, mouseLayer.height);
    mouseCtx.drawImage(canvas, 0, 0); //copy the current canvas
    console.log((CS.isDrawing === true) + " is drawing");
    mouseCtx.strokeStyle = CS.strokeS || randomRGBA();
    mouseCtx.fillStyle = CS.fillS || randomRGBA();
    mouseCtx.globalAlpha = CS.lOpacity;
    mouseCtx.beginPath(); //draw the thing on the current canvas
    switch (CS.tool) {
      case 'tBrush':
        drawBrush(mouseParams, mouseCtx, CS.brush, CS.brushSize);
        break;
      case 'tLine':
        drawLine(mouseParams, mouseCtx);
        break;
      case 'tCurve':
        drawBezier(mouseParams, mouseCtx);
        break;
      case 'tCircle':
        drawCircle(mouseParams, mouseCtx);
        break;
      case 'tSquare':
        drawSquare(mouseParams, mouseCtx);
        break;
    }
  } else {
    ctx.drawImage(mouseLayer, 0, 0);
  }
}
canvas {
  position: absolute;
  left: 0px;
  top: 0px;
  border: 2px solid green;
  outline: none;
  -webkit-user-select: none;
  /* Chrome all / Safari all */
  -moz-user-select: none;
  /* Firefox all */
  -ms-user-select: none;
  /* IE 10+ */
  user-select: none;
  cursor: none;
  z-index: 1;
}
canvas.mouseOverlay {
  position: absolute;
  left: 0px;
  top: 0px;
  border: 2px solid green;
  outline: none;
  -webkit-user-select: none;
  /* Chrome all / Safari all */
  -moz-user-select: none;
  /* Firefox all */
  -ms-user-select: none;
  /* IE 10+ */
  user-select: none;
  cursor: none;
  z-index: 0;
}

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    可能发生的情况是,您的预览画布妨碍了事件在主画布上被触发。您是否检查过主画布上的mousedown 事件是否被触发?如果确实没有被触发,请尝试将pointer-events:none; 添加到您的canvas.mouseOver css(z-index 更高)。

    注意:如果您需要支持旧版本的 IE,这可能是一个糟糕的解决方案

    【讨论】:

    • 谢谢!哇,由于某种原因,我忘记了我的画布元素是堆叠的,而不是嵌套在 DOM 中,所以没有事件捕获,而是事件“阻塞”,我猜是由于 z-index。应该知道看听者。您的 CSS 解决方案效果很好,就像下面的重构一样,只需 queryselectorAll-ing 画布并监听每个画布: let canvases=document.querySelectorAll('canvas'); canvases.forEach((c)=>c.addEventListener('mousemove',mouseTrack)); canvases.forEach((c)=>c.addEventListener('mousedown',mouseTrack)); canvases.forEach((c)=>c.addEventListener('mouseup',mouseTrack));
    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 2016-02-22
    • 2011-03-01
    • 2013-07-24
    • 2015-02-10
    • 2014-08-20
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多