JSFiddle - React, Tailwind, and code Playground

HTML

<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
</head>
<body>
<div>
    <canvas id="c" width="1500" height="1000" style="border:1px solid #999"></canvas>
</div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.7.0/fabric.min.js"></script>
</body>
</html>

JavaScript

const calcNewAngle = ({ x1, y1, x2, y2 }) => {
  const width = Math.abs(Math.max(x1, x2) - Math.min(x1, x2));
  const height = Math.abs(Math.max(y1, y2) - Math.min(y1, y2));
  let theta;
  if (x1 < x2 && y1 < y2) {
    theta = Math.atan(height / width);
  } else if (x1 < x2 && y1 >= y2) {
    theta = Math.atan(-height / width);
  } else if (x1 >= x2 && y1 < y2) {
    theta = Math.abs(Math.atan(height / width) - Math.PI);
  } else {
    theta = Math.abs(Math.atan(-height / width) - Math.PI);
  }
  return theta;
};

const setArrowPoints = ({x1, y1, x2, y2}) => {
  const angle = calcNewAngle({x1, y1, x2, y2});
  const headlen = 8;
  return [
    {
      x: x1,
      y: y1
    },
    {
      x: x2,
      y: y2
    },
    {
      x: x2 - headlen * Math.cos(angle - Math.PI / 2),
      y: y2 - headlen * Math.sin(angle - Math.PI / 2)
    },
    {
      x: x2 + headlen * Math.cos(angle),
      y: y2 + headlen * Math.sin(angle)
    },
    {
      x: x2 - headlen * Math.cos(angle + Math.PI / 2),
      y: y2 - headlen * Math.sin(angle + Math.PI / 2)
    },
    {
      x: x2,
      y: y2
    }
  ];
}

const getX1Y1X2Y2 = points => {
	return {
    x1: points[0].x,
    y1: points[0].y,
    x2: points[1].x,
    y2: points[1].y
  }
}

const updateArrow = (e, canvas, arrow, index) => {
	const mousePos = canvas.getPointer(e);
  const {points} = arrow;
  points[index].x = mousePos.x;
  points[index].y = mousePos.y;
  arrow.set('points', setArrowPoints(getX1Y1X2Y2(points)))
}

const createControl = ({canvas, index, arrow}) => {
	const left = arrow.points[index].x;
  const top = arrow.points[index].y;
  const control = new fabric.Circle({
  	index,
    left, 
    top,
    radius: 5,
    strokeWidth: 1,
    hasBorders: false,
    stroke: 'rgba(0,0,255,1)',
    fill: 'rgba(255,255,255,1)',
    originX: 'center',
    originY: 'center'
  });
  control.setControlsVisibility({
    bl: false,
    br: false,
    mb: false,
    ml: false,
    mr: false,
    mt: false,
    tl: false,
    tr:...