Last active
February 9, 2026 01:38
-
-
Save amoshydra/beee25fce3fc0d17be4bc2b146a08660 to your computer and use it in GitHub Desktop.
CodeVinci - Snippets
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
| document.body.insertAdjacentHTML("beforeend", ` | |
| <style> | |
| body { | |
| font-family: system-ui, -apple-system, sans-serif; | |
| padding: 2rem; | |
| display: flex; | |
| flex-direction: column; | |
| align-items: center; | |
| background-color: #f8f9fa; | |
| } | |
| form { | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 12px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
| width: 100%; | |
| max-width: 400px; | |
| } | |
| h2 { margin-top: 0; font-size: 1.25rem; } | |
| .instructions { font-size: 0.85rem; color: #666; margin-bottom: 1.5rem; } | |
| button[type="submit"] { | |
| margin-top: 1rem; | |
| width: 100%; | |
| padding: 0.5rem; | |
| cursor: pointer; | |
| } | |
| </style> | |
| <form id="myForm"> | |
| <h2>Custom Component Form</h2> | |
| <p class="instructions">Open the <strong>Console</strong> to see the events fire.</p> | |
| <clearable-input id="myInput" name="username" placeholder="Type something..."></clearable-input> | |
| <button type="submit">Submit</button> | |
| </form> | |
| `); | |
| class ClearableInput extends HTMLElement { | |
| constructor() { | |
| super(); | |
| this.attachShadow({ mode: 'open' }); | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: inline-flex; | |
| align-items: center; | |
| border: 1px solid #ccc; | |
| border-radius: 6px; | |
| padding: 4px 10px; | |
| background: white; | |
| transition: border-color 0.2s; | |
| } | |
| :host(:focus-within) { | |
| border-color: #007bff; | |
| outline: 2px solid rgba(0,123,255,0.25); | |
| } | |
| input { | |
| border: none; | |
| outline: none; | |
| font-size: 1rem; | |
| flex: 1; | |
| padding: 4px 0; | |
| width: 100%; | |
| } | |
| button { | |
| background: #efefef; | |
| border: none; | |
| border-radius: 50%; | |
| width: 22px; | |
| height: 22px; | |
| margin-left: 8px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: #666; | |
| font-weight: bold; | |
| user-select: none; | |
| } | |
| button:hover { background: #e0e0e0; color: #333; } | |
| </style> | |
| <input type="text" /> | |
| <button type="button" id="clearBtn" aria-label="Clear input">✕</button> | |
| `; | |
| this._input = this.shadowRoot.querySelector('input'); | |
| this._clearBtn = this.shadowRoot.querySelector('#clearBtn'); | |
| } | |
| connectedCallback() { | |
| // Initial attribute sync | |
| this._input.placeholder = this.getAttribute('placeholder') || ''; | |
| this._input.value = this.getAttribute('value') || ''; | |
| // 1. CLEAR BUTTON LOGIC | |
| this._clearBtn.addEventListener('click', () => { | |
| if (this._input.value !== '') { | |
| this._input.value = ''; | |
| this._input.focus(); | |
| // Manually trigger events since the change was programatic | |
| this.dispatchEvent(new Event('input', { bubbles: true, composed: true })); | |
| this.dispatchEvent(new Event('change', { bubbles: true, composed: true })); | |
| } | |
| }); | |
| // 2. THE 'CHANGE' BRIDGE | |
| // Native 'change' is NOT composed (won't cross shadow boundary). | |
| // We catch it inside and fire a composed version from the host. | |
| this._input.addEventListener('change', (e) => { | |
| this.dispatchEvent(new Event('change', { bubbles: true, composed: true })); | |
| }); | |
| // NOTE: 'input' events ARE naturally composed, so they bubble out | |
| // on their own. We don't need a bridge for them, preventing double-fires. | |
| } | |
| // Expose value so that event.target.value works in external scripts | |
| get value() { return this._input.value; } | |
| set value(val) { this._input.value = val; } | |
| // Support standard attribute reflection if needed | |
| static get observedAttributes() { return ['placeholder', 'value']; } | |
| attributeChangedCallback(name, oldVal, newVal) { | |
| if (this._input && oldVal !== newVal) { | |
| this._input[name] = newVal; | |
| } | |
| } | |
| } | |
| // Register component | |
| customElements.define('clearable-input', ClearableInput); | |
| // --- EVENT LISTENERS (External) --- | |
| const inputComponent = document.getElementById('myInput'); | |
| // Test oninput | |
| inputComponent.oninput = (e) => { | |
| console.log('INPUT EVENT:', { | |
| value: e.target.value, | |
| type: e.type, | |
| target: e.target.tagName | |
| }); | |
| }; | |
| // Test onchange | |
| inputComponent.onchange = (e) => { | |
| console.log('CHANGE EVENT (Fires on blur or clear):', { | |
| value: e.target.value | |
| }); | |
| }; | |
| // Form Submit handling | |
| document.getElementById('myForm').onsubmit = (e) => { | |
| e.preventDefault(); | |
| console.log('FORM SUBMITTED. Component Value:', inputComponent.value); | |
| }; |
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
| import * as THREE from "https://esm.sh/three@0.182.0"; | |
| import gsap from "https://esm.sh/gsap@3.14.2"; | |
| document.body.insertAdjacentHTML("beforeend", ` | |
| <style> | |
| body { margin: 0; overflow: hidden; background: #111; font-family: 'Segoe UI', sans-serif; } | |
| .controls { | |
| position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); | |
| display: flex; gap: 10px; background: rgba(0,0,0,0.8); padding: 12px; border-radius: 50px; | |
| } | |
| button { | |
| padding: 10px 18px; border: none; border-radius: 20px; cursor: pointer; | |
| background: #333; color: white; transition: 0.2s; font-size: 12px; | |
| } | |
| button.active { background: #0088ff; box-shadow: 0 0 10px #0088ff; } | |
| #hud { position: absolute; top: 20px; left: 20px; color: #0088ff; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; } | |
| #help { position: absolute; top: 20px; right: 20px; color: #666; text-align: right; font-size: 13px; } | |
| </style> | |
| <div id="hud">Status: Idle</div> | |
| <div id="help">WASD to Move<br>SHIFT to Run<br>SPACE to Attack</div> | |
| <div class="controls"> | |
| <button onclick="setState('SIT')" id="btn-SIT">Sit Down</button> | |
| <button onclick="setState('IDLE')" id="btn-IDLE">Reset</button> | |
| </div> | |
| `); | |
| // --- SCENE SETUP --- | |
| const scene = new THREE.Scene(); | |
| scene.background = new THREE.Color(0x050505); | |
| scene.fog = new THREE.Fog(0x050505, 5, 15); | |
| const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 100); | |
| const renderer = new THREE.WebGLRenderer({ antialias: true }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| renderer.shadowMap.enabled = true; | |
| document.body.appendChild(renderer.domElement); | |
| const ambient = new THREE.AmbientLight(0xffffff, 0.4); | |
| const sun = new THREE.DirectionalLight(0xffffff, 1.2); | |
| sun.position.set(5, 10, 5); | |
| sun.castShadow = true; | |
| scene.add(ambient, sun); | |
| // Floor Grid | |
| const grid = new THREE.GridHelper(50, 50, 0x222222, 0x111111); | |
| scene.add(grid); | |
| const floor = new THREE.Mesh(new THREE.PlaneGeometry(50, 50), new THREE.MeshStandardMaterial({ color: 0x050505 })); | |
| floor.rotation.x = -Math.PI / 2; | |
| floor.receiveShadow = true; | |
| scene.add(floor); | |
| // --- CHARACTER SYSTEM ---\ | |
| const player = new THREE.Group(); | |
| scene.add(player); | |
| function createLimb(radius, height, color = 0xE8BEAC) { | |
| const pivot = new THREE.Group(); | |
| const mesh = new THREE.Mesh( | |
| new THREE.CapsuleGeometry(radius, height, 4, 10), | |
| new THREE.MeshStandardMaterial({ color, roughness: 0.7 }) | |
| ); | |
| mesh.position.y = -height / 2; | |
| mesh.castShadow = true; | |
| pivot.add(mesh); | |
| return pivot; | |
| } | |
| // Body creation | |
| const hips = new THREE.Group(); hips.position.y = 1; player.add(hips); | |
| const torso = createLimb(0.2, 0.45, 0x2955dd); torso.position.y = 0.65; hips.add(torso); | |
| const head = new THREE.Mesh(new THREE.SphereGeometry(0.14), new THREE.MeshStandardMaterial({ color: 0xE8BEAC })); | |
| head.position.y = 0.35; torso.add(head); | |
| const leftArm = createLimb(0.06, 0.4); leftArm.position.set(0.25, 0.1, 0); torso.add(leftArm); | |
| const leftForearm = createLimb(0.05, 0.35); leftForearm.position.y = -0.45; leftArm.add(leftForearm); | |
| const rightArm = createLimb(0.06, 0.4); rightArm.position.set(-0.25, 0.1, 0); torso.add(rightArm); | |
| const rightForearm = createLimb(0.05, 0.35); rightForearm.position.y = -0.45; rightArm.add(rightForearm); | |
| const leftThigh = createLimb(0.08, 0.45); leftThigh.position.set(0.15, 0, 0); hips.add(leftThigh); | |
| const rightThigh = createLimb(0.08, 0.45); rightThigh.position.set(-0.15, 0, 0); hips.add(rightThigh); | |
| const leftCalf = createLimb(0.07, 0.45); leftCalf.position.y = -0.5; leftThigh.add(leftCalf); | |
| const rightCalf = createLimb(0.07, 0.45); rightCalf.position.y = -0.5; rightThigh.add(rightCalf); | |
| // --- MOVEMENT LOGIC --- | |
| let state = 'IDLE'; | |
| const keys = { w: false, a: false, s: false, d: false, shift: false }; | |
| const velocity = new THREE.Vector3(); | |
| let targetRotation = 0; | |
| window.addEventListener('keydown', (e) => { | |
| const key = e.key.toLowerCase(); | |
| if (keys.hasOwnProperty(key)) keys[key] = true; | |
| if (e.code === 'Space') attack(); | |
| }); | |
| window.addEventListener('keyup', (e) => { | |
| const key = e.key.toLowerCase(); | |
| if (keys.hasOwnProperty(key)) keys[key] = false; | |
| }); | |
| window.setState = (s) => { | |
| state = s; | |
| document.getElementById('hud').innerText = `Status: ${s}`; | |
| if (s === 'SIT') { | |
| gsap.to(hips.position, { y: 0.45, duration: 0.5 }); | |
| gsap.to([leftThigh.rotation, rightThigh.rotation], { x: -Math.PI/2, duration: 0.5 }); | |
| gsap.to([leftCalf.rotation, rightCalf.rotation], { x: Math.PI/2, duration: 0.5 }); | |
| } else { | |
| gsap.to(hips.position, { y: 1, duration: 0.3 }); | |
| gsap.to([leftThigh.rotation, rightThigh.rotation, leftCalf.rotation, rightCalf.rotation], { x: 0, duration: 0.3 }); | |
| } | |
| }; | |
| // Sword Generation | |
| const sword = new THREE.Group(); | |
| const blade = new THREE.Mesh(new THREE.BoxGeometry(0.04, 0.7, 0.01), new THREE.MeshStandardMaterial({color: 0xffffff, metalness: 1})); | |
| blade.position.y = 0.4; sword.add(blade); | |
| const hilt = new THREE.Mesh(new THREE.BoxGeometry(0.15, 0.03, 0.04), new THREE.MeshStandardMaterial({color: 0x333333})); | |
| hilt.position.y = 0.1; sword.add(hilt); | |
| sword.rotation.x = Math.PI / 2; | |
| sword.position.y = -0.35; | |
| rightForearm.add(sword); | |
| function attack() { | |
| if (state === 'ATTACK') return; | |
| const prevState = state; | |
| state = 'ATTACK'; | |
| const tl = gsap.timeline({ onComplete: () => state = prevState }); | |
| tl.to(rightArm.rotation, { x: -Math.PI * 0.8, duration: 0.1 }) | |
| .to(rightArm.rotation, { x: 0, duration: 0.3, ease: "back.out" }); | |
| } | |
| // --- MAIN LOOP --- | |
| const clock = new THREE.Clock(); | |
| const camOffset = new THREE.Vector3(0, 3, 5); | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| const dt = clock.getDelta(); | |
| const t = clock.getElapsedTime(); | |
| // 1. Calculate Input | |
| let moveX = Number(keys.d) - Number(keys.a); | |
| let moveZ = Number(keys.s) - Number(keys.w); | |
| const isMoving = moveX !== 0 || moveZ !== 0; | |
| if (state !== 'SIT' && state !== 'ATTACK') { | |
| if (isMoving) { | |
| state = keys.shift ? 'RUN' : 'WALK'; | |
| // Determine rotation angle based on keys | |
| targetRotation = Math.atan2(moveX, moveZ); | |
| player.rotation.y = THREE.MathUtils.lerp(player.rotation.y, targetRotation, 0.15); | |
| // Move Forward relative to character facing | |
| const moveSpeed = state === 'RUN' ? 5 : 2.5; | |
| player.translateZ(moveSpeed * dt); | |
| } else { | |
| state = 'IDLE'; | |
| } | |
| } | |
| document.getElementById('hud').innerText = `Status: ${state}`; | |
| // 2. Procedural Animation Math | |
| if (state === 'WALK' || state === 'RUN') { | |
| const speedMult = state === 'RUN' ? 12 : 7; | |
| const amp = state === 'RUN' ? 0.8 : 0.5; | |
| leftThigh.rotation.x = Math.sin(t * speedMult) * amp; | |
| rightThigh.rotation.x = Math.sin(t * speedMult + Math.PI) * amp; | |
| leftCalf.rotation.x = Math.max(0, Math.sin(t * speedMult - 1) * amp * 1.2); | |
| rightCalf.rotation.x = Math.max(0, Math.sin(t * speedMult + Math.PI - 1) * amp * 1.2); | |
| leftArm.rotation.x = Math.sin(t * speedMult + Math.PI) * amp; | |
| if (state !== 'ATTACK') rightArm.rotation.x = Math.sin(t * speedMult) * amp; | |
| hips.position.y = 1 + Math.abs(Math.sin(t * speedMult)) * 0.05; | |
| } else if (state === 'IDLE') { | |
| hips.position.y = 1 + Math.sin(t * 2) * 0.02; | |
| leftArm.rotation.z = 0.1 + Math.sin(t * 2) * 0.02; | |
| rightArm.rotation.z = -0.1 - Math.sin(t * 2) * 0.02; | |
| } | |
| // 3. Smooth Follow Camera | |
| const targetCamPos = player.position.clone().add(camOffset); | |
| camera.position.lerp(targetCamPos, 0.05); | |
| camera.lookAt(player.position.x, player.position.y + 0.5, player.position.z); | |
| renderer.render(scene, camera); | |
| } | |
| animate(); | |
| window.addEventListener('resize', () => { | |
| camera.aspect = window.innerWidth / window.innerHeight; | |
| camera.updateProjectionMatrix(); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment