Canvas 思维导图:实现节点拖拽、缩放、添加和删除
要实现类似思维导图的效果,可以使用 HTML5 的 canvas 元素来绘制节点和连线。具体实现步骤如下:
- 创建 canvas 元素,并设置其宽高。可以使用 CSS 样式或 JavaScript 动态设置。
- 定义节点对象。节点包括位置、大小、颜色、文字等属性。可以使用 JavaScript 的类或对象来实现。
- 定义连线对象。连线包括起点、终点、线型、颜色等属性。可以使用 JavaScript 的类或对象来实现。
- 编写绘制函数。绘制函数根据节点和连线的属性,使用 canvas 的 2D 绘图 API 来绘制图形。
- 实现节点的拖拽、放缩、添加、删除等操作。可以使用 JavaScript 的事件处理函数来实现。
- 最后,将绘制函数和事件处理函数绑定到 canvas 元素上,就可以实现类似思维导图的效果了。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>Canvas Mind Map</title>
<style>
canvas {
width: 600px;
height: 400px;
border: 1px solid #ccc;
}
</style>
</head>
<body>
<canvas id='myCanvas'></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 定义节点对象
class Node {
constructor(x, y, width, height, color, text) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.color = color;
this.text = text;
}
draw() {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = '#fff';
ctx.fillText(this.text, this.x + this.width / 2, this.y + this.height / 2);
}
contains(x, y) {
return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height;
}
}
// 定义连线对象
class Line {
constructor(startX, startY, endX, endY, color) {
this.startX = startX;
this.startY = startY;
this.endX = endX;
this.endY = endY;
this.color = color;
}
draw() {
ctx.beginPath();
ctx.moveTo(this.startX, this.startY);
ctx.lineTo(this.endX, this.endY);
ctx.strokeStyle = this.color;
ctx.stroke();
}
}
// 创建节点和连线数组
const nodes = [];
const lines = [];
// 添加节点和连线示例
const node1 = new Node(100, 100, 80, 40, '#f00', 'Node 1');
const node2 = new Node(300, 100, 80, 40, '#0f0', 'Node 2');
const line1 = new Line(node1.x + node1.width, node1.y + node1.height / 2, node2.x, node2.y + node2.height / 2, '#00f');
nodes.push(node1, node2);
lines.push(line1);
// 绘制函数
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
lines.forEach(line => line.draw());
nodes.forEach(node => node.draw());
}
// 事件处理函数
let dragging = false;
let resizing = false;
let startX, startY, nodeIndex, resizingIndex;
canvas.addEventListener('mousedown', function(e) {
startX = e.offsetX;
startY = e.offsetY;
nodeIndex = nodes.findIndex(node => node.contains(startX, startY));
resizingIndex = nodes.findIndex(node => startX >= node.x + node.width - 5 && startX <= node.x + node.width + 5 && startY >= node.y + node.height - 5 && startY <= node.y + node.height + 5);
if (nodeIndex !== -1) {
dragging = true;
} else if (resizingIndex !== -1) {
resizing = true;
}
});
canvas.addEventListener('mousemove', function(e) {
if (dragging) {
const node = nodes[nodeIndex];
node.x += e.offsetX - startX;
node.y += e.offsetY - startY;
startX = e.offsetX;
startY = e.offsetY;
draw();
} else if (resizing) {
const node = nodes[resizingIndex];
node.width += e.offsetX - startX;
node.height += e.offsetY - startY;
startX = e.offsetX;
startY = e.offsetY;
draw();
}
});
canvas.addEventListener('mouseup', function(e) {
dragging = false;
resizing = false;
});
canvas.addEventListener('dblclick', function(e) {
const newNode = new Node(e.offsetX, e.offsetY, 80, 40, '#000', 'New Node');
nodes.push(newNode);
draw();
});
// 初始化绘制
draw();
</script>
</body>
</html>
注意:
- 以上代码仅供参考,你可以根据自己的需求进行修改和扩展。
- 代码中使用了 JavaScript 的事件处理函数来实现拖拽、缩放、添加和删除操作,你也可以使用其他方法来实现。
- 为了方便理解,代码中没有添加对连线操作的实现,你可以参考节点操作的实现来实现连线操作。
- 你可以在代码中添加更多功能,例如:
- 添加对节点文本的编辑功能
- 添加对节点样式的自定义功能
- 添加对节点连接线的自定义功能
- 添加对节点布局的控制功能
原文地址: https://www.cveoy.top/t/topic/mU4V 著作权归作者所有。请勿转载和采集!