《义字最难写,情字最难收!》了了子老师修改版
<meta charset="UTF-8"><title>播放 - 修改版</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--color-1: #fff887;
--color-2: #fc89e5;
--color-3: #fd27d2;
--color-4: #9cf9fc;
--color-5: #0dd7de;
--color-6: #fbcb6d;
--color-7: #fb8739;
--color-8: #fa5f57;
--color-9: #FF4444;
--color-10: #44DD88;
--color-11: #4488FF;
--color-12: #FFDD44;
--color-13: #DD44FF;
}
#papa {
position: relative;
margin: 30px 0;
left: calc(50% - 81px);
transform: translateX(-50%);
aspect-ratio: 16/9;
width: clamp(600px, 90vw, 1400px);
min-height: 338px;
background: linear-gradient(45deg, rgba(255, 0, 0, 0.1) 90%, rgba(8, 8, 13, 0.3) 100%) center/100% 100% no-repeat;
box-shadow: 2px 2px 6px #000;
z-index: 1;
overflow: hidden;
border-radius: 32px;
--state: running;
animation: colorFlash 3.5s linear infinite var(--state);
}
.progress-wrap {
position: absolute;
left: 50%;
top: 95%;
transform: translateX(-50%);
width: 65%;
z-index: 10;
}
.time-box {
display: flex;
justify-content: space-between;
color: #FF0000;
font-size: 20px;
margin-bottom: 6px;
}
.range {
-webkit-appearance: none;
width: 100%;
background: none;
position: absolute;
bottom: 1%;
z-index: 15;
}
.range::-webkit-slider-runnable-track {
margin: 30px auto;
background: linear-gradient(90deg, lightgreen, lightgreen) no-repeat center/100% 2px;
}
.range::-webkit-slider-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: radial-gradient(lightgreen 30%, green 35%, darkgreen 100%);
cursor: pointer;
}
.range::-moz-range-track {
background: linear-gradient(90deg, lightgreen, lightgreen) no-repeat center/100% 2px;
}
.range::-moz-range-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: radial-gradient(lightgreen 30%, green 35%, darkgreen 100%);
cursor: pointer;
}
#lyricDisplay {
height: 100%;
letter-spacing: -9px;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
padding: 0 1em;
width: 100%;
}
.lyrichar {
display: inline-block;
opacity: 0;
animation: charAppear 0.5s forwards, hue-rotate 1.5s linear infinite var(--state);
margin: 0 2px;
}
@keyframes charAppear {
to {
opacity: 1;
transform: translate(0%);
}
}
@keyframes hue-rotate {
50% {
filter: hue-rotate(360deg);
}
}
#lyric {
position: relative;
left: 50%;
top: 80%;
transform: translateX(-50%);
z-index: 10;
display: flex;
flex-direction: column;
justify-content: center;
height: auto;
width: 80%;
text-align: center;
filter: drop-shadow(#000 1px 0 0) drop-shadow(#000 0 1px 0) drop-shadow(#000 -1px 0 0) drop-shadow(#000 0 -1px 0);
font: 4em "KaiTi", "SimHei", "Arial", "sans-serif";
}
.wrap {
position: absolute;
background-color: #2c3e50;
border-radius: 25px;
padding: 20px 15px;
left: 40px;
top: 50%;
transform: translateY(-50%);
z-index: 12;
height: auto;
min-height: 200px;
width: auto;
min-width: 80px;
display: flex;
justify-content: center;
align-items: center;
animation: wrapGlowPulse 3s ease-in-out infinite var(--state), wrapColorShift 6s infinite alternate var(--state);
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
@keyframes wrapGlowPulse {
0% {
transform: translateY(-50%) scale(0.95);
box-shadow: 0 0 5px rgba(255, 215, 0, 0.4), 0 0 10px rgba(255, 200, 0, 0.2);
}
50% {
transform: translateY(-50%) scale(1.05);
box-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 0 25px rgba(255, 180, 0, 0.6);
}
100% {
transform: translateY(-50%) scale(0.95);
box-shadow: 0 0 5px rgba(255, 215, 0, 0.4), 0 0 10px rgba(255, 200, 0, 0.2);
}
}
@keyframes wrapColorShift {
0% { background-color: #1e2a3a; }
100% { background-color: #2c3e50; }
}
/* 文字样式:直接可见,无宽度动画,仅颜色循环和轻微淡入 */
.text {
font-size: 42px;
font-weight: bold;
font-family: "KaiTi", "楷体", "STKaiti", "华文楷书", "Microsoft YaHei", "微软雅黑", "PingFang SC", "Helvetica Neue", cursive, serif;
letter-spacing: 8px;
color: #ffd966;
writing-mode: vertical-rl;
text-orientation: upright;
white-space: nowrap;
opacity: 0;
animation: textFadeIn 0.8s ease-out forwards, textColorFlow 6s infinite alternate var(--state);
}
/* 淡入动画,仅一次 */
@keyframes textFadeIn {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* 颜色循环 */
@keyframes textColorFlow {
0% { color: var(--color-1); }
10% { color: var(--color-2); }
20% { color: var(--color-3); }
30% { color: var(--color-4); }
40% { color: var(--color-5); }
50% { color: var(--color-6); }
60% { color: var(--color-7); }
70% { color: var(--color-8); }
80% { color: var(--color-9); }
90% { color: var(--color-10); }
100% { color: var(--color-11); }
}
.msvg {
position: absolute;
right: 10px;
bottom: 10px;
cursor: pointer;
transition: all 0.5s ease;
animation: rot 5s linear infinite var(--state);
width: 200px;
height: 200px;
}
.msvg:hover {
filter: invert(80%);
}
#fullscreen {
position: absolute;
top: 30px;
right: 30px;
font: normal 1.5em 楷体;
color: #fff;
text-shadow: 0 0 3px #000;
opacity: 1;
cursor: pointer;
user-select: none;
z-index: 8;
transition: opacity 0.3s;
}
#fullscreen:hover {
font-style: italic;
}
@keyframes rot {
to { transform: rotate(1turn); }
}
@keyframes colorFlash {
0% { filter: hue-rotate(0deg) brightness(1) saturate(1); }
20% { filter: hue-rotate(70deg) brightness(1.2) saturate(1.25); }
40% { filter: hue-rotate(140deg) brightness(1.25) saturate(1.3); }
60% { filter: hue-rotate(210deg) brightness(1.2) saturate(1.25); }
80% { filter: hue-rotate(280deg) brightness(1.15) saturate(1.2); }
100% { filter: hue-rotate(360deg) brightness(1) saturate(1); }
}
.vid {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
pointer-events: none;
mix-blend-mode: screen;
z-index: 1;
opacity: 1;
}
</style>
</head>
<body>
<div id="papa">
<video class="vid" src="https://img-baofun.zhhainiao.com/pcwallpaper_ugc/preview/e8e51ccaef284de89b1105c15fd8600b_preview.mp4" autoplay loop preload="auto" playsinline muted></video>
<span id="fullscreen">全屏欣赏</span>
<svg class="msvg" width="200" height="200" viewBox="-200 -200 400 400">
<defs>
<linearGradient id="grd" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="red"/>
<stop offset="90%" stop-color="orange"/>
<stop offset="100%" stop-color="gold"/>
</linearGradient>
</defs>
<circle cx="0" cy="0" r="125" fill="none" stroke="url(#grd)" stroke-width="14"/>
<circle cx="0" cy="0" r="15" fill="white" stroke="none"/>
<g id="petals">
<polygon points="0,0 -25,-120 0,-90 25,-120 0,0" fill="none" stroke="url(#grd)" stroke-width="14"/>
</g>
<use href="#petals" transform="rotate(45)"/>
<use href="#petals" transform="rotate(90)"/>
<use href="#petals" transform="rotate(135)"/>
<use href="#petals" transform="rotate(180)"/>
<use href="#petals" transform="rotate(225)"/>
<use href="#petals" transform="rotate(270)"/>
<use href="#petals" transform="rotate(315)"/>
</svg>
<div id="lyric">
<div id="lyricDisplay"></div>
</div>
<div class="progress-wrap">
<div class="time-box">
<span id="current">00:00</span>
<span id="duration">00:00</span>
</div>
<input id="myrange" type="range" class="range" min="0" max="100" step="any" value="0" title="调节进度">
</div>
<div class="wrap">
<div class="text">义字最难写,情字最难收</div>
<audio id="aud" preload="auto" autoplay loop></audio>
</div>
</div>
<script>
(function() {
requestAnimationFrame(() => document.body.style.opacity = '1');
setTimeout(() => {
if (document.body.style.opacity !== '1') document.body.style.opacity = '1';
}, 50);
})();
const papa = document.getElementById('papa');
const aud = document.getElementById('aud');
const currentSpan = document.getElementById('current');
const durationSpan = document.getElementById('duration');
const myrange = document.getElementById('myrange');
const fullscreen = document.getElementById('fullscreen');
const msvg = document.querySelector('.msvg');
const lyricDisplay = document.getElementById('lyricDisplay');
// ---------- 歌词数据 ----------
const lrcText = `
义字最难写,情字最难收
LRC编辑:醉美水芙蓉
常言说好人难做好路难修
却不见深情之人少泪流
问苍天为何真心难长久
原来是人心善变人情难留
义字最难写
情字最难收
忍字心头一把刀
孝字最难求
红尘路慢慢
苦乐自己受
人间万般不由己
善恶终有头
常言说好人难做好路难修
却不见深情之人少泪流
问苍天为何真心难长久
原来是人心善变人情难留
义字最难写
情字最难收
忍字心头一把刀
孝字最难求
红尘路慢慢
苦乐自己受
人间万般不由己
善恶终有头
义字最难写
情字最难收
忍字心头一把刀
孝字最难求
红尘路慢慢
苦乐自己受
人间万般不由己
善恶终有头
谢谢欣赏!
`;
function parseLrc(lrc) {
const lyrics = [];
const lines = lrc.trim().split('\n');
const lrcRegex = /\[(\d{2}):(\d{2})\.(\d{2})\](.*)/;
for (let line of lines) {
const match = line.match(lrcRegex);
if (match) {
const minutes = parseInt(match);
const seconds = parseInt(match);
const ms = parseInt(match);
const totalSeconds = minutes * 60 + seconds + ms / 100;
const text = match.trim();
lyrics.push({ time: totalSeconds, text });
}
}
return lyrics;
}
function displayLyricCharByChar(text) {
lyricDisplay.innerHTML = '';
const chars = text.split('');
const colorList = ['var(--color-1)', 'var(--color-2)', 'var(--color-3)',
'var(--color-4)', 'var(--color-5)', 'var(--color-6)'];
chars.forEach((char, i) => {
const span = document.createElement('span');
span.className = 'lyrichar';
span.style.color = colorList;
if (char === ' ') {
span.innerHTML = ' ';
} else {
span.textContent = char;
}
const offset = i === 0 ? 0 : i * 30;
span.style.transform = `translateY(${offset}px)`;
span.style.animationDelay = `${i * 0.08}s`;
if (/[,。!?,.!?]/.test(char)) {
span.style.animationDelay = `${i * 0.08 + 0.08}s`;
}
lyricDisplay.appendChild(span);
});
}
let lyrics = parseLrc(lrcText);
let currentLyricIndex = -1;
let isUpdating = false;
function resetLyrics() {
currentLyricIndex = -1;
lyricDisplay.innerHTML = '';
}
//音频数据
aud.src = "https://www.joy127.com/url/151508.mp3";
aud.load();
function formatTime(seconds) {
if (isNaN(seconds)) return "00:00";
const min = Math.floor(seconds / 60);
const sec = Math.floor(seconds % 60);
return `${min.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}`;
}
function updateCurrentTime() {
currentSpan.textContent = formatTime(aud.currentTime);
if (aud.duration && !isNaN(aud.duration)) {
myrange.value = (aud.currentTime / aud.duration) * 100;
}
}
aud.addEventListener('loadedmetadata', () => {
durationSpan.textContent = formatTime(aud.duration);
});
aud.addEventListener('timeupdate', () => {
if (isUpdating) return;
isUpdating = true;
setTimeout(() => isUpdating = false, 100);
const ct = aud.currentTime;
updateCurrentTime();
for (let i = 0; i < lyrics.length; i++) {
const start = lyrics.time;
const end = (i < lyrics.length - 1) ? lyrics.time : Infinity;
if (ct >= start - 0.3 && ct < end + 0.3) {
if (currentLyricIndex !== i) {
currentLyricIndex = i;
displayLyricCharByChar(lyrics.text);
}
break;
}
}
});
aud.addEventListener('ended', resetLyrics);
myrange.addEventListener('input', (e) => {
if (!aud.duration) return;
const percent = parseFloat(e.target.value) / 100;
aud.currentTime = percent * aud.duration;
});
//状态同步
const videos = document.querySelectorAll('.vid');
function syncState() {
const paused = aud.paused;
papa.style.setProperty('--state', paused ? 'paused' : 'running');
videos.forEach(v => paused ? v.pause() : v.play());
let title = msvg.querySelector('title');
if (!title) {
title = document.createElementNS('http://www.w3.org/2000/svg', 'title');
msvg.prepend(title);
}
title.textContent = paused ? '播放' : '暂停';
}
aud.addEventListener('canplay', syncState);
aud.addEventListener('playing', syncState);
aud.addEventListener('pause', syncState);
aud.addEventListener('play', syncState);
msvg.onclick = () => {
if (aud.paused) {
aud.play().catch(e => console.warn('播放失败:', e));
} else {
aud.pause();
}
};
//全屏
let isFullscreen = true;
let fsTimer;
fullscreen.onclick = () => {
if (isFullscreen) {
fullscreen.innerText = '退出全屏';
papa.requestFullscreen();
} else {
fullscreen.innerText = '全屏欣赏';
document.exitFullscreen();
}
isFullscreen = !isFullscreen;
};
papa.addEventListener('mousemove', () => {
clearTimeout(fsTimer);
fullscreen.style.opacity = '1';
fsTimer = setTimeout(() => fullscreen.style.opacity = '0', 3000);
});
['contextmenu', 'dragstart', 'selectstart'].forEach(ev =>
papa.addEventListener(ev, e => e.preventDefault())
);
// 激活音频(用户首次点击)
const activateAudio = () => {
if (aud.paused) {
aud.play().catch(e => console.log('需要用户交互'));
}
document.body.removeEventListener('click', activateAudio);
document.body.removeEventListener('touchstart', activateAudio);
};
document.body.addEventListener('click', activateAudio);
document.body.addEventListener('touchstart', activateAudio);
syncState();
</script>
效果漂亮~谢谢精彩分享 klxf 发表于 2026-5-31 12:14
效果漂亮~谢谢精彩分享
谢谢友友光临!
页:
[1]