【问题标题】:How to draw arrow in HTML table across cells?如何在 HTML 表格中跨单元格绘制箭头?
【发布时间】:2018-06-26 20:43:41
【问题描述】:

我有一个简单的 html 表格,其中包含一些使用 td 标记创建的单元格。 例如,现在我需要从单元格 A2 到 C2 绘制一个箭头。 我想创建一个 jQuery 函数来获取单元格 A2 和 C2 中间的 XY 坐标,然后以某种方式绘制一个箭头。

实现如图所示的外观和感觉的好方法是什么?

【问题讨论】:

  • 您可以尝试在表格上添加浮动图像,使用 css 位置:developer.mozilla.org/en-US/docs/Web/CSS/position
  • 谢谢。如果箭头必须是可变大小的,这是否也有效,这意味着有时更短有时更长?
  • 为此,您可以拉伸图像,或使用不同的图像,或使用画布,如下面的解决方案所示。

标签: javascript html html-table


【解决方案1】:

您可以通过使用画布元素来动态执行此操作,以包含您的箭头,您将通过 2D 上下文绘图函数动态绘制该箭头。您完全可以使用 javascript 定位 canvas 元素。

这里是示例代码:

HTML:

<canvas id="canvas" width="100" height="100">
</canvas>



 <table>
 <tr><td>1</td><td>2</td></tr>
 <tr><td>3</td><td>4</td></tr>
 <tr><td>5</td><td>6</td></tr>
 </table>

Javascript:

 var canvas = document.querySelector('canvas');
 var ctx = canvas.getContext('2d');

 canvas.style.top = 7 + "px";
 canvas.style.left = 7 + "px";

 var fromx = 0;
 var fromy = 12;
 var tox = 25;
 var toy = 12;

 var headlen = 10;   // length of head in pixels
 var angle = Math.atan2(toy-fromy,tox-fromx);
 var arrowSize = 2;
 var headlen = 10;

 var angle = Math.atan2(toy-fromy,tox-fromx);
 //starting path of the arrow from the start square to the end square and drawing the stroke
 ctx.beginPath();
ctx.moveTo(fromx, fromy);
 ctx.lineTo(tox, toy);
 ctx.strokeStyle = "#cc0000";
 ctx.lineWidth = arrowSize;
 ctx.stroke();

 //starting a new path from the head of the arrow to one of the sides of the point
 ctx.beginPath();
 ctx.moveTo(tox, toy);
 ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

 //path from the side point of the arrow, to the other side point
 ctx.lineTo(tox-headlen*Math.cos(angle+Math.PI/7),toy-headlen*Math.sin(angle+Math.PI/7));

 //path from the side point back to the tip of the arrow, and then again to the opposite side point
 ctx.lineTo(tox, toy);
 ctx.lineTo(tox-headlen*Math.cos(angle-Math.PI/7),toy-headlen*Math.sin(angle-Math.PI/7));

 //draws the paths created above
 ctx.strokeStyle = "#cc0000";
 ctx.lineWidth = arrowSize;
 ctx.stroke();
 ctx.fillStyle = "#cc0000";
 ctx.fill();

CSS:

 #canvas {
        position: absolute;
        top: 0px;
        left: 0px;
        width: 100px;
        height: 100px;
 }

您可以通过编程方式获取表格元素的定位信息,以便为 fromx、fromy 等设置正确的值,以及设置 canvas.style.top 和 canvas.style.left。

我借用Draw arrow on canvas tag的箭头绘制代码

【讨论】:

  • 如果你这样做了,你还能获得表格单元格的鼠标事件吗?像悬停?还是画布会放在桌子上,挡住鼠标?
【解决方案2】:

首先,我们可以获得单元格相对于文档的中心。然后,我们可以简单地在画布上(相对于文档)从头到尾绘制一个箭头。诀窍是在画布上设置pointer-events: none,这样我们就不会意外地与之交互。

// gets the center of a table cell relative to the document
function getCellCenter(table, row, column) {
  var tableRow = $(table).find('tr')[row];
  var tableCell = $(tableRow).find('td')[column];

  var offset = $(tableCell).offset();
  var width = $(tableCell).innerWidth();
  var height = $(tableCell).innerHeight();
  
  return {
    x: offset.left + width / 2,
    y: offset.top + height / 2
  }
}

// draws an arrow on the document from the start to the end offsets
function drawArrow(start, end) {

  // create a canvas to draw the arrow on
  var canvas = document.createElement('canvas');
  canvas.width = $('body').innerWidth();
  canvas.height = $('body').innerHeight();
  $(canvas).css('position', 'absolute');
  $(canvas).css('pointer-events', 'none');
  $(canvas).css('top', '0');
  $(canvas).css('left', '0');
  $(canvas).css('opacity', '0.85');
  $('body').append(canvas);
  
  // get the drawing context
  var ctx = canvas.getContext('2d');
  ctx.fillStyle = 'steelblue';
  ctx.strokeStyle = 'steelblue';
  
  // draw line from start to end
  ctx.beginPath();
  ctx.moveTo(start.x, start.y);
  ctx.lineTo(end.x, end.y);
  ctx.lineWidth = 2;
  ctx.stroke();
  
  // draw circle at beginning of line
  ctx.beginPath();  
  ctx.arc(start.x, start.y, 4, 0, Math.PI * 2, true);
  ctx.fill();

  // draw pointer at end of line (needs rotation)
  ctx.beginPath();  
  var angle = Math.atan2(end.y - start.y, end.x - start.x);
  ctx.translate(end.x, end.y);
  ctx.rotate(angle);
  ctx.moveTo(0, 0);
  ctx.lineTo(-10, -7);
  ctx.lineTo(-10, 7);
  ctx.lineTo(0, 0);
  ctx.fill();

  // reset canvas context
  ctx.setTransform(1, 0, 0, 1, 0, 0);  
  
  return canvas;
}

// finds the center of the start and end cells, and then calls drawArrow
function drawArrowOnTable(table, startRow, startColumn, endRow, endColumn) {
  drawArrow(
    getCellCenter($(table), startRow, startColumn),
    getCellCenter($(table), endRow, endColumn)
  );
}

// draw an arrow from (1, 0) to (2, 4)
drawArrowOnTable('table', 1, 0, 2, 4);
table, td {
  border-collapse: collapse;
}

td {
  border: 1px solid #ddd;
  padding: 6px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<table>
  <tr>
    <td>A1</td>
    <td>B1</td>
    <td>C1</td>
    <td>D1</td>
    <td>E1</td>
  </tr>

  <tr>
    <td>A2</td>
    <td>B2</td>
    <td>C2</td>
    <td>D2</td>
    <td>E2</td>
  </tr>

  <tr>
    <td>A3</td>
    <td>B3</td>
    <td>C3</td>
    <td>D3</td>
    <td>E3</td>
  </tr>
  
</table>

<pre>drawArrowOnTable('table', 1, 0, 2, 4);</pre>
</body>
</html>

【讨论】:

  • 优秀的解决方案。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-17
  • 1970-01-01
  • 2014-06-02
  • 1970-01-01
  • 1970-01-01
  • 2018-02-13
  • 2019-08-06
相关资源
最近更新 更多