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:...