马黑黑 发表于 2023-2-23 07:23

许你

<style>
#papa {
        margin: -80px 0 0 calc(50% - 593px);
        display: grid;
        place-items: center;
        width: 1024px;
        height: 640px;
        background: gray url('https://638183.freep.cn/638183/t23/webp/xuni.webp') no-repeat center/cover;
        box-shadow: 8px 4px 20px hsla(0,0%,0%,.65);
        user-select: none;
        position: relative;
        z-index: 1;
        animation: flash 10s infinite alternate;
}
@keyframes flash { from {filter: brightness(60%); } to {filter: brightness(140%); } }
</style>

<div id="papa"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1997297004.mp3" loop autoplay></audio>

<script >
(function() {
        (function(mkPlayer) {let defaults = {lrcAr: [],lrc_css: 'top: 10px; left: 50%; transform: translateX(-50%);',player_css: 'bottom: 20px; left: 50%; transform: translateX(-50%);',btn_txt: '\u2638',playerCode: `<style>#mplayer {position: absolute;grid-template-columns: auto auto auto;gap: 8px;display: grid;place-items: center;color: var(--color);font: normal 16px sans-serif;z-index: 999;--ww: 260px;--color: hsl(0, 100%, 100%);--btn_size: 35px;--track: hsla(90,100%,95%,.65);--prog: linear-gradient(90deg,hsla(90,30%,50%,.55),hsla(0,70%,50%,.65),hsla(90,30%,50%,.75));}#btnplay {--state: paused;margin-right: -4px;font: bold var(--btn_size) / var(--btn_size) serif;text-align: center;cursor: pointer;animation: rot 4s infinite linear;animation-play-state: var(--state);}#prog {--xx: 0px;width: var(--ww);height: 10px;border-radius: 8px;background: var(--track);position: relative;cursor: pointer;}#prog::before {position: absolute;content: '';width: var(--xx);height: 100%;border-radius: 8px;background: var(--prog);}#lrc {--motion: cover2;--tt: 2s;--state: paused;--bg: linear-gradient(180deg, hsla(60, 50%, 50%, .45), hsla(80, 70%, 50%, .6), hsla(0, 100%, 50%, .75));position: absolute;font: bold 2.4em sans-serif;color: hsl(0, 10%, 90%);white-space: pre;-webkit-background-clip: text;filter: drop-shadow(1px 1px 2px hsla(0, 0%, 0%, .95));}#lrc::before {position: absolute;content: attr(data-lrc);width: 20%;height: 100%;color: transparent;overflow: hidden;white-space: pre;background: var(--bg);filter: inherit;-webkit-background-clip: text;animation: var(--motion) var(--tt) linear forwards;animation-play-state: var(--state);}@keyframes cover1 { from { width: 0; } to { width: 100%; } }@keyframes cover2 { from { width: 0; } to { width: 100%; } }@keyframes rot { to { transform: rotate(1turn); } }</style><div id="lrc" data-lrc="HCPlayer">HCPlayer</div><div id="mplayer"><span id="btnplay"></span><span id="prog"></span><span id="tmsg">00:00 | 00:00</span></div>`,};let playCode = (user_config) => {let data = Object.assign({}, defaults, user_config);papa.innerHTML += data.playerCode;mplayer.style.cssText += data.player_css;lrc.style.cssText += data.lrc_css;btnplay.innerHTML = data.btn_txt;let mKey = 0, mFlag = true;btnplay.onclick = () => aud.paused ? aud.play() : aud.pause();prog.onclick = (e) => aud.currentTime = aud.duration * e.offsetX / prog.offsetWidth;aud.addEventListener('timeupdate', () => {let prg = aud.currentTime * prog.offsetWidth / aud.duration < 6 ? 6 : aud.currentTime * prog.offsetWidth / aud.duration;tmsg.innerText = `${toMin(aud.currentTime)} | ${toMin(aud.duration)}`;prog.style.setProperty('--xx', prg + 'px');for (j = 0; j < data.lrcAr.length; j++) {if (aud.currentTime >= data.lrcAr) {cKey = j;if (mKey === j) showLrc(data.lrcAr);else continue;}}});aud.addEventListener('pause', () => mState());aud.addEventListener('play', () => mState());aud.addEventListener('seeked', () => calcKey());let mState = () => aud.paused ? (lrc.style.setProperty('--state','paused'),btnplay.style.setProperty('--state', 'paused')) : (lrc.style.setProperty('--state','running'),btnplay.style.setProperty('--state', 'running'));let showLrc = (time) => {let name = mFlag ? 'cover1' : 'cover2';lrc.innerHTML = data.lrcAr;lrc.dataset.lrc = data.lrcAr.replace(/<br>/, '\n');lrc.style.setProperty('--motion', name);lrc.style.setProperty('--tt', time + 's');lrc.style.setProperty('--state', 'running');mKey += 1;mFlag = !mFlag;};let calcKey = () => {for (j = 0; j < data.lrcAr.length; j++) {if (aud.currentTime <= data.lrcAr) {mKey = j - 1;break;}}if (mKey < 0) mKey = 0;if (mKey > data.lrcAr.length - 1) mKey = data.lrcAr.length - 1;let time = data.lrcAr - (aud.currentTime - data.lrcAr);showLrc(time);};let toMin = (val) => {if (!val) return '00:00';val = Math.floor(val);let min = parseInt(val / 60), sec = parseFloat(val % 60);if (min < 10) min = '0' + min;if (sec < 10) sec = '0' + sec;return min + ':' + sec;}};mkPlayer.HCPlayer = playCode;})(this);
        (function(mkFS) {let setFullScreen = (user_set) => {let pa = user_set.pa;if(typeof(pa) !== 'object') return false;if(!user_set.set) user_set.set = 'color: snow; background: black; border: 2px solid snow; left: 40px; bottom: 40px;';btnMsg = document.createElement('span');btnMsg.style.cssText = `position: absolute; border-radius: 8px; padding: 4px; cursor: pointer; z-index:998; ${user_set.set}`;btnMsg.innerText = '全屏观赏';btnMsg.style.display = 'none';pa.appendChild(btnMsg);let timerId, fs = false;btnMsg.onclick = () => fs ? document.exitFullscreen() : pa.requestFullscreen();pa.addEventListener('mousemove', (e) => {clearTimeout(timerId);btnMsg.style.display = 'block';timerId = setTimeout('btnMsg.style.display = "none"', 3000);});document.addEventListener('fullscreenchange', () => {if (document.fullscreenElement !== null) {fs = true;btnMsg.innerText = '退出全屏';} else {fs = false;btnMsg.innerText = '全屏观赏';}});};mkFS.FS = setFullScreen;})(this);
        let averAdd = 0, offset = 0;
        let geci = `许你(唐诗逸定制向)\n作词:黄颖章(朝露)\n作曲:黄颖章(朝露)、猫玖(深蓝音乐)\n编曲:猫玖(深蓝音乐)\n演唱:Eleven\n混音:海艺音乐\n出品:@唐诗逸百首_SYPoems\n\n再一次 把你自己抛向天际\n大开大合之间 层层剥离\n抖落的是泪滴 撞入海底\n你燃尽自己 为此生不虚\n\n你为了 一场相遇翻山越岭\n我在黢黑的夜 踽踽前行\n看见一轮光晕 冉冉升起\n该有多幸运 能被你唤醒\n\n如果我能陪你 走过每个四季\n春花夏夜秋风冬雪 为你收集\n许你鸟鸣嘤嘤 江湖侠骨柔情\n许你属于自由 属于明天\n许你永远 许你是你\n\n你为了 一场相遇翻山越岭\n我在黢黑的夜 踽踽前行\n看见一轮光晕 冉冉升起\n该有多幸运 能被你唤醒\n\n如果我能陪你 走过每个四季\n就让山间朗月清清 为你做衣\n许你鸟鸣嘤嘤 江湖侠骨柔情\n许你属于自由 属于明天\n许你永远 许你是你\n\n你属于你 你只是你\n我只需要 永远是你\n你属于你 你爱自己\n我会知道 永远是你\n\n你属于你 你只是你\n我只需要 永远是你\n你属于你 你爱自己\n我会知道 永远是你`;

        let lrcTime = (ar) => {let tmpAr = [];for(j = 0; j <ar.length - 1; j ++) {if(j !== ar.length - 1) tmpAr = parseFloat((ar - ar).toFixed(1));}let aver = parseInt(tmpAr.reduce((a,b) => a + b) / (tmpAr.length - 1)) + averAdd;tmpAr.push(aver);tmpAr.forEach((item,key) => {ar = item > aver ? aver : item;});return ar;};
        let getLrcAr = (text) => {let lrcAr = [];let calcRule = ;for(x of text.split('\n')) {let ar = [];let re = /\d+[\.:]\d+([\.:]\d+)?/g;let geci = x.replace(re,'');if(geci) {geci = geci.replace(/[\[\]\'\"\t,]s?/g,'');let time = x.match(re);if(time != null) {for(y of time) {let tmp = y.match(/\d+/g);let sec = 0;for(z in tmp) sec += tmp * calcRule;ar = ;lrcAr.push(ar); }}}}lrcAr.sort((a,b)=> a - b);return(lrcTime(lrcAr));}

        HCPlayer({
                lrcAr: getLrcAr(geci),
                lrc_css: '--bg: linear-gradient(hsla(90,80%,50%,.35),hsla(100,70%,45%,.6)); top: 20px;',
                player_css: '--ww: 180px; bottom: 10px;',
                btn_txt: '\u2623',
        });

        FS({
                pa: papa,
                set: 'backgroun: transparent; color: snow; border: 2px dotted snow; left: 20px; top: 20px;',
        });

        aud.onerror = () => {
                if(aud.error.code === 4) aud.src = 'http://www.kumeiwp.com/sub/filestores/2023/02/22/2ac4a3600cb498c42c2ffdea9e9dbcdf.mp3';
        }
})();
</script>

马黑黑 发表于 2023-2-23 07:23

帖子代码
<style>
#papa {
        margin: -80px 0 0 calc(50% - 593px);
        display: grid;
        place-items: center;
        width: 1024px;
        height: 640px;
        background: gray url('https://638183.freep.cn/638183/t23/webp/xuni.webp') no-repeat center/cover;
        box-shadow: 8px 4px 20px hsla(0,0%,0%,.65);
        user-select: none;
        position: relative;
        z-index: 1;
        animation: flash 10s infinite alternate;
}
@keyframes flash { from {filter: brightness(60%); } to {filter: brightness(140%); } }
</style>

<div id="papa"></div>
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=1997297004.mp3" loop autoplay></audio>

<script >
(function() {
        (function(mkPlayer) {let defaults = {lrcAr: [],lrc_css: 'top: 10px; left: 50%; transform: translateX(-50%);',player_css: 'bottom: 20px; left: 50%; transform: translateX(-50%);',btn_txt: '\u2638',playerCode: `<style>#mplayer {position: absolute;grid-template-columns: auto auto auto;gap: 8px;display: grid;place-items: center;color: var(--color);font: normal 16px sans-serif;z-index: 999;--ww: 260px;--color: hsl(0, 100%, 100%);--btn_size: 35px;--track: hsla(90,100%,95%,.65);--prog: linear-gradient(90deg,hsla(90,30%,50%,.55),hsla(0,70%,50%,.65),hsla(90,30%,50%,.75));}#btnplay {--state: paused;margin-right: -4px;font: bold var(--btn_size) / var(--btn_size) serif;text-align: center;cursor: pointer;animation: rot 4s infinite linear;animation-play-state: var(--state);}#prog {--xx: 0px;width: var(--ww);height: 10px;border-radius: 8px;background: var(--track);position: relative;cursor: pointer;}#prog::before {position: absolute;content: '';width: var(--xx);height: 100%;border-radius: 8px;background: var(--prog);}#lrc {--motion: cover2;--tt: 2s;--state: paused;--bg: linear-gradient(180deg, hsla(60, 50%, 50%, .45), hsla(80, 70%, 50%, .6), hsla(0, 100%, 50%, .75));position: absolute;font: bold 2.4em sans-serif;color: hsl(0, 10%, 90%);white-space: pre;-webkit-background-clip: text;filter: drop-shadow(1px 1px 2px hsla(0, 0%, 0%, .95));}#lrc::before {position: absolute;content: attr(data-lrc);width: 20%;height: 100%;color: transparent;overflow: hidden;white-space: pre;background: var(--bg);filter: inherit;-webkit-background-clip: text;animation: var(--motion) var(--tt) linear forwards;animation-play-state: var(--state);}@keyframes cover1 { from { width: 0; } to { width: 100%; } }@keyframes cover2 { from { width: 0; } to { width: 100%; } }@keyframes rot { to { transform: rotate(1turn); } }</style><div id="lrc" data-lrc="HCPlayer">HCPlayer</div><div id="mplayer"><span id="btnplay"></span><span id="prog"></span><span id="tmsg">00:00 | 00:00</span></div>`,};let playCode = (user_config) => {let data = Object.assign({}, defaults, user_config);papa.innerHTML += data.playerCode;mplayer.style.cssText += data.player_css;lrc.style.cssText += data.lrc_css;btnplay.innerHTML = data.btn_txt;let mKey = 0, mFlag = true;btnplay.onclick = () => aud.paused ? aud.play() : aud.pause();prog.onclick = (e) => aud.currentTime = aud.duration * e.offsetX / prog.offsetWidth;aud.addEventListener('timeupdate', () => {let prg = aud.currentTime * prog.offsetWidth / aud.duration < 6 ? 6 : aud.currentTime * prog.offsetWidth / aud.duration;tmsg.innerText = `${toMin(aud.currentTime)} | ${toMin(aud.duration)}`;prog.style.setProperty('--xx', prg + 'px');for (j = 0; j < data.lrcAr.length; j++) {if (aud.currentTime >= data.lrcAr) {cKey = j;if (mKey === j) showLrc(data.lrcAr);else continue;}}});aud.addEventListener('pause', () => mState());aud.addEventListener('play', () => mState());aud.addEventListener('seeked', () => calcKey());let mState = () => aud.paused ? (lrc.style.setProperty('--state','paused'),btnplay.style.setProperty('--state', 'paused')) : (lrc.style.setProperty('--state','running'),btnplay.style.setProperty('--state', 'running'));let showLrc = (time) => {let name = mFlag ? 'cover1' : 'cover2';lrc.innerHTML = data.lrcAr;lrc.dataset.lrc = data.lrcAr.replace(/<br>/, '\n');lrc.style.setProperty('--motion', name);lrc.style.setProperty('--tt', time + 's');lrc.style.setProperty('--state', 'running');mKey += 1;mFlag = !mFlag;};let calcKey = () => {for (j = 0; j < data.lrcAr.length; j++) {if (aud.currentTime <= data.lrcAr) {mKey = j - 1;break;}}if (mKey < 0) mKey = 0;if (mKey > data.lrcAr.length - 1) mKey = data.lrcAr.length - 1;let time = data.lrcAr - (aud.currentTime - data.lrcAr);showLrc(time);};let toMin = (val) => {if (!val) return '00:00';val = Math.floor(val);let min = parseInt(val / 60), sec = parseFloat(val % 60);if (min < 10) min = '0' + min;if (sec < 10) sec = '0' + sec;return min + ':' + sec;}};mkPlayer.HCPlayer = playCode;})(this);
        (function(mkFS) {let setFullScreen = (user_set) => {let pa = user_set.pa;if(typeof(pa) !== 'object') return false;if(!user_set.set) user_set.set = 'color: snow; background: black; border: 2px solid snow; left: 40px; bottom: 40px;';btnMsg = document.createElement('span');btnMsg.style.cssText = `position: absolute; border-radius: 8px; padding: 4px; cursor: pointer; z-index:998; ${user_set.set}`;btnMsg.innerText = '全屏观赏';btnMsg.style.display = 'none';pa.appendChild(btnMsg);let timerId, fs = false;btnMsg.onclick = () => fs ? document.exitFullscreen() : pa.requestFullscreen();pa.addEventListener('mousemove', (e) => {clearTimeout(timerId);btnMsg.style.display = 'block';timerId = setTimeout('btnMsg.style.display = "none"', 3000);});document.addEventListener('fullscreenchange', () => {if (document.fullscreenElement !== null) {fs = true;btnMsg.innerText = '退出全屏';} else {fs = false;btnMsg.innerText = '全屏观赏';}});};mkFS.FS = setFullScreen;})(this);
        let averAdd = 0, offset = 0;
        let geci = `许你(唐诗逸定制向)\n作词:黄颖章(朝露)\n作曲:黄颖章(朝露)、猫玖(深蓝音乐)\n编曲:猫玖(深蓝音乐)\n演唱:Eleven\n混音:海艺音乐\n出品:@唐诗逸百首_SYPoems\n\n再一次 把你自己抛向天际\n大开大合之间 层层剥离\n抖落的是泪滴 撞入海底\n你燃尽自己 为此生不虚\n\n你为了 一场相遇翻山越岭\n我在黢黑的夜 踽踽前行\n看见一轮光晕 冉冉升起\n该有多幸运 能被你唤醒\n\n如果我能陪你 走过每个四季\n春花夏夜秋风冬雪 为你收集\n许你鸟鸣嘤嘤 江湖侠骨柔情\n许你属于自由 属于明天\n许你永远 许你是你\n\n你为了 一场相遇翻山越岭\n我在黢黑的夜 踽踽前行\n看见一轮光晕 冉冉升起\n该有多幸运 能被你唤醒\n\n如果我能陪你 走过每个四季\n就让山间朗月清清 为你做衣\n许你鸟鸣嘤嘤 江湖侠骨柔情\n许你属于自由 属于明天\n许你永远 许你是你\n\n你属于你 你只是你\n我只需要 永远是你\n你属于你 你爱自己\n我会知道 永远是你\n\n你属于你 你只是你\n我只需要 永远是你\n你属于你 你爱自己\n我会知道 永远是你`;

        let lrcTime = (ar) => {let tmpAr = [];for(j = 0; j <ar.length - 1; j ++) {if(j !== ar.length - 1) tmpAr = parseFloat((ar - ar).toFixed(1));}let aver = parseInt(tmpAr.reduce((a,b) => a + b) / (tmpAr.length - 1)) + averAdd;tmpAr.push(aver);tmpAr.forEach((item,key) => {ar = item > aver ? aver : item;});return ar;};
        let getLrcAr = (text) => {let lrcAr = [];let calcRule = ;for(x of text.split('\n')) {let ar = [];let re = /\d+[\.:]\d+([\.:]\d+)?/g;let geci = x.replace(re,'');if(geci) {geci = geci.replace(/[\[\]\'\"\t,]s?/g,'');let time = x.match(re);if(time != null) {for(y of time) {let tmp = y.match(/\d+/g);let sec = 0;for(z in tmp) sec += tmp * calcRule;ar = ;lrcAr.push(ar); }}}}lrcAr.sort((a,b)=> a - b);return(lrcTime(lrcAr));}

        HCPlayer({
                lrcAr: getLrcAr(geci),
                lrc_css: '--bg: linear-gradient(hsla(90,80%,50%,.35),hsla(100,70%,45%,.6)); top: 20px;',
                player_css: '--ww: 180px; bottom: 10px;',
                btn_txt: '\u2623',
        });

        FS({
                pa: papa,
                set: 'backgroun: transparent; color: snow; border: 2px dotted snow; left: 20px; top: 20px;',
        });

        aud.onerror = () => {
                if(aud.error.code === 4) aud.src = 'http://www.kumeiwp.com/sub/filestores/2023/02/22/2ac4a3600cb498c42c2ffdea9e9dbcdf.mp3';
        }
})();
</script>


马黑黑 发表于 2023-2-23 07:43

本帖最后由 马黑黑 于 2023-2-23 07:48 编辑

本帖需要解释的要点

一、背景忽明忽暗效果

使用 CSS滤镜 实现,在关键帧动画里设计:

@keyframes flash {
      from { filter: brightness(60%); }
      to { filter: brightness(140%); }
}


filter 滤镜有好几个,这里使用 brightness,亮度,brightness为 100% 时亮度正常,低于 100% 偏暗,高于 100% 偏亮。关键帧动画设计了从 60% 到 140% 的变化区间。

然后由 #papa 选择器通过 animation 属性调用 flash 关键帧动画:

animation: flash 10s infinite alternate;

10s 一个运行周期,循环运行(infinite),反向运行(alternate)。因为使用了 alternate,一个完整的变化过程实际需要 10 * 2 = 20(s) 的时间。

二、提供备选音频地址

JS代码的最后,有一个 error 时间处理机制:

      aud.onerror = () => {
                if(aud.error.code === 4) aud.src = 'http://www.kumeiwp.com/sub/filestores/2023/02/22/2ac4a3600cb498c42c2ffdea9e9dbcdf.mp3';
      }


若 audio 控件出错(onerror),且出错代码为 4 ,则给它更换一个音频链接。

这个出错处理机制其实也不完美,比如,假如第二个地址同样失效,这就没办法了。聊胜于无,中奖率不会是百分之百,失败率也不会是百分之百。

三、原生lrc歌词能够相对精准同步

歌词我放在一行里,不容易观察它的特点。可以使用第三方文本编辑器快速将其还原为多行,方法是使用正则替换:查找,\\n,替换,\n ,这就可以看到如下结构——

许你永远 许你是你

你为了 一场相遇翻山越岭
我在黢黑的夜 踽踽前行
看见一轮光晕 冉冉升起
该有多幸运 能被你唤醒

如果我能陪你 走过每个四季
就让山间朗月清清 为你做衣
许你鸟鸣嘤嘤 江湖侠骨柔情
许你属于自由 属于明天
许你永远 许你是你



有空歌词的lrc信息行。这类lrc歌词,空行是有意义的,它表明上一句歌词到此唱完,这样的歌词同步时在我们的函数处理机制里会比较准确。

制作这样的歌词,可以使用优秀的第三方软件,也可是找网上现成的这类歌词。

马黑黑 发表于 2023-2-23 08:12

如果你没有一款趁手的代码编辑器,强烈建议大家使用 notepad-- ,这是一款对标 notepad++ 的国人的作品,用它写帖子代码体验很好,处理文本替换那是小菜一碟。如果需要,请按下面的链接介绍的下载安装:

https://blog.csdn.net/KKBoy11/article/details/128802093

红影 发表于 2023-2-23 09:22

这个文字符号的播放器漂亮,这张背景图加了变暗效果变化更有感觉。黑黑又带来新效果{:4_199:}

红影 发表于 2023-2-23 09:24

马黑黑 发表于 2023-2-23 08:12
如果你没有一款趁手的代码编辑器,强烈建议大家使用 notepad-- ,这是一款对标 notepad++ 的国人的作品,用 ...

去下载了静态编辑的那个,虽然还没习惯用它,但是黑黑推荐的都是好东西{:4_187:}

海笑 发表于 2023-2-23 09:56

欣赏老师佳作!

庶民 发表于 2023-2-23 10:35

太美了,很喜欢这个,收藏起来。纪念。

樵歌 发表于 2023-2-23 11:01

挖,太漂亮了{:4_178:}

樵歌 发表于 2023-2-23 11:02

又又又又可以当文抄公啦{:4_358:}

樵歌 发表于 2023-2-23 11:04

许你为花山亭候世世世袭{:4_189:}

起个网名好难 发表于 2023-2-23 11:06

js里用大量篇幅设置CSS和HTML

梦油 发表于 2023-2-23 11:31

美不胜收、赞!

醉美水芙蓉 发表于 2023-2-23 11:51

醉美水芙蓉 发表于 2023-2-23 11:55

醉美水芙蓉 发表于 2023-2-23 11:56

醉美水芙蓉 发表于 2023-2-23 11:57

马黑黑 发表于 2023-2-23 12:31

醉美水芙蓉 发表于 2023-2-23 11:57
这个编辑歌词有点困难吧?

不难,掐头掐尾

马黑黑 发表于 2023-2-23 12:36

红影 发表于 2023-2-23 09:24
去下载了静态编辑的那个,虽然还没习惯用它,但是黑黑推荐的都是好东西

我试过它的一些功能,挺好的

马黑黑 发表于 2023-2-23 12:36

红影 发表于 2023-2-23 09:22
这个文字符号的播放器漂亮,这张背景图加了变暗效果变化更有感觉。黑黑又带来新效果

这也不算新呢,只是大家没留意
页: [1] 2 3 4 5
查看完整版本: 许你