This is a simple test of an HTML canvas, without JointJS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
<style>
#canvas {
border: 1px solid #000;
}
</style>
<div class="relative h-[800px] w-[1088px]">
<canvas id="canvas" class="absolute bottom-0 right-0" width="750" height="750"></canvas>
<button id="toggleModeButton">Toggle Mode</button>
<script>
const toggleModeButton = document.getElementById("toggleModeButton");
let isNodePlacingMode = true; // Initially, start with node placing mode
toggleModeButton.addEventListener("click", () => {
isNodePlacingMode = !isNodePlacingMode; // Toggle the mode
});
const canvas = document.getElementById("canvas")
const ctx = canvas.getContext("2d")
const ghostCircle = { x: 0, y: 0, radius: 0, color: "#ccc" }
const circles = []
let circleCounter = 0
let selectedNode = null;
let pathStartPoint = null;
canvas.addEventListener("mousemove", (e) => {
if (isNodePlacingMode) {
const mouseX = e.clientX - canvas.getBoundingClientRect().left
const mouseY = e.clientY - canvas.getBoundingClientRect().top
ghostCircle.x = mouseX
ghostCircle.y = mouseY
ghostCircle.radius = 30
} else {
if (!isNodePlacingMode && selectedNode && pathStartPoint) {
const mouseX = e.clientX - canvas.getBoundingClientRect().left;
const mouseY = e.clientY - canvas.getBoundingClientRect().top;
// Clear the canvas and redraw everything
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawCircles();
drawConnections(); // Draw connections as well
// Draw the path from the selected node to the mouse position
ctx.beginPath();
ctx.moveTo(selectedNode.x, selectedNode.y);
ctx.lineTo(mouseX, mouseY);
ctx.strokeStyle = "#000"; // Adjust the path color as needed
ctx.lineWidth = 2;
ctx.stroke();
ctx.closePath();
}
}
});
canvas.addEventListener("click", (e) => {
if (isNodePlacingMode) {
const circleRadius = 30
const circleColor = `#000`
const newCircle = { id: ++circleCounter, x: ghostCircle.x, y: ghostCircle.y, radius: circleRadius, color: circleColor }
circles.push(newCircle)
ghostCircle.radius = 0
drawCircles()
} else {
const mouseX = e.clientX - canvas.getBoundingClientRect().left;
const mouseY = e.clientY - canvas.getBoundingClientRect().top;
// Check if the click is inside a node
for (const circle of circles) {
const distance = Math.sqrt(
(mouseX - circle.x) ** 2 + (mouseY - circle.y) ** 2
);
if (distance < circle.radius) {
// Clicked inside a node, select it
selectedNode = circle;
return;
}
}
pathStartPoint = { x: selectedNode.x, y: selectedNode.y };
console.log(pathStartPoint)
// If not inside a node, start a path if a node is selected
if (selectedNode) {
}
}
});
canvas.addEventListener("mouseup", (e) => {
if (isNodePlacingMode) {
// Handle node placing mode
// ...
} else {
if (selectedNode && pathStartPoint) {
const mouseX = e.clientX - canvas.getBoundingClientRect().left;
const mouseY = e.clientY - canvas.getBoundingClientRect().top;
// Check if the release is inside a node
for (const circle of circles) {
const distance = Math.sqrt(
(mouseX - circle.x) ** 2 + (mouseY - circle.y) ** 2
);
if (distance < circle.radius) {
// Released inside a node, create a connection
const newConnection = {
from: selectedNode.id,
to: circle.id,
};
drawConnections()
break;
}
}
}
// Reset selection and path start point
selectedNode = null;
pathStartPoint = null;
}
});
function drawCircle(x, y, radius, color, id) {
ctx.beginPath()
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.fillStyle = color
ctx.fill()
ctx.closePath()
ctx.fillStyle = "#fff"
ctx.font = "25px SFPro-Text-Regular"
const textWidth = ctx.measureText(id).width;
const textX = x - textWidth / 2;
const textY = y + 7;
ctx.fillText(id, textX, textY);
}
function drawCircles() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
circles.forEach((circle) => {
drawCircle(circle.x, circle.y, circle.radius, circle.color, circle.id)
})
drawGhostCircle()
}
function drawGhostCircle() {
const { x, y, radius, color } = ghostCircle
if (radius > 0) {
ctx.beginPath()
ctx.arc(x, y, radius, 0, Math.PI * 2)
ctx.strokeStyle = color
ctx.lineWidth = 2
ctx.stroke()
ctx.closePath()
}
}
function drawConnections() {
for (const connection of connections) {
const fromNode = circles.find(circle => circle.id === connection.from);
const toNode = circles.find(circle => circle.id === connection.to);
ctx.beginPath();
ctx.moveTo(fromNode.x, fromNode.y);
ctx.lineTo(toNode.x, toNode.y);
ctx.strokeStyle = "#000"; // Adjust the path color as needed
ctx.lineWidth = 2;
ctx.stroke();
ctx.closePath();
}
}
function animate() {
drawCircles()
requestAnimationFrame(animate)
}
animate()
</script>
</div>