Use Canvas to Draw Dependency Arrows

Use Arrows

by Trever Shick

HTML

<canvas id="can"></canvas>

<table id="tbl">
    <tr>
        <th></th>
        <th>col1</th>
        <th>col2</th>
        <th>col3</th>
        <th>col4</th>
    </tr>
    <tr>
        <td>Name 0</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
    </tr>
    <tr>
        <td></td>
        <td><div class="pill" id="F0">F0</div></td>
        <td></td>
        <td>
            <div class="pill" id="F1">F1</div>
        </td>
        <td><div class="pill" id="F2">F2</div></td>
    </tr>
    <tr>
        <td></td>
        <td><div class="pill" id="F3">F3</div></td>
        <td>
            
        </td>
        <td></td>
        <td><div class="pill" id="F5">F5</div></td>
    </tr>

    <tr>
        <td>Name 1</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
    </tr>
    <tr>
        <td></td>
        <td></td>
        <td></td>
        <td>
            <div class="pill subdued" id="F123">F123</div>
        </td>
        <td></td>
    </tr>

    <tr>
        <td>Name 2</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
        <td>PBAR</td>
    </tr>
    <tr>
        <td></td>
        <td><div class="pill" id="F6">F6</div></td>
        <td></td>
        <td><div class="pill" id="F7">F7</div></td>
        <td>
            <div class="pill" id="F8">F8</div>
        </td>
    </tr>

</table>

CSS

body{
    padding:10px;
}
#can {
    position: absolute;
    top: 0px;
    left: 0px;
    right:0px;
    bottom:0px;
/*     background-color:blue;
     */    /* opacity:0.01; */
    z-index: 3;
}
.subdued {
    opacity:.20;
}
table {
    width:100%;
    height:600px;
}
td {
    border: 1px solid grey;
}
.pill {
    margin:10px;
    padding:3px;
    border:1px solid blue;
}

JavaScript

var canvas = document.getElementById('can'),
    context = canvas.getContext('2d');

function resizeCanvas(ctx) {
  ctx.canvas.width  = window.innerWidth;
  ctx.canvas.height = window.innerHeight;
}

function circleAt(context, point,radius) {
    context.save();
    context.beginPath();
    context.arc(point.x, point.y, radius, 0, 2 * Math.PI, false);
    context.fill();
    context.restore();
}

function drawArrowHead(context, from,to) {
    var headlen = 10;   // length of head in pixels
    var angle = Math.atan2(to.y-from.y,to.x-from.x);
    context.moveTo(to.x,to.y);
    context.lineTo(to.x-headlen*Math.cos(angle-Math.PI/6),to.y-headlen*Math.sin(angle-Math.PI/6));
    context.moveTo(to.x, to.y);
    context.lineTo(to.x-headlen*Math.cos(angle+Math.PI/6),to.y-headlen*Math.sin(angle+Math.PI/6));
context.stroke();
}

function drawDependencies(context, fromid, toid) {
    debugger;
    var fromElement = document.getElementById(fromid);
    var toElement = document.getElementById(toid);
    var ports = findPorts(fromElement.getBoundingClientRect(),
                          toElement.getBoundingClientRect());
    drawDependencyLine(context, ports[0], ports[1]);
}

function drawDependencyLine(context, from, to) {
    context.save();
    context.beginPath();
    context.setLineDash([5,2]);
    context.moveTo(from.x,from.y);
    context.lineTo(to.x, to.y);
    context.lineWidth=2;
    context.stroke();
// reset the dashes
    context.setLineDash([0,0]);
    circleAt(context, from,3);
    drawArrowHead(context, from, to);
    context.restore();
}

function rightCenterOfRect(rect) {
    return {
        x: rect.right, 
        y: centerOfRect(rect).y
    };
}

function leftCenterOfRect(rect) {
    return {
        x: rect.left, 
        y: centerOfRect(rect).y
    };
}

function topCenterOfRect(rect){
    return {
        x: centerOfRect(rect).x,
        y: rect.top
    };
}

function bottomCenterOfRect(rect){
    return {
        x: centerOfRect(rect).x,
        y:...