Created
March 10, 2026 01:54
-
-
Save EncodeTheCode/601ae2ac716269ca8faa677e411b2f20 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>PS1 Demo One Menu</title> | |
| <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> | |
| <style> | |
| :root{ | |
| --menu-radius:420px; | |
| --label-size:48px; | |
| --ribbon-height:120px; | |
| --dot-spacing:25px; | |
| } | |
| body{ | |
| margin:0; | |
| overflow:hidden; | |
| background:#021822; | |
| font-family:Trebuchet MS, Arial; | |
| } | |
| #bgCanvas{ | |
| position:fixed; | |
| width:100%; | |
| height:100%; | |
| z-index:0; | |
| } | |
| .stage{ | |
| position:absolute; | |
| width:100%; | |
| height:100%; | |
| display:flex; | |
| align-items:center; | |
| justify-content:center; | |
| perspective:1200px; | |
| } | |
| .menu3d{ | |
| position:relative; | |
| width:900px; | |
| height:600px; | |
| transform-style:preserve-3d; | |
| } | |
| .menu-item{ | |
| position:absolute; | |
| left:50%; | |
| top:50%; | |
| transform-style:preserve-3d; | |
| transform-origin:center; | |
| } | |
| svg{ | |
| overflow:visible; | |
| } | |
| .label-text{ | |
| font-size:48px; | |
| font-weight:900; | |
| fill:#eaff6a; | |
| stroke:#000; | |
| stroke-width:2px; | |
| paint-order:stroke fill; | |
| } | |
| .dot{ | |
| fill:#ff7a2c; | |
| } | |
| .front{ | |
| opacity:1; | |
| } | |
| .side{ | |
| opacity:0.45; | |
| } | |
| .back{ | |
| opacity:0.2; | |
| } | |
| #star{ | |
| position:absolute; | |
| left:50%; | |
| top:50%; | |
| transform:translate(-50%,-50%); | |
| width:300px; | |
| z-index:5; | |
| } | |
| .submenu{ | |
| position:absolute; | |
| bottom:80px; | |
| width:100%; | |
| text-align:center; | |
| color:#eaffc8; | |
| font-size:22px; | |
| font-weight:bold; | |
| z-index:20; | |
| } | |
| .submenu div{ | |
| margin:6px 0; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <canvas id="bgCanvas"></canvas> | |
| <div class="stage"> | |
| <img id="star" src="https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/Starfish_red.svg/512px-Starfish_red.svg.png"> | |
| <div class="menu3d" id="menu"></div> | |
| <div class="submenu" id="submenu"></div> | |
| </div> | |
| <script> | |
| const labels=[ | |
| { name:"Games", items:["Tomb Raider 3","Tekken 3","Crash Bandicoot"] }, | |
| { name:"Video", items:["Play Movie","Scene Select","Options"] }, | |
| { name:"Music", items:["Track 1","Track 2","Track 3"] }, | |
| { name:"Memory", items:["Memory Card 1","Memory Card 2","Format Card"] }, | |
| { name:"Network", items:["Connect","Settings","Status"] } | |
| ]; | |
| const radius=420; | |
| const step=360/labels.length; | |
| let rotation=0; | |
| let speed=-6; | |
| let selected=0; | |
| let inMenu=false; | |
| const menu=$("#menu"); | |
| function createLabel(text){ | |
| let spacing=25; | |
| return ` | |
| <svg width="500" height="200" viewBox="-250 -100 500 200"> | |
| <text class="label-text" text-anchor="middle" x="0" y="0"> | |
| ${text} | |
| </text> | |
| <circle class="dot" cx="${text.length*14 + spacing}" cy="-8" r="8"/> | |
| </svg> | |
| `; | |
| } | |
| labels.forEach((l,i)=>{ | |
| let el=$(`<div class="menu-item">${createLabel(l.name)}</div>`); | |
| el.attr("data-index",i); | |
| menu.append(el); | |
| }); | |
| function updateMenu(){ | |
| $(".menu-item").each(function(){ | |
| let i=parseInt($(this).attr("data-index")); | |
| let angle=i*step+rotation; | |
| let rad=angle*Math.PI/180; | |
| let z=radius*Math.cos(rad); | |
| let x=radius*Math.sin(rad); | |
| let scale=(z+radius)/(2*radius); | |
| let tilt=Math.sin(rad)*20; | |
| $(this).css("transform", | |
| `translate(-50%,-50%) translateX(${x}px) translateZ(${z}px) rotateX(${tilt}deg) scale(${0.6+scale*0.5})` | |
| ); | |
| let diff=Math.abs(i-selected); | |
| $(this).removeClass("front side back"); | |
| if(diff===0)$(this).addClass("front"); | |
| else if(diff===1 || diff===labels.length-1)$(this).addClass("side"); | |
| else $(this).addClass("back"); | |
| }); | |
| } | |
| function animate(){ | |
| if(!inMenu){ | |
| rotation+=speed*0.016; | |
| } | |
| updateMenu(); | |
| requestAnimationFrame(animate); | |
| } | |
| animate(); | |
| function openMenu(){ | |
| let menuItems=labels[selected].items; | |
| let html=""; | |
| menuItems.forEach(i=>{ | |
| html+=`<div>${i}</div>`; | |
| }); | |
| $("#submenu").html(html); | |
| inMenu=true; | |
| } | |
| function closeMenu(){ | |
| $("#submenu").html(""); | |
| inMenu=false; | |
| } | |
| $(document).keydown(function(e){ | |
| if(e.key==="ArrowRight" && !inMenu){ | |
| selected=(selected+1)%labels.length; | |
| rotation=-selected*step; | |
| } | |
| if(e.key==="ArrowLeft" && !inMenu){ | |
| selected=(selected-1+labels.length)%labels.length; | |
| rotation=-selected*step; | |
| } | |
| if(e.key==="Enter"){ | |
| openMenu(); | |
| } | |
| if(e.key==="Escape"){ | |
| closeMenu(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment