Javascript uses canvas to draw curves, arrows, etc. between two points

Javascript uses canvas to draw curves and rectangles between two points, and draw text in the rectangle to achieve center alignment and arrow drawing. The effect is as shown below:

1. HTML, the code is as follows

<canvas id="canvas" width="1000" height="600"></canvas>

2. The css code is as follows:

canvas {<!-- -->
display: block;
width: 1000px;
height: 600px;
background: conic-gradient(#eee 25%, white 0deg 50%, #eee 0deg 75%, white 0deg) 0 / 20px 20px;
margin-inline: auto;
}
@media (max-width: 640px) {<!-- -->
canvas {<!-- -->
width: 100vw;
height: 60vw;
}
}

3. The Javascript code is as follows

var context = document.getElementById("canvas").getContext("2d"); ;
// draw size
var width = canvas.width;
var height = canvas.height;
\t\t\t
//The coordinates, size, color and other data of the two blocks
var data = [{<!-- -->
x: 800,
y: 180,
width: 200,
height: 50,
color: 'deepskyblue',
text:" + u + ate"
}, {<!-- -->
x: 600,
y: 680,
width: 200,
height: 50,
color: 'deeppink',
text:"gress step"
}];
// Draw rectangle method
var drawRect = function () {<!-- -->
data.forEach(function (obj) {<!-- -->
context.beginPath();
context.fillStyle = obj.color;
context.fillRect(obj.x, obj.y, obj.width, obj.height);
context.closePath();
context.font="30px Verdana";
context.fillStyle="#fff";
console.log(context.measureText(obj.text))
const textMetrics = context.measureText(obj.text);
//The height of all words in this font
let fontHeight = textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent;
console.log(fontHeight)
\t\t\t\t\t
context.fillText(obj.text,0,0)
context.fillText(obj.text,obj.x + (obj.width-context.measureText(obj.text).width)/2,obj.y + fontHeight);
});
\t\t\t\t
};
\t\t\t
//Method to draw connection curve
var drawCurve = function () {<!-- -->
// Sort by coordinate position
var dataSort = data.sort(function (objA, objB) {<!-- -->
return (objA.y + objA.height) - (objB.y + objB.height);
});
//Know the upper and lower data
var from = dataSort[0];
var to = dataSort[1];
\t\t\t    
//The starting point and end point of the curve
var fromX = from.x + from.width / 2;
var fromY = from.y + from.height;
var toX = to.x + to.width / 2;
var toY = to.y;
\t\t\t    
// Curve control point coordinates
var cp1x = fromX;
var cp1y = fromY + (toY - fromY) / 2;
\t\t\t    
var cp2x = toX;
var cp2y = toY - (toY - fromY) / 2;
\t\t\t    
// Start drawing curve
context.beginPath();
context.lineWidth = 1
context.strokeStyle = '#000';
context.moveTo(fromX, fromY);
// draw curve points
context.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, toX, toY);
context.stroke();
};
\t\t\t
// drawing method
var draw = function () {<!-- -->
context.clearRect(0, 0, width, height);
drawRect();
drawCurve();
};
\t\t\t
draw();
\t\t\t
canvas_arrow(ctx, 10, 30, 200, 150);
canvas_arrow(ctx, 100, 200, 400, 50);
canvas_arrow(ctx, 200, 30, 10, 150);
canvas_arrow(ctx, 400, 200, 100, 50);
ctx.stroke();
\t\t\t 
function canvas_arrow(context, fromx, fromy, tox, toy) {<!-- -->
var headlen = 10; // length of head in pixels
var dx = tox - fromx;
var dy = toy - fromy;
var angle = Math.atan2(dy, dx);
context.moveTo(fromx, fromy);
context.lineTo(tox, toy);
context.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
context.moveTo(tox, toy);
context.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
}

Ok, this is the code. The complete code is as follows: