在使用 Canvas 绘制思维导图时,绘制连线是连接各个节点以展示它们之间关系的重要环节。以下是几种常见的绘制连线的方法及其详细介绍:
直线连线
- 基本原理:通过指定起始点和结束点的坐标,使用
moveTo()
和lineTo()
方法绘制一条直线段来连接两个节点。 - 示例代码:
function drawStraightLink(ctx, startNode, endNode) {
ctx.beginPath();
ctx.moveTo(startNode.x, startNode.y);
ctx.lineTo(endNode.x, endNode.y);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 1.5;
ctx.stroke();
}
- 适用场景:适用于简单的思维导图结构,当节点之间的关系较为直接,用直线连接能够清晰地表达其逻辑关系时使用。
折线连线
- 基本原理:通过多个
lineTo()
方法,指定多个中间点的坐标,绘制出由多条直线段组成的折线来连接节点。这种方式可以实现更复杂的路径,使连线能够绕过其他元素或按照特定的布局进行绘制。 - 示例代码:
function drawPolylineLink(ctx, startNode, endNode) {
ctx.beginPath();
ctx.moveTo(startNode.x, startNode.y);
ctx.lineTo(startNode.x + 50, startNode.y + 50);
ctx.lineTo(endNode.x - 30, endNode.y + 30);
ctx.lineTo(endNode.x, endNode.y);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 1.5;
ctx.stroke();
}
- 适用场景:当节点之间的直接连线会与其他元素交叉或需要更灵活的布局时,可以使用折线连线来避开障碍物,使思维导图的结构更加清晰和易于理解。
曲线连线
- 基本原理:使用 Canvas 的二次贝塞尔曲线(
quadraticCurveTo()
)或三次贝塞尔曲线(bezierCurveTo()
)方法来绘制曲线连线。这些方法需要指定曲线的控制点,通过控制点来调整曲线的形状,从而实现平滑的曲线连接效果。 - 示例代码二次贝塞尔曲线:
function drawQuadraticCurveLink(ctx, startNode, endNode) {
ctx.beginPath();
ctx.moveTo(startNode.x, startNode.y);
// 控制点坐标
const controlX = (startNode.x + endNode.x) / 2;
const controlY = startNode.y;
ctx.quadraticCurveTo(controlX, controlY, endNode.x, endNode.y);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 1.5;
ctx.stroke();
}
- 示例代码三次贝塞尔曲线:
function drawCubicCurveLink(ctx, startNode, endNode) {
ctx.beginPath();
ctx.moveTo(startNode.x, startNode.y);
// 两个控制点坐标
const control1X = startNode.x + 50;
const control1Y = startNode.y + 30;
const control2X = endNode.x - 50;
const control2Y = endNode.y - 30;
ctx.bezierCurveTo(control1X, control1Y, control2X, control2Y, endNode.x, endNode.y);
ctx.strokeStyle = 'gray';
ctx.lineWidth = 1.5;
ctx.stroke();
}
- 适用场景:当希望连线具有更自然、流畅的过渡效果,或者节点之间的关系具有某种动态或渐进的含义时,曲线连线能够更好地体现这种视觉效果,使思维导图更具美感和吸引力。
箭头连线
- 基本原理:在绘制直线或曲线连线的基础上,在连线的末端绘制一个箭头形状。可以通过计算连线的角度和长度,使用
beginPath()
、moveTo()
和lineTo()
方法来绘制箭头的各个边。 - 示例代码:
function drawArrowLink(ctx, startNode, endNode) {
// 绘制连线
drawStraightLink(ctx, startNode, endNode);
// 计算箭头的角度和长度
const dx = endNode.x - startNode.x;
const dy = endNode.y - startNode.y;
const length = Math.sqrt(dx * dx + dy * dy);
const angle = Math.atan2(dy, dx);
// 箭头的大小和角度调整
const arrowSize = 10;
const arrowAngle = Math.PI / 6;
// 绘制箭头
ctx.beginPath();
ctx.moveTo(endNode.x, endNode.y);
ctx.lineTo(endNode.x - arrowSize * Math.cos(angle - arrowAngle), endNode.y - arrowSize * Math.sin(angle - arrowAngle));
ctx.lineTo(endNode.x - arrowSize * Math.cos(angle + arrowAngle), endNode.y - arrowSize * Math.sin(angle + arrowAngle));
ctx.closePath();
ctx.fillStyle = 'gray';
ctx.fill();
}
- 适用场景:箭头连线能够更明确地表示节点之间的流向或层次关系,常用于有明确的逻辑顺序或父子关系的思维导图中,增强信息的传达效果。
在实际绘制思维导图时,可以根据节点之间的具体关系、整体布局以及视觉效果的需求,选择合适的连线绘制方法来展示思维导图的逻辑结构,使其更加清晰、直观和易于理解。