一个电视机频道切换网页源代码.点击按钮切换不同频道
- 2026-09-25 22:21:21
一个电视机频道切换网页源代码.点击按钮切换不同频道一个电视机频道切换网页代码 点击按钮切换不同频道,有那种老电视机换台的特效。一共三个文件,存一下即可。 


我能为你提供什么服务?
网站建设 | 小程序开发 | 软件定制
我是鹏魔王,一个做网站、小程序的程序员,记录生活日常、及技术分享。
本欲起身离红尘,奈何影子落人间,欢迎关注,祝大家早日实现财务自由!



<!DOCTYPE html><htmllang="zh"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>鹏魔王</title><linkrel="stylesheet"href="./style.css"></head><body><divclass="tv-wrap"><divclass="tv-cabinet"><divclass="tv-bezel"><divclass="tv-screen"id="tvScreen"tabindex="0"><canvasid="screen"></canvas><divclass="scanlines"></div><divclass="phosphor-glow"id="glow"></div><divclass="screen-glass"></div></div></div><divclass="tv-controls"><divclass="tv-brand">Petrichor</div><divclass="indicator-row"><divclass="led"></div><spanstyle="font-family:'VT323',monospace;font-size:14px;color:rgba(200,191,173,0.3);letter-spacing:0.1em;">ONAIR</span></div><divclass="knobs"><divclass="knob"id="prevKnob"title="Previous channel"></div><divclass="knob ch-knob"id="nextKnob"title="Next channel"></div></div></div></div><divclass="channel-strip"id="channelStrip"></div><divclass="hint">click knob or channel buttons to switch · space / arrow keys work too</div></div><scriptsrc="./script.js"></script></body></html>
// ── PALETTE / CHANNELS ───────────────────────────────────────────const CHANNELS = [{ ch: 1, name: 'Ink', hex: '#1a1814', r:26, g:24, b:20, desc:'the sky at midnight' },{ ch: 2, name: 'Storm', hex: '#2e3d4f', r:46, g:61, b:79, desc:'cumulonimbus at dusk' },{ ch: 3, name: 'Slate', hex: '#6b7f8e', r:107, g:127, b:142, desc:'wet flagstone' },{ ch: 4, name: 'Rain', hex: '#8fafc2', r:143, g:175, b:194, desc:'first drops on glass' },{ ch: 5, name: 'Moss', hex: '#4a5e45', r:74, g:94, b:69, desc:'lichen on old walls' },{ ch: 6, name: 'Clay', hex: '#9c7c5e', r:156, g:124, b:94, desc:'exposed earth' },{ ch: 7, name: 'Ochre', hex: '#c4893a', r:196, g:137, b:58, desc:'amber before the storm' },{ ch: 8, name: 'Petal', hex: '#d4a5a0', r:212, g:165, b:160, desc:'wild rose, last bloom' },{ ch: 9, name: 'Dust', hex: '#c8bfad', r:200, g:191, b:173, desc:'dry road before rain' },{ ch: 10, name: 'Stone', hex: '#e8e2d9', r:232, g:226, b:217, desc:'limestone in afternoon light' },];// ── CANVAS SETUP ─────────────────────────────────────────────────const tvScreen = document.getElementById('tvScreen');const canvas = document.getElementById('screen');const ctx = canvas.getContext('2d');const glow = document.getElementById('glow');let CW, CH;function resizeCanvas() {const rect = tvScreen.getBoundingClientRect();CW = canvas.width = rect.width;CH = canvas.height = rect.height;}resizeCanvas();window.addEventListener('resize', resizeCanvas);// ── STATE ─────────────────────────────────────────────────────────let currentCh = 0;let staticNoise = null;let noiseAge = 0;let staticBurst = 0;let switching = false;let scanOffset = 0;let glitchTimer = 0;let ticker = 0;// ── BUILD CHANNEL BUTTONS ─────────────────────────────────────────const strip = document.getElementById('channelStrip');CHANNELS.forEach((ch, i) => {const btn = document.createElement('button');btn.className = 'ch-btn' + (i === 0 ? ' active' : '');btn.textContent = String(ch.ch).padStart(2, '0');btn.style.setProperty('--ch-color', ch.hex);btn.addEventListener('click', () => switchTo(i));strip.appendChild(btn);});function updateButtons(idx) {document.querySelectorAll('.ch-btn').forEach((b, i) => {b.classList.toggle('active', i === idx);});}// ── PHOSPHOR GLOW ─────────────────────────────────────────────────function setGlow(ch) {const { r, g, b } = ch;const brightness = (r * 0.299 + g * 0.587 + b * 0.114) / 255;const a = 0.25 + brightness * 0.3;glow.style.boxShadow = `0 0 18px rgba(${r},${g},${b},${a}),0 0 45px rgba(${r},${g},${b},${a * 0.6}),0 0 90px rgba(${r},${g},${b},${a * 0.3})`;}// ── NOISE BUFFER ──────────────────────────────────────────────────function makeNoiseBuffer() {const off = document.createElement('canvas');off.width = CW; off.height = CH;const oc = off.getContext('2d');const id = oc.createImageData(CW, CH);const d = id.data;for (let i = 0; i < d.length; i += 4) {const v = Math.random() * 255 | 0;d[i] = d[i+1] = d[i+2] = v;d[i+3] = 255;}oc.putImageData(id, 0, 0);return off;}// ── DRAW SCREEN ───────────────────────────────────────────────────function drawScreen(ch, staticAlpha) {const { r, g, b, hex, name, desc, ch: chNum } = ch;ticker++;// Base color fillctx.fillStyle = hex;ctx.fillRect(0, 0, CW, CH);// CRT vignette darkeningconst vg = ctx.createRadialGradient(CW/2, CH/2, CH*0.1, CW/2, CH/2, CH*0.72);vg.addColorStop(0, 'rgba(0,0,0,0)');vg.addColorStop(1, 'rgba(0,0,0,0.38)');ctx.fillStyle = vg;ctx.fillRect(0, 0, CW, CH);// Phosphor warmth glow from centerconst luma = (r*0.299 + g*0.587 + b*0.114) / 255;const pgA = 0.12 + luma * 0.15;const pg = ctx.createRadialGradient(CW/2, CH/2, 0, CW/2, CH/2, CH*0.55);pg.addColorStop(0, `rgba(255,255,255,${pgA})`);pg.addColorStop(1, 'rgba(255,255,255,0)');ctx.fillStyle = pg;ctx.fillRect(0, 0, CW, CH);// Moving scanline bandscanOffset = (scanOffset + 0.4) % CH;ctx.fillStyle = 'rgba(255,255,255,0.025)';for (let y = scanOffset % 80; y < CH; y += 80) {ctx.fillRect(0, y, CW, 2);}// Occasional glitch lineglitchTimer++;if (glitchTimer > 180 && Math.random() < 0.03) {glitchTimer = 0;const gy = Math.random() * CH | 0;ctx.fillStyle = `rgba(255,255,255,${Math.random() * 0.4})`;ctx.fillRect(0, gy, CW, (Math.random() * 3 + 1) | 0);}// Text color based on background luminanceconst textLight = `rgba(232,226,217,0.92)`;const textDark = `rgba(26,24,20,0.80)`;const subLight = `rgba(200,191,173,0.65)`;const subDark = `rgba(46,24,20,0.55)`;const dimLight = `rgba(200,191,173,0.40)`;const dimDark = `rgba(46,24,20,0.38)`;const mainColor = luma < 0.45 ? textLight : textDark;const subColor = luma < 0.45 ? subLight : subDark;const dimColor = luma < 0.45 ? dimLight : dimDark;// Channel number — top leftctx.font = `bold ${CW * 0.075}px 'VT323', monospace`;ctx.textAlign = 'left';ctx.fillStyle = `rgba(0,0,0,0.2)`;ctx.fillText(`CH ${String(chNum).padStart(2, '0')}`, CW*0.05 + 1, CW*0.1 + 1);ctx.fillStyle = mainColor.replace('0.92','0.15').replace('0.80','0.12');ctx.fillText(`CH ${String(chNum).padStart(2, '0')}`, CW*0.05, CW*0.1);// Color name — large centeredconst nameSize = CW * 0.155;ctx.font = `${nameSize}px 'VT323', monospace`;ctx.textAlign = 'center';// drop shadowctx.fillStyle = 'rgba(0,0,0,0.22)';ctx.fillText(name.toUpperCase(), CW/2 + 2, CH/2 + nameSize*0.34 + 2);ctx.fillStyle = mainColor;ctx.fillText(name.toUpperCase(), CW/2, CH/2 + nameSize*0.34);// Hex codectx.font = `${CW * 0.055}px 'Share Tech Mono', monospace`;ctx.fillStyle = subColor;ctx.fillText(hex.toUpperCase(), CW/2, CH/2 + nameSize*0.34 + CW*0.075);// Descriptionctx.font = `${CW * 0.038}px 'Share Tech Mono', monospace`;ctx.fillStyle = dimColor;ctx.fillText(desc, CW/2, CH/2 + nameSize*0.34 + CW*0.13);// RGB bars at bottomconst barY = CH - CW*0.085;const barH = CW*0.025;const barW = CW*0.65;const barX = (CW - barW) / 2;const segments = [{ label:'R', val:r, color:'rgba(212,100,100,0.7)' },{ label:'G', val:g, color:'rgba(100,180,120,0.7)' },{ label:'B', val:b, color:'rgba(100,150,220,0.7)' },];ctx.font = `${CW * 0.032}px 'Share Tech Mono', monospace`;segments.forEach((seg, i) => {const by = barY + i * (barH + CW*0.018);ctx.fillStyle = 'rgba(0,0,0,0.2)';ctx.beginPath();ctx.roundRect(barX, by, barW, barH, barH/2);ctx.fill();ctx.fillStyle = seg.color;ctx.beginPath();ctx.roundRect(barX, by, barW * (seg.val/255), barH, barH/2);ctx.fill();ctx.textAlign = 'right';ctx.fillStyle = dimColor;ctx.fillText(`${seg.label}${seg.val}`, barX - CW*0.016, by + barH*0.82);});ctx.textAlign = 'left';// Static overlayif (staticAlpha > 0.01) {if (!staticNoise || noiseAge++ > 3) {staticNoise = makeNoiseBuffer();noiseAge = 0;}ctx.globalAlpha = staticAlpha;ctx.drawImage(staticNoise, 0, 0);ctx.globalAlpha = 1;}}// ── SWITCH CHANNEL ────────────────────────────────────────────────function switchTo(idx) {if (switching) return;switching = true;currentCh = ((idx % CHANNELS.length) + CHANNELS.length) % CHANNELS.length;staticBurst = 1.0;updateButtons(currentCh);setGlow(CHANNELS[currentCh]);tvScreen.classList.add('switching');setTimeout(() => {tvScreen.classList.remove('switching');switching = false;}, 500);}function next() { switchTo(currentCh + 1); }function prev() { switchTo(currentCh - 1); }// ── INPUT ─────────────────────────────────────────────────────────document.getElementById('nextKnob').addEventListener('click', next);document.getElementById('prevKnob').addEventListener('click', prev);tvScreen.addEventListener('click', next);document.addEventListener('keydown', e => {if (e.key === 'ArrowRight' || e.key === ' ' || e.key === 'ArrowUp') { e.preventDefault(); next(); }if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') { e.preventDefault(); prev(); }const n = parseInt(e.key);if (!isNaN(n) && n >= 1 && n <= 9) switchTo(n - 1);if (e.key === '0') switchTo(9);});// Auto-advancelet autoTimer = setInterval(next, 6000);tvScreen.addEventListener('click', () => {clearInterval(autoTimer);autoTimer = setInterval(next, 8000);});// ── RENDER LOOP ───────────────────────────────────────────────────setGlow(CHANNELS[currentCh]);function loop() {staticBurst = staticBurst > 0.01 ? staticBurst * 0.82 : 0;drawScreen(CHANNELS[currentCh], staticBurst);requestAnimationFrame(loop);}loop();
@import url('https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=VT323&display=swap');*, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }body {background: #0a0806;min-height: 100vh;display: flex;flex-direction: column;align-items: center;justify-content: center;font-family: 'Share Tech Mono', monospace;overflow: hidden;position: relative;}body::before {content: '';position: fixed;inset: 0;background:radial-gradient(ellipse 80% 60% at 50% 40%, rgba(156,124,94,0.04) 0%, transparent 70%),radial-gradient(ellipse 50% 80% at 20% 80%, rgba(46,61,79,0.06) 0%, transparent 60%);pointer-events: none;z-index: 0;}/* ── TV CABINET ───────────────────────────────────── */.tv-wrap {position: relative;z-index: 10;filter: drop-shadow(0 40px 80px rgba(0,0,0,0.9)) drop-shadow(0 0 60px rgba(156,124,94,0.08));animation: tvFloat 6s ease-in-out infinite;}@keyframes tvFloat {0%,100% { transform: translateY(0px); }50% { transform: translateY(-10px); }}.tv-cabinet {background: linear-gradient(160deg, #3a2e22 0%, #2a2018 40%, #1e1710 100%);border-radius: 28px 28px 24px 24px;padding: 28px 32px 36px;position: relative;border: 2px solid #4a3828;box-shadow:inset 0 2px 4px rgba(255,255,255,0.08),inset 0 -4px 8px rgba(0,0,0,0.6),0 8px 0 #1a1208,0 12px 0 #140e06;}.tv-cabinet::before {content: '';position: absolute;inset: 0;border-radius: inherit;background: repeating-linear-gradient(92deg,transparent 0px,transparent 18px,rgba(0,0,0,0.06) 18px,rgba(0,0,0,0.06) 19px);pointer-events: none;}/* ── SCREEN BEZEL ─────────────────────────────────── */.tv-bezel {background: linear-gradient(145deg, #1a1410 0%, #0e0c08 100%);border-radius: 14px;padding: 18px;box-shadow:inset 0 0 0 2px rgba(255,255,255,0.04),inset 4px 4px 12px rgba(0,0,0,0.8),inset -2px -2px 8px rgba(255,255,255,0.03);position: relative;}/* ── SCREEN ───────────────────────────────────────── */.tv-screen {width: 520px;height: 390px;position: relative;overflow: hidden;border-radius: 8px;cursor: pointer;outline: none;}.tv-screen::after {content: '';position: absolute;inset: 0;border-radius: 8px;box-shadow:inset 8px 0 20px rgba(0,0,0,0.35),inset -8px 0 20px rgba(0,0,0,0.35),inset 0 8px 20px rgba(0,0,0,0.25),inset 0 -8px 20px rgba(0,0,0,0.25);pointer-events: none;z-index: 20;}#screen {display: block;width: 100%;height: 100%;image-rendering: pixelated;}.scanlines {position: absolute;inset: 0;background: repeating-linear-gradient(to bottom,transparent 0px,transparent 3px,rgba(0,0,0,0.18) 3px,rgba(0,0,0,0.18) 4px);pointer-events: none;z-index: 15;border-radius: 8px;mix-blend-mode: multiply;}.phosphor-glow {position: absolute;inset: -2px;border-radius: 10px;pointer-events: none;z-index: 5;transition: box-shadow 1.2s ease;}.screen-glass {position: absolute;top: 6px; left: 8px;width: 45%; height: 30%;background: linear-gradient(135deg,rgba(255,255,255,0.06) 0%,rgba(255,255,255,0.02) 50%,transparent 100%);border-radius: 6px 6px 0 0;pointer-events: none;z-index: 25;}/* ── CONTROLS BAR ─────────────────────────────────── */.tv-controls {display: flex;align-items: center;justify-content: space-between;margin-top: 20px;padding: 0 4px;}.tv-brand {font-family: 'VT323', monospace;font-size: 22px;color: rgba(200,191,173,0.35);letter-spacing: 0.18em;text-transform: uppercase;}.knobs {display: flex;gap: 18px;align-items: center;}.knob {width: 32px; height: 32px;border-radius: 50%;background: radial-gradient(circle at 35% 30%, #5a4535, #2a1e14);border: 2px solid #3a2a1c;box-shadow:0 3px 6px rgba(0,0,0,0.6),inset 0 1px 2px rgba(255,255,255,0.1);cursor: pointer;position: relative;transition: transform 0.15s ease;}.knob::after {content: '';position: absolute;top: 4px; left: 50%; transform: translateX(-50%);width: 3px; height: 10px;background: rgba(200,191,173,0.5);border-radius: 2px;}.knob:hover { transform: rotate(30deg); }.knob:active { transform: rotate(60deg); }.knob.ch-knob { width: 38px; height: 38px; }.knob.ch-knob::after { height: 12px; top: 5px; }.indicator-row {display: flex;gap: 6px;align-items: center;}.led {width: 6px; height: 6px;border-radius: 50%;background: #c4893a;box-shadow: 0 0 6px #c4893a, 0 0 12px rgba(196,137,58,0.5);animation: ledPulse 2s ease-in-out infinite;}@keyframes ledPulse {0%,100% { opacity: 1; }50% { opacity: 0.4; }}/* ── CHANNEL STRIP ────────────────────────────────── */.channel-strip {display: flex;gap: 8px;margin-top: 22px;justify-content: center;flex-wrap: wrap;max-width: 590px;}.ch-btn {width: 44px; height: 30px;border: 1px solid rgba(200,191,173,0.15);background: rgba(255,255,255,0.03);border-radius: 4px;color: rgba(200,191,173,0.5);font-family: 'VT323', monospace;font-size: 16px;cursor: pointer;transition: all 0.2s ease;}.ch-btn:hover {border-color: rgba(200,191,173,0.4);color: rgba(232,226,217,0.9);transform: translateY(-1px);}.ch-btn.active {border-color: var(--ch-color, #c4893a);color: #e8e2d9;box-shadow: 0 0 10px var(--ch-color, #c4893a), inset 0 0 8px rgba(255,255,255,0.05);}/* ── HINT ─────────────────────────────────────────── */.hint {margin-top: 16px;font-size: 10px;letter-spacing: 0.22em;text-transform: uppercase;color: rgba(200,191,173,0.2);text-align: center;}/* ── CHANNEL SWITCH ANIMATION ─────────────────────── */.tv-screen.switching #screen {animation: crtSwitch 0.45s ease forwards;}@keyframes crtSwitch {0% { transform: scaleY(1); filter: brightness(1.2); }20% { transform: scaleY(0.02); filter: brightness(3) blur(1px); }55% { transform: scaleY(0.02); filter: brightness(0.1); }75% { transform: scaleY(1.04); filter: brightness(1.4); }90% { transform: scaleY(0.97); filter: brightness(0.9); }100% { transform: scaleY(1); filter: brightness(1); }}@media (max-width: 640px) {.tv-screen { width: 320px; height: 240px; }.tv-cabinet { padding: 16px 18px 24px; }.ch-btn { width: 36px; height: 26px; font-size: 14px; }}/* ── RUSSELL BADGE ─────────────────────────────────── */.russell-badge {position: fixed;bottom: 22px;left: 22px;z-index: 100;text-decoration: none;display: inline-flex;align-items: center;padding: 6px 14px;border: 1px solid rgba(196,137,58,0.35);border-radius: 4px;background: rgba(10,8,6,0.75);backdrop-filter: blur(4px);overflow: hidden;transition: border-color 0.3s ease, transform 0.2s ease;}.russell-badge:hover {border-color: rgba(196,137,58,0.8);transform: translateY(-2px);}.russell-badge:hover .badge-glow {opacity: 1;}.badge-text {position: relative;z-index: 2;font-family: 'VT323', monospace;font-size: 18px;letter-spacing: 0.22em;text-transform: uppercase;color: rgba(200,191,173,0.55);transition: color 0.3s ease;}.russell-badge:hover .badge-text {color: #e8e2d9;text-shadow: 0 0 8px rgba(196,137,58,0.6);}.badge-glow {position: absolute;inset: 0;background: radial-gradient(ellipse at 50% 120%, rgba(196,137,58,0.12) 0%, transparent 70%);opacity: 0;transition: opacity 0.4s ease;pointer-events: none;}
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。