Update index.php
This commit is contained in:
210
index.php
210
index.php
@@ -508,6 +508,68 @@ try {
|
||||
gap:6px;
|
||||
}
|
||||
}
|
||||
|
||||
/* ===== Keyboard player + selection styles ===== */
|
||||
|
||||
#kb-player{
|
||||
position:fixed;
|
||||
width:26px;
|
||||
height:26px;
|
||||
border-radius:40%;
|
||||
background:radial-gradient(circle at 30% 20%, #ffffff, #7cf5ff);
|
||||
box-shadow:
|
||||
0 0 10px rgba(124,245,255,.9),
|
||||
0 0 26px rgba(124,245,255,.5);
|
||||
transform:translate(-50%, -50%);
|
||||
z-index:999;
|
||||
pointer-events:none;
|
||||
}
|
||||
|
||||
#kb-player::after{
|
||||
content:"";
|
||||
position:absolute;
|
||||
left:50%;
|
||||
top:50%;
|
||||
width:4px;
|
||||
height:9px;
|
||||
border-radius:10px;
|
||||
background:rgba(0,0,0,.35);
|
||||
transform:translate(-50%,-80%);
|
||||
}
|
||||
|
||||
#kb-hint{
|
||||
position:fixed;
|
||||
bottom:10px;
|
||||
left:50%;
|
||||
transform:translateX(-50%);
|
||||
padding:6px 12px;
|
||||
font-size:11px;
|
||||
border-radius:999px;
|
||||
background:rgba(0,0,0,.65);
|
||||
border:1px solid rgba(255,255,255,.10);
|
||||
z-index:998;
|
||||
color:var(--muted);
|
||||
}
|
||||
#kb-hint kbd{
|
||||
display:inline-block;
|
||||
min-width:18px;
|
||||
padding:1px 5px;
|
||||
border-radius:4px;
|
||||
border:1px solid rgba(255,255,255,.3);
|
||||
font-size:10px;
|
||||
font-weight:600;
|
||||
text-align:center;
|
||||
background:rgba(255,255,255,.06);
|
||||
margin:0 1px;
|
||||
}
|
||||
|
||||
/* Highlight when orb is overlapping a nav link */
|
||||
.mk-nav-link.kb-highlight{
|
||||
background:radial-gradient(circle at 0 0,var(--accent-soft),transparent 55%);
|
||||
border-color:var(--accent-border);
|
||||
color:var(--text);
|
||||
transform:translateX(2px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -646,5 +708,153 @@ try {
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Keyboard-player orb + hint -->
|
||||
<div id="kb-player"></div>
|
||||
<div id="kb-hint">
|
||||
Move with <kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd>, stand on a nav item, press <kbd>E</kbd> to select.
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
const player = document.getElementById('kb-player');
|
||||
const hint = document.getElementById('kb-hint');
|
||||
const interactables = Array.from(document.querySelectorAll('.mk-nav-link'));
|
||||
|
||||
// Initial position (near left side / sidebar)
|
||||
let x = 160;
|
||||
let y = 220;
|
||||
const speed = 230; // pixels per second
|
||||
const keys = { w:false, a:false, s:false, d:false };
|
||||
|
||||
function updatePlayer(){
|
||||
player.style.left = x + 'px';
|
||||
player.style.top = y + 'px';
|
||||
}
|
||||
updatePlayer();
|
||||
|
||||
// Key handling
|
||||
window.addEventListener('keydown', (e)=>{
|
||||
switch(e.code){
|
||||
case 'KeyW':
|
||||
case 'KeyA':
|
||||
case 'KeyS':
|
||||
case 'KeyD':
|
||||
case 'KeyE':
|
||||
e.preventDefault(); // stop page scrolling on these keys
|
||||
break;
|
||||
}
|
||||
|
||||
if(e.code === 'KeyW') keys.w = true;
|
||||
if(e.code === 'KeyA') keys.a = true;
|
||||
if(e.code === 'KeyS') keys.s = true;
|
||||
if(e.code === 'KeyD') keys.d = true;
|
||||
|
||||
if(e.code === 'KeyE'){
|
||||
tryInteract();
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('keyup', (e)=>{
|
||||
if(e.code === 'KeyW') keys.w = false;
|
||||
if(e.code === 'KeyA') keys.a = false;
|
||||
if(e.code === 'KeyS') keys.s = false;
|
||||
if(e.code === 'KeyD') keys.d = false;
|
||||
});
|
||||
|
||||
// Movement loop
|
||||
let lastTime = null;
|
||||
function loop(timestamp){
|
||||
if(lastTime === null) lastTime = timestamp;
|
||||
const dt = (timestamp - lastTime) / 1000;
|
||||
lastTime = timestamp;
|
||||
|
||||
let vx = 0, vy = 0;
|
||||
if(keys.w) vy -= 1;
|
||||
if(keys.s) vy += 1;
|
||||
if(keys.a) vx -= 1;
|
||||
if(keys.d) vx += 1;
|
||||
|
||||
if(vx !== 0 || vy !== 0){
|
||||
const len = Math.hypot(vx, vy) || 1;
|
||||
vx /= len;
|
||||
vy /= len;
|
||||
|
||||
x += vx * speed * dt;
|
||||
y += vy * speed * dt;
|
||||
|
||||
const half = 13;
|
||||
const maxW = window.innerWidth;
|
||||
const maxH = window.innerHeight;
|
||||
|
||||
if(x < half) x = half;
|
||||
if(y < half) y = half;
|
||||
if(x > maxW - half) x = maxW - half;
|
||||
if(y > maxH - half) y = maxH - half;
|
||||
|
||||
updatePlayer();
|
||||
}
|
||||
|
||||
updateHighlights();
|
||||
requestAnimationFrame(loop);
|
||||
}
|
||||
requestAnimationFrame(loop);
|
||||
|
||||
function updateHighlights(){
|
||||
const pRect = player.getBoundingClientRect();
|
||||
let best = null;
|
||||
let bestArea = 0;
|
||||
|
||||
interactables.forEach(el=>{
|
||||
const r = el.getBoundingClientRect();
|
||||
const overlapX = Math.max(0, Math.min(pRect.right, r.right) - Math.max(pRect.left, r.left));
|
||||
const overlapY = Math.max(0, Math.min(pRect.bottom, r.bottom) - Math.max(pRect.top, r.top));
|
||||
const area = overlapX * overlapY;
|
||||
|
||||
if(area > 1 && area > bestArea){
|
||||
bestArea = area;
|
||||
best = el;
|
||||
}
|
||||
});
|
||||
|
||||
interactables.forEach(el => el.classList.remove('kb-highlight'));
|
||||
if(best){
|
||||
best.classList.add('kb-highlight');
|
||||
}
|
||||
}
|
||||
|
||||
function tryInteract(){
|
||||
const highlighted = document.querySelector('.mk-nav-link.kb-highlight');
|
||||
if(!highlighted) return;
|
||||
|
||||
const href = highlighted.getAttribute('href');
|
||||
|
||||
if(href && href.startsWith('#') && href.length > 1){
|
||||
const target = document.querySelector(href);
|
||||
if(target){
|
||||
target.scrollIntoView({ behavior:'smooth', block:'start' });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(href && href !== '#'){
|
||||
window.location.href = href;
|
||||
} else {
|
||||
highlighted.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust player if window size changes (keeps it on-screen)
|
||||
window.addEventListener('resize', ()=>{
|
||||
const half = 13;
|
||||
const maxW = window.innerWidth;
|
||||
const maxH = window.innerHeight;
|
||||
if(x > maxW - half) x = maxW - half;
|
||||
if(y > maxH - half) y = maxH - half;
|
||||
updatePlayer();
|
||||
});
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user