javascript - "Drawing"超过 html 文本

标签 javascript html drawing

我需要做以下事情:拥有一个普通的网页,能够使用鼠标、手写笔或手指(如果是平板电脑或智能手机)在文本上“绘制形状”,然后使用形状,确定某些“ Action ”。

我举个例子。想象一下 stackoverflow 上的这个问题,我在 ipad 上围绕这一段“画”了一个圆圈。圆圈(或圆圈的尝试,手动绘制总是很不完美),“捕获”段落,所以我知道我将在“段落”上进行操作,例如,选择所有内部文本。

我的问题是:这可行吗?有没有这样做的图书馆?如果不是,可以研究哪些技术?

我一直在进行自己的研究,但没有任何东西能满足我的所有需求。例如,canvas 完全按照我的需要进行绘制,但是不能在 html 页面上使用 canvas。它是页面上的另一个元素,而不是“包裹”另一个元素。

最佳答案

那么回答最初的问题:这可行吗?

首先,您需要能够在页面上绘图。 HTML5 标签对此很有用,因为它使我们能够非常轻松地在页面上绘制

其次,您需要能够识别页面上的哪些元素已被圈出。 javascript 函数 .getBoundingClientRect() 对此很有用,因为它告诉我们 x 和 y 位置以及宽度和高度。由于这些值是基于它们相对于文档边界框(而不是父元素)的位置,我们可以将其与我们绘制的圆的坐标进行比较。

因此,对于这两个组件,我们可以将这样的东西放在一起......(我承认这有点笨拙,但它可以根据您的特定用例进行优化) :

var canvas, ctx, flag, coords, cntnr, dot_flag;
    
    function _InitDraw() {
      flag = false;
      coords = {
        pX: 0,
        cX: 0,
        pY: 0,
        cY: 0
      };
      cntnr = {
        minX: document.body.offsetWidth,
        minY: document.body.offsetHeight,
        maxX: 0,
        maxY: 0
      };
      dot_flag = false;

      canvas = document.createElement('canvas');
      canvas.id = "cnvTest";
      canvas.style.position = "fixed";
      canvas.style.top = 0;
      canvas.style.left = 0;
      document.body.appendChild(canvas);
      canvas.style.width = "100%";
      canvas.style.height = "100%";
      canvas.style.zIndex = 9001;
      ctx = canvas.getContext("2d");
      ctx.canvas.width = window.innerWidth;
      ctx.canvas.height = window.innerHeight;
  
      canvas.addEventListener("mousemove", function (e) { _Draw('move', e); }, false);
      canvas.addEventListener("mousedown", function (e) { _Draw('down', e); }, false);
      canvas.addEventListener("mouseup", function (e) { _Draw('up', e); }, false);
      //canvas.addEventListener("mouseout", function (e) { _Draw('out', e); }, false);
    }
    
    function _Draw(action, e) {
      if(action == 'down') {
        coords.pX = coords.cX;
        coords.pY = coords.cY;
        coords.cX = e.pageX;
        coords.cY = e.pageY;
        
        if(coords.cX < cntnr.minX) cntnr.minX = coords.cX;
        if(coords.cY < cntnr.minY) cntnr.minY = coords.cY;
        if(coords.cX > cntnr.maxX) cntnr.maxX = coords.cX;
        if(coords.cY > cntnr.maxY) cntnr.maxY = coords.cY;

        flag = true;
        dot_flag = true;
        if(dot_flag) {
          ctx.beginPath();
          ctx.fillStyle = "black";
          ctx.lineCap = 'round';
          ctx.fillRect(coords.cX, coords.cY, 2, 2);
          ctx.closePath();
          dot_flag = false;
        }
      }
      if(action == 'up' || action == "out") {
        flag = false;
        _GetText();
      }
      if(action == 'move') {
        if(flag) {
          coords.pX = coords.cX;
          coords.pY = coords.cY;
          coords.cX = e.pageX;
          coords.cY = e.pageY;

          if(coords.cX < cntnr.minX) cntnr.minX = coords.cX;
          if(coords.cY < cntnr.minY) cntnr.minY = coords.cY;
          if(coords.cX > cntnr.maxX) cntnr.maxX = coords.cX;
          if(coords.cY > cntnr.maxY) cntnr.maxY = coords.cY;
          
          ctx.beginPath();
          ctx.moveTo(coords.pX, coords.pY);
          ctx.lineTo(coords.cX, coords.cY);
          ctx.strokeStyle = "black";
          ctx.lineCap = 'round';
          ctx.lineWidth = 4;
          ctx.stroke();
          ctx.closePath();
        }
      }
    }

    function _GetText() {
      // Find position and get closest element
      document.body.removeChild(canvas);

      var allEls = document.body.getElementsByTagName("*");
      for(var i = 0; i < allEls.length; i++) {
        var elBox = allEls[i].getBoundingClientRect();
        if(elBox.x > cntnr.minX && elBox.x+elBox.width < cntnr.maxX && elBox.y > cntnr.minY && elBox.y+elBox.height < cntnr.maxY) {
          // Do whatever you want with the element here.
          // I am adding an outline for confirmation of the circled elements.
          allEls[i].style.outline = "2px solid rgba(255, 255, 0, 0.8)";
          if(allEls[i].innerText !== null && allEls[i].innerText !== "undefined") {
            // Do something with the innerText here if you need the text from the element.
            console.log(allEls[i].innerText);
          }
        }
      }
    }

为了了解一点上下文,您需要先调用_InitDraw() 函数。这将在页面上创建一个应覆盖整个页面的 元素。

一旦您释放鼠标,它就会结束绘图模式并使用最小和最大位置值并循环遍历页面上的所有元素以查看是否有任何元素在这些边界内。

出于示例目的,此脚本随后会概述这些对象并将其中的任何文本记录到控制台。

*如果您想将其用于移动设备,则需要更改事件监听器(touchstart、touchmove、touchend)。

**另请注意,某些元素(例如任何“ block ”元素)的边界框可能比您在视觉上看到的文本大得多。所以这个脚本不会“捕获”那些元素。当然,您可以修改脚本以包含绘图传递的任何元素,但这可能会导致困惑的结果。

关于javascript - "Drawing"超过 html 文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70437386/

相关文章:

Java绘图框架: Refreshing?

JavaScript - 等待 IndexedDB 中的异步函数

javascript - Aurelia 要求 html 导入不起作用

PHP数据提交错误

jquery - 使用 Jquery 设置 Select 的样式

javascript - PaperJS:穿过前一条路径时停止绘制路径

javascript - 使用 Javascript 和 Canvas 重复绘图

javascript - addEventListener() 仅适用于最后一个实例

javascript - 如何将php变量值赋给javascript变量

javascript - DOM 元素可见性和 requestAnimationFrame