Started working on arrows

This commit is contained in:
2026-03-27 20:44:27 +01:00
parent 94efc03593
commit 535a4584aa
3 changed files with 148 additions and 11 deletions

View File

@@ -4,25 +4,24 @@
<meta charset="utf-8">
<title>Ayabusa club - Projects</title>
<link rel="stylesheet" href="./style.css">
<!--<script src="script.js"></script> -->
</head>
<body>
<body id="body">
<div style="display: flex; direction: row; justify-content: center; margin-bottom: 50px;">
<div class="disbox">
<div class="disbox node" id="n0">
<div class="disboxh">
<img class="ico" src="../assets/gitico.png"></img>
<img class="ico" src="../assets/blogico.png"></img>
</div>
<p class="disboxp">
loc_projects:<br><br>
During my <b>dev journey</b>, I had the opportunity to create some cool projects.<br><br>
During my <b>dev journey</b>, I have the opportunity to create some cool projects.<br><br>
I've collected here those that might <b>pick your interest</b>.
</p>
</div>
</div>
<div style="display: flex; direction: row; justify-content: center; margin-bottom: 50px;">
<div>
<div class="disbox" style="margin-bottom: 50px;">
<div class="disbox node" id="n1" style="margin-bottom: 50px;">
<div class="disboxh">
<img class="ico" src="../assets/gitico.png"></img>
<img class="ico" src="../assets/blogico.png"></img>
@@ -37,7 +36,7 @@
I develloped it with <b>Golang</b> for the backend and <b>svelte</b> for the frontend, and it has worked pretty well for me :D
</p>
</div>
<div class="disbox">
<div class="disbox node" id="n2">
<div class="disboxh">
<img class="ico" src="../assets/gitico.png"></img>
<img class="ico" src="../assets/blogico.png"></img>
@@ -71,15 +70,15 @@
</div>
</div>
<div style="display: flex; direction: row; justify-content: center; margin-bottom: 50px;">
<div class="disbox">
<div class="disbox node" id="n3">
<div class="disboxh">
<img class="ico" src="../assets/gitico.png"></img>
<img class="ico" src="../assets/blogico.png"></img>
</div>
<p class="disboxp">
loc_a_la_carte:<br><br>
During my <b>dev journey</b>, I had the opportunity to create some cool projects.<br><br>
I've collected here those that might <b>pick your interest</b>.
<b>À la carte</b> is a <b>game</b> I built for the <b>Numworks</b>, in the context of a <a href="https://tiplanet.org/">TI Planet</a> contest.
It's built in <b>python</b> and optimized for it to <b>run smoothly</b> on the target <b>calculator</b>.
</p>
</div>
</div>
@@ -91,10 +90,31 @@
</div>
<p class="disboxp">
loc_minecraft_mods:<br><br>
During my <b>dev journey</b>, I had the opportunity to create some cool projects.<br><br>
I've collected here those that might <b>pick your interest</b>.
During some of my (too) many <b>Minecraft two weeks phases</b>, I develloped some <b>minecraft mods</b>. Mainly in <b>Fabric</b>,
I even did a <a href="https://blog.ayabusa.dev/2023/10/30/how-minecraft-mods-works-for-dummies/">tutorial to get
started</a> and be introduced to the wonderfull world of <b>Mixins</b> xD.<br/><br/>
<a href="https://modrinth.com/mod/no-more-spire">No more spire</a>: I did this mod for the server that I was playing back then <b>OriginRealms</b>.
Everyone was spamming about the <b>spire update</b> in chat, so I decided to do some <b>cleanup</b> and free the chat from this <b>pollution</b>.<br/><br/>
<a href="https://modrinth.com/mod/modern-chunk-detector">Modern chunk detector</a>: This mod was made for the server <b>9b9t</b> that my friend and I were playing. It <b>highlights</b> the chunk that were
generated in <b>modern version of MC</b>. Great to track bases trails ;)
</p>
</div>
</div>
<svg id="arrows">
<defs>
<!-- Arrowhead marker — inherits line color via context-stroke -->
<marker id="head"
viewBox="0 0 10 10" refX="8" refY="5"
markerWidth="6" markerHeight="6"
orient="auto-start-reverse">
<path d="M1 1L9 5L1 9Z"
fill="context-stroke" stroke="none"/>
</marker>
</defs>
<!-- One <path> per connection (added by JS below) -->
</svg>
<script src="script.js"></script>
</body>
</html>

97
projects/script.js Normal file
View File

@@ -0,0 +1,97 @@
// ─── Configuration ────────────────────────────────────────────
// Each pair is [sourceId, targetId].
// Arrows go from the bottom-center of the source
// to the top-center of the target.
const CONNECTIONS = [
['n0', 'n1'],
['n1', 'n2'],
['n2', 'n3'],
];
// ─── Setup ────────────────────────────────────────────────────
const scene = document.getElementById('body');
const svg = document.getElementById('arrows');
// Create one SVG <path> per connection
const pathEls = CONNECTIONS.map(() => {
const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
p.setAttribute('class', 'arrow-path');
p.setAttribute('marker-end', 'url(#head)');
svg.appendChild(p);
return p;
});
// ─── Core: Manhattan path between two elements ────────────────
// r1 = bounding rect of source, r2 = bounding rect of target
// Both rects are relative to the scene container.
function manhattanPath(r1, r2) {
const x1 = r1.left + r1.width / 2; // bottom-center of source
const y1 = r1.top + r1.height + 10;
const x2 = r2.left + r2.width / 2; // top-center of target
const y2 = r2.top + 5; // stop 8px above target (arrowhead gap)
const ymid = y1 + (y2 - y1) / 2; // elbow halfway between the two
// M: move to source bottom
// L: go straight down to mid-y
// L: go horizontally to target x
// L: go straight down to target top
return `M ${x1} ${y1}
L ${x1} ${ymid}
L ${x2} ${ymid}
L ${x2} ${y2}`;
}
// ─── Redraw all arrows ────────────────────────────────────────
function redraw() {
const sceneRect = scene.getBoundingClientRect();
CONNECTIONS.forEach(([srcId, tgtId], i) => {
const src = document.getElementById(srcId).getBoundingClientRect();
const tgt = document.getElementById(tgtId).getBoundingClientRect();
// Convert from viewport coords → scene-local coords
const r1 = {
left: src.left - sceneRect.left,
top: src.top - sceneRect.top,
width: src.width,
height: src.height,
};
const r2 = {
left: tgt.left - sceneRect.left,
top: tgt.top - sceneRect.top,
width: tgt.width,
height: tgt.height,
};
pathEls[i].setAttribute('d', manhattanPath(r1, r2));
});
}
// ─── Drag logic ───────────────────────────────────────────────
document.querySelectorAll('.node').forEach(node => {
node.addEventListener('mousedown', e => {
e.preventDefault();
const startX = e.clientX;
const startY = e.clientY;
const originL = parseInt(node.style.left);
const originT = parseInt(node.style.top);
const onMove = e => {
node.style.left = Math.max(0, originL + e.clientX - startX) + 'px';
node.style.top = Math.max(0, originT + e.clientY - startY) + 'px';
redraw();
};
const onUp = () => {
window.removeEventListener('mousemove', onMove);
window.removeEventListener('mouseup', onUp);
};
window.addEventListener('mousemove', onMove);
window.addEventListener('mouseup', onUp);
});
});
// ─── Initial draw ─────────────────────────────────────────────
// Wait two frames so the browser has laid out the divs
requestAnimationFrame(() => requestAnimationFrame(redraw));

View File

@@ -51,6 +51,26 @@ a {
margin-bottom: -3px;
}
/* ─── SVG overlay ────────────────────────────────────────── */
#arrows {
position: absolute;
inset: 0; /* fill the scene */
width: 100%;
height: 100%;
pointer-events: none; /* clicks pass through to divs */
overflow: visible; /* arrows can leave the box if needed */
}
/* Arrow path style */
.arrow-path {
fill: none;
stroke: #aaa9a2;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
}
/* Win32 classic scrollbar */
::-webkit-scrollbar {
width: 17px;