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: