Started working on arrows
This commit is contained in:
@@ -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
97
projects/script.js
Normal 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));
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user