function appendArrow(d, i) { let arrowHeadSize = strokeWidth(d.value) * 3; let thisPath = d3.select(this).node(); let pathLength = thisPath.getTotalLength(); let point = thisPath.getPointAtLength(pathLength); let previousPoint = thisPath.getPointAtLength(pathLength - 1); let rotation = 0; if (point.y == previousPoint.y) { rotation = point.x < previousPoint.x ? 180 : 0; } else if (point.x == previousPoint.x) { rotation = point.y < previousPoint.y ? -90 : 90; } else { let adj = Math.abs(point.x - previousPoint.x); let opp = Math.abs(point.y - previousPoint.y); let angle = Math.atan(opp / adj) * (180 / Math.PI); if (point.x < previousPoint.x) { angle = angle + (90 - angle) * 2; } if (point.y < previousPoint.y) { rotation = -angle; } else { rotation = angle; } } let dString = "M" + point.x + "," + (point.y - arrowHeadSize / 2) + " L" + (point.x + arrowHeadSize / 2) + "," + point.y + " L" + point.x + "," + (point.y + arrowHeadSize / 2); let rotationString = "rotate(" + rotation + "," + point.x + "," + point.y + ")"; g.append("path") .attr("d", dString) .attr("class", "arrow-head") .attr("transform", rotationString) .style("stroke", colour(d.source)) .style("fill", colour(d.source)); }