WEBLEB
Inicio
Editora de código
Iniciar sesión
Pro
Español
English
Français
Español
Português
Deutsch
Italiano
हिंदी
Activar o desactivar grabación
1341
Andev.web
Abrir en el editor
Publica tu código
Recomendado
30 March 2025
Un código de ytr3d3
15 May 2025
Un código de kouadioarmel055
28 November 2024
Efecto de la carta
HTML
Copy
Andev Web
CSS
Copy
* { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 223; --red: hsl(3,90%,50%); --white: hsl(0,0%,100%); --primary: hsl(var(--hue),90%,50%); --primary-t: hsla(var(--hue),90%,50%,0); --gray1: hsl(var(--hue),10%,90%); --gray2: hsl(var(--hue),10%,80%); --gray3: hsl(var(--hue),10%,70%); --gray4: hsl(var(--hue),10%,60%); --gray5: hsl(var(--hue),10%,50%); --gray6: hsl(var(--hue),10%,40%); --gray7: hsl(var(--hue),10%,30%); --gray8: hsl(var(--hue),10%,20%); --gray9: hsl(var(--hue),10%,10%); --trans-dur: 0.3s; --trans-timing: cubic-bezier(0.65,0,0.35,1); font-size: calc(28px + (60 - 28) * (100vw - 320px) / (3840 - 320)); } body, button { color: var(--gray9); font: 1em/1.5 "DM Sans", sans-serif; transition: background-color var(--trans-dur), color var(--trans-dur); } body { background-color: var(--gray1); } .recorder { background-color: transparent; cursor: pointer; display: flex; align-items: center; margin: auto; outline: transparent; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); -webkit-appearance: none; appearance: none; -webkit-tap-highlight-color: transparent; } .recorder__label-start, .recorder__label-end { display: block; position: relative; } .recorder__label-start, .recorder__label-end-text { transition: opacity var(--trans-dur); } .recorder__label-start { margin-inline: 0 0.5em; } .recorder__label-end { margin-inline: 0.5em 0; } .recorder__label-end-text { opacity: 0.4; } .recorder__label-end-text + .recorder__label-end-text { opacity: 0; position: absolute; top: 0; left: 0; } [dir=rtl] .recorder__label-end-text + .recorder__label-end-text { right: 0; left: auto; } .recorder__switch { background-color: var(--white); border-radius: 0.75em; box-shadow: 0 0 0 0.125em var(--primary-t), 0 0.25em 0.25em rgba(0, 0, 0, 0.1); display: flex; padding: 0.25em; width: 2.5em; height: 1.5em; } .recorder__switch, .recorder__switch-handle { transition: background-color var(--trans-dur), box-shadow var(--trans-dur), transform var(--trans-dur) var(--trans-timing), transform-origin var(--trans-dur) var(--trans-timing); } .recorder__switch-handle { background-color: var(--gray3); border-radius: 50%; display: block; transform-origin: 0 0.5em; width: 1em; height: 1em; } [dir=rtl] .recorder__switch-handle { transform-origin: 100% 0.5em; } .recorder__timer { display: block; overflow: visible; width: 100%; height: auto; } .recorder__timer-ring { transition: r var(--trans-dur) var(--trans-timing), stroke-dasharray var(--trans-dur) var(--trans-timing), stroke-dashoffset var(--trans-dur) var(--trans-timing), stroke-width var(--trans-dur) var(--trans-timing); } .recorder:focus-visible .recorder__switch { box-shadow: 0 0 0 0.125em var(--primary), 0 0.25em 0.25em rgba(0, 0, 0, 0.1); } .recorder:active .recorder__switch-handle { transform: scaleX(1.5); } .recorder[aria-pressed=true] .recorder__label-start { opacity: 0.4; } .recorder[aria-pressed=true] .recorder__label-end-text { opacity: 0; } .recorder[aria-pressed=true] .recorder__label-end-text + .recorder__label-end-text { opacity: 1; } .recorder[aria-pressed=true] .recorder__switch-handle { background-color: var(--red); transform: translateX(100%); transform-origin: 100% 0.5em; } [dir=rtl] .recorder[aria-pressed=true] .recorder__switch-handle { transform: translateX(-100%); transform-origin: 0 0.5em; } .recorder[aria-pressed=true] .recorder__timer-ring { r: 6.5px; stroke-width: 3px; } .recorder[aria-pressed=true]:active .recorder__switch-handle { transform: translateX(100%) scaleX(1.5); } [dir=rtl] .recorder[aria-pressed=true]:active .recorder__switch-handle { transform: translateX(-100%) scaleX(1.5); } /* Dark theme */ @media (prefers-color-scheme: dark) { body, button { color: var(--gray1); } body { background-color: var(--gray9); } .recorder__switch { background-color: var(--gray8); box-shadow: 0 0 0 0.125em var(--primary-t), 0 0.25em 0.25em rgba(0, 0, 0, 0.2); } .recorder__switch-handle { background-color: var(--gray6); } .recorder:focus-visible .recorder__switch { box-shadow: 0 0 0 0.125em var(--primary), 0 0.25em 0.25em rgba(0, 0, 0, 0.2); } }
JS
Copy
import React, { StrictMode, useEffect, useState } from "https://esm.sh/react"; import { createRoot } from "https://esm.sh/react-dom/client"; createRoot(document.getElementById("root")).render(React.createElement(StrictMode, null, React.createElement(RecordingToggle, null))); function RecordingToggle() { const [recording, setRecording] = useState(false); const [time, setTime] = useState(0); const timeMax = 60; const [timeStopped, setTimeStopped] = useState(0); const circumference = recording ? 40.84 : 50.27; const circumferencePart = recording ? 1 - (time / timeMax) : 1; const strokeDashArray = `${circumference} ${circumference}`; const strokeDashOffset = +(circumference * circumferencePart).toFixed(2); function timeFormatted() { const timeToDisplay = recording ? time : timeStopped; const minutes = `0${Math.floor(timeToDisplay / 60)}`.slice(-2); const seconds = `0${timeToDisplay % 60}`.slice(-2); return `${minutes}:${seconds}`; } // timer loop useEffect(() => { let frameId = 0; if (recording) { setTimeStopped(0); const render = () => { setTime((time) => time + 1); // allow the time to be shown in the transition when stopping setTimeStopped((time) => time + 1); frameId = setTimeout(render, 1e3); }; frameId = setTimeout(render, 1e3); } else { setTime(0); clearTimeout(frameId); } return () => { clearTimeout(frameId); }; }, [recording]); // stop automatically if time hits limit useEffect(() => { if (time >= timeMax) { setRecording(false); } }, [time]); return (React.createElement("button", { className: "recorder", type: "button", "aria-pressed": recording, onClick: () => setRecording(!recording) }, React.createElement("span", { className: "recorder__label-start", "aria-hidden": recording }, "Stop"), React.createElement("span", { className: "recorder__switch" }, React.createElement("span", { className: "recorder__switch-handle" }, React.createElement("svg", { className: "recorder__timer", viewBox: "0 0 16 16", width: "16px", height: "16px", "aria-hidden": "true" }, React.createElement("g", { fill: "none", strokeLinecap: "round", strokeWidth: "0", transform: "rotate(-90,8,8)" }, React.createElement("circle", { className: "recorder__timer-ring", stroke: "hsla(0,0%,100%,0.3)", cx: "8", cy: "8", r: "8" }), React.createElement("circle", { className: "recorder__timer-ring", stroke: "hsla(0,0%,100%,0.5)", cx: "8", cy: "8", r: "8", strokeDasharray: strokeDashArray, strokeDashoffset: strokeDashOffset }))))), React.createElement("span", { className: "recorder__label-end", "aria-hidden": !recording }, React.createElement("span", { className: "recorder__label-end-text" }, "Record"), React.createElement("span", { className: "recorder__label-end-text" }, timeFormatted())))); }