WEBLEB
Home
Editor
Accedi
Pro
Italiano
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Manopole del volume
682
kevekıbhack
Apri nell'Editor
Pubblica il Tuo Codice
Consigliato
31 July 2025
Il sussurratore del codice
3 July 2025
Esempio di codice del menu a discesa HTML
15 May 2025
Modello di sito Web di e-commerce HTML CSS
HTML
Copy
CSS
Copy
/* :root kısmına yeni renkler ekleyin */ :root { /* ...diğer değişkenler... */ --purple: hsl(270, 90%, 60%); --pink: hsl(330, 90%, 60%); --yellow: hsl(60, 90%, 60%); --cyan: hsl(180, 90%, 60%); } /* Yeni renk sınıfları ekleyin */ .volume--rainbow .volume__dot--filled { --dot-color: var(--red); animation: rainbow 5s linear infinite; } .volume--gradient .volume__dot--filled { --dot-color: var(--blue); animation: gradientGlow 3s ease-in-out infinite alternate; } .volume--pastel .volume__dot--filled { --dot-color: var(--green); filter: brightness(1.2); } /* Animasyonlar */ @keyframes rainbow { 0% { background-color: var(--red); } 14% { background-color: var(--orange); } 28% { background-color: var(--yellow); } 42% { background-color: var(--green); } 57% { background-color: var(--blue); } 71% { background-color: var(--indigo); } 85% { background-color: var(--purple); } 100% { background-color: var(--red); } } @keyframes gradientGlow { 0% { box-shadow: 0 0 5px var(--blue); } 100% { box-shadow: 0 0 15px var(--cyan); } }
JS
Copy
import React, { StrictMode, useEffect, useRef, useState } from "https://esm.sh/react"; import { createRoot } from "https://esm.sh/react-dom/client"; import gsap from "https://esm.sh/gsap"; import { useGSAP } from "https://esm.sh/@gsap/react"; import { Draggable } from "https://esm.sh/gsap/Draggable"; gsap.registerPlugin(useGSAP, Draggable); createRoot(document.getElementById("root")!).render( <StrictMode> <main> <VolumeDial ticks={24} color="rainbow" volume={0.7} label="Party Mode" /> <VolumeDial ticks={16} color="gradient" volume={0.4} label="Neon Glow" /> <VolumeDial ticks={12} color="pastel" volume={0.2} label="Soft Tones" /> </main> </StrictMode> ); function VolumeDial({ color, ticks, volume = 0, label = "Volume", children }: VolumeDialProps) { const [isKeyDown, setIsKeydown] = useState(false); const dialRef = useRef<HTMLButtonElement>(null); const rootClass = `volume${color ? ` volume--${color}` : ''}`; // volume state const [vol, setVol] = useState(volume); const maxTick = Math.max(1, ticks) || 1; const tick = Math.max(0, vol * maxTick); const percent = `${Math.round(vol * 100)}%`; // dial angle const minAngle = -135; const maxAngle = 135; const angleSpan = maxAngle - minAngle; const startAngle = minAngle + vol * angleSpan; const [angle, setAngle] = useState(startAngle); // dots const dotSectorAngle = angleSpan / maxTick; const dotSectorAngleOffset = -angleSpan / 2 + dotSectorAngle / 2; const dotTickOffset = 0.5; const dotFillArray: boolean[] = []; for (let t = 0; t < ticks; ++t) { dotFillArray.push(t < tick - dotTickOffset); } // Color schemes const colorSchemes = { rainbow: [ '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#0000FF', '#4B0082', '#9400D3' ], gradient: [ '#FF00FF', '#FF007F', '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', '#00FFFF', '#0000FF' ], pastel: [ '#FFD1DC', '#FFECB8', '#B5EAD7', '#C7CEEA', '#E2F0CB', '#FFDAC1', '#B5EAD7', '#F8B195' ], default: ['var(--dot-color)'] }; const getDotColor = (index: number) => { const scheme = colorSchemes[color as keyof typeof colorSchemes] || colorSchemes.default; return scheme[index % scheme.length]; }; // set the volume useEffect(() => { setVol((angle - minAngle) / angleSpan); }, [angle]); // initiate the draggable useEffect(() => { Draggable.create(dialRef.current, { type: "rotation", bounds: { minRotation: minAngle, maxRotation: maxAngle }, onDrag: function() { setAngle(this.rotation); } }); }, []); // run a transition when adjusting using arrow keys useGSAP(() => { if (isKeyDown) { gsap.to(dialRef.current, { rotation: angle, duration: 0.15 }); } }, [angle]); // starting angle useGSAP(() => { gsap.to(dialRef.current, { rotation: startAngle, duration: 0 }); }, []); function keyboardAction(e: React.KeyboardEvent<HTMLButtonElement>) { const up = e.code === "ArrowUp" || e.code === "ArrowRight"; const down = e.code === "ArrowDown" || e.code === "ArrowLeft"; if (up || down) { e.preventDefault(); setIsKeydown(true); } if (up) { setAngle(minAngle + Math.min(tick + 1, maxTick) / maxTick * angleSpan); } else if (down) { setAngle(minAngle + Math.max(0, tick - 1) / maxTick * angleSpan); } } return ( <div className={rootClass}> <div className="volume__control"> {dotFillArray.map((filled, i) => { const angle = dotSectorAngle * i + dotSectorAngleOffset; return ( <VolumeDialDot key={i} angle={angle} filled={filled} color={getDotColor(i)} /> ) })} <div className="volume__dial-wrap"> <button className="volume__dial" type="button" ref={dialRef} onKeyDown={keyboardAction} onKeyUp={() => setIsKeydown(false)} aria-description={percent} > <span className="volume__dial-label">{label}</span> </button> </div> </div> <div className="volume__content"> {children || <div className="volume__display">{percent}</div>} </div> </div> ); } function VolumeDialDot({ angle = 0, filled = false, color = '' }: VolumeDialDotProps) { const filledClass = filled ? " volume__dot--filled" : ""; const dotClass = `volume__dot${filledClass}`; const dotStyle = { transform: `rotate(${angle}deg)`, ...(color && filled ? { '--dot-color': color } : {}) }; return ( <div className={dotClass} style={dotStyle}></div> ); } interface VolumeDialProps { ticks: number; volume?: number; color?: string; label?: string; children?: React.ReactNode; }; interface VolumeDialDotProps { angle?: number; filled?: boolean; color?: string; };