如何跨单元格在HTML表格中绘制箭头?

时间:2018-01-17 21:13:41

标签: javascript html html-table

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

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

Table cells with arrow

2 个答案:

答案 0 :(得分:1)

您可以使用canvas元素动态地执行此操作,以包含箭头,您将通过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

中的箭头绘图代码

答案 1 :(得分:0)

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

&#13;
&#13;
// 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);
&#13;
table, td {
  border-collapse: collapse;
}

td {
  border: 1px solid #ddd;
  padding: 6px;
}
&#13;
<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>
&#13;
&#13;
&#13;