可爱老人网

 找回密码
 注册会员
搜索
查看: 154|回复: 27

亚伦代码-猫头鹰播放器

[复制链接]
发表于 2025-9-10 21:16 | 显示全部楼层 |阅读模式

评分

参与人数 6人气值 +26 收起 理由
静悟 + 3 赞一个!
肖燕 + 5 赞一个!
彩色风筝 + 5 大赞!
汉风 + 5 赞一个!
沧海笑 + 3 赞一个!

查看全部评分

 楼主| 发表于 2025-9-10 21:17 | 显示全部楼层
本帖最后由 园弄桥 于 2025-9-11 15:38 编辑
  1. <table cellspacing="0" cellpadding="0"><tr><td class="t_f" id="postmessage_504411">
  2. <style>
  3. #gc{margin: 120px -25%;position: relative;z-index: 1;width: 750px;}
  4. .lyrics{margin: 0;
  5. top: 0px;
  6. left: 50%;
  7. transform: translate(-50%, -50%);
  8. height: 100px; /* 调整高度,只容纳当前歌词 */
  9. text-align: center;
  10. position: absolute;z-index: 50;
  11. }
  12. .lyric-line{
  13. width: 100%;
  14. position: relative;
  15. height: 60px;
  16. overflow: visible;
  17. font: 300 50px '华文隶书', sans-serif;
  18. line-height: 60px;
  19. text-align: left;            
  20. white-space: nowrap; /* 禁止换行 */
  21. filter: drop-shadow(#fff 1px 0 0) drop-shadow(#fff 0 1px 0) drop-shadow(#fff -1px 0 0) drop-shadow(#fff 0 -1px 0);
  22. }
  23. .lyric-mask {
  24. position: absolute;
  25. top: 0;
  26. left: 0;
  27. width: 0;
  28. overflow: hidden;
  29. color: #8B4513;
  30. height: 100%;
  31. white-space: nowrap;
  32. }
  33. .lyric-original {
  34. color: #ag0000;
  35. white-space: nowrap;
  36. }
  37. </style>
  38. <style>
  39. @keyframes an-pupils {
  40. from {transform: rotate(0deg);
  41. left: 60px;
  42. }
  43. to {transform: rotate(360deg);
  44. left: 0px;
  45. }
  46. }
  47. @keyframes an-ears {
  48. from {
  49. top:0;
  50. }
  51. to {
  52. top:25px;
  53. }
  54. }
  55. #cat {position: relative;
  56. width: 480px;z-index: 20;
  57. margin:20px auto;
  58. }
  59. #head {
  60. width: 400px;
  61. height: 370px;
  62. background-color: #171717;
  63. border-radius: 50%;
  64. margin: auto;
  65. }
  66. #ears {
  67. height: 65px;
  68. position: relative;
  69. left: 35px;
  70. animation-name: an-ears;
  71. animation-duration: 1s;
  72. animation-iteration-count: infinite;
  73. animation-direction: alternate-reverse;
  74. }
  75. .ear{
  76. width: 0;
  77. height: 0;
  78. border-left: 90px solid transparent;  
  79. border-right: 90px solid transparent;
  80. border-bottom: 160px solid #171717;
  81. font-size: 0;
  82. line-height: 0;
  83. float: left;
  84. margin-right: 60px;      
  85. transform: rotate(35deg);      
  86. }
  87. .ear:first-child {         
  88. transform: rotate(-35deg);
  89. }
  90. #eyes {
  91. clear: both;
  92. width: 350px;
  93. position: relative;
  94. top: 25px;
  95. left: 53px;
  96. }
  97. .eye {
  98. width: 120px;
  99. height: 120px;
  100. background-color: #FFFFFF;
  101. border-radius: 50%;
  102. float: left;      
  103. }
  104. .eye:first-child {
  105. margin-right: 50px;
  106. }
  107. .pupil {
  108. position: relative;
  109. top:40px;
  110. background-color: #171717;
  111. border-radius: 50%;
  112. width: 80px;
  113. height: 80px;
  114. animation-name: an-pupils;
  115. animation-duration: 1.5s;
  116. animation-iteration-count: infinite;
  117. animation-direction: alternate-reverse;
  118. }
  119. .pupil_ref {
  120. background-color: #FFFFFF;
  121. border-radius: 45%;
  122. width: 30px;
  123. height: 30px;
  124. position: relative;
  125. top: 40px;
  126. left: 10px;
  127. }
  128. #nose {
  129. width: 45px;
  130. height: 30px;
  131. border-radius: 50%;
  132. background-color: #FFFFFF;
  133. position: relative;
  134. top: 160px;
  135. left: 170px;
  136. }
  137. #baffisx {
  138. position: relative;
  139. left: -100px;
  140. top: 100px; transform-origin: 70% 0%;
  141. animation: hue-rotate 1s linear infinite ;
  142. }
  143. @keyframes hue-rotate {
  144. from {transform: rotate(-15deg);margin: 0px 0px;
  145. }
  146. to {margin: 0px 0px;transform: rotate(15deg);
  147. }
  148. }
  149. #baffidx {
  150. position: relative;
  151. left: 223px;
  152. top: 140px;
  153. transform-origin: 0% 0%;
  154. animation: hue 1s linear infinite ;
  155. }
  156. @keyframes hue {
  157. from {transform: rotate(15deg);margin: 0px 0px;
  158. }
  159. to {
  160. margin: 0px 0px;transform: rotate(-15deg);
  161. }
  162. }
  163. .baffo{
  164. width:260px;
  165. height:5px;  
  166. border:solid 4px #fff;
  167. border-color:#eee transparent transparent transparent;
  168. border-radius: 60%/30px 30px 0 0;
  169. }
  170. </style>
  171. <div id="cat">
  172. <div id="ears">
  173. <div class="ear"></div>
  174. <div class="ear"></div>
  175. </div>
  176. <div id="head">
  177. <div id="eyes">
  178. <div class="eye" >
  179. <div class="pupil" id="p1"><div class="pupil_ref"></div></div>
  180. </div>
  181. <div class="eye" >
  182. <div class="pupil" id="p2"><div class="pupil_ref"></div></div>
  183. </div>
  184. </div>
  185. <div id="nose"></div>
  186. <div id="baffidx">
  187. <div class="baffo"></div>
  188. <div class="baffo"></div>
  189. <div class="baffo"></div>
  190. </div>
  191. <div id="baffisx">
  192. <div class="baffo"></div>
  193. <div class="baffo"></div>
  194. <div class="baffo"></div>
  195. </div>
  196. </div>
  197. <div id="gc">
  198. <div class="lyrics">
  199. <div class="lyric-line">
  200. <div class="lyric-mask"></div>
  201. <div class="lyric-original"></div>
  202. </div>
  203. </div>
  204. </div>
  205. <audio id="audio" src="https://cccimg.com/view.php/31d806f415397bea14fa33a3b2030f8e.mp3" autoplay loop></audio>
  206. <script>
  207. cat.onclick = () => audio.paused ? (audio.play(),ears.style.animationPlayState = 'running',p1.style.animationPlayState = 'running',p2.style.animationPlayState = 'running',baffisx.style.animationPlayState = 'running',baffidx.style.animationPlayState = 'running') : (audio.pause(),ears.style.animationPlayState = 'paused',p1.style.animationPlayState = 'paused',p2.style.animationPlayState = 'paused',baffisx.style.animationPlayState = 'paused',baffidx.style.animationPlayState = 'paused')
  208. </script>
  209. <script>
  210. // 歌词解析ksc歌词或lrc歌词
  211. const lrc = `[00:00.900]爱江山更爱美人-周华健
  212. [00:19.050]道不尽红尘奢恋
  213. [00:22.050]诉不完人间恩怨
  214. [00:25.830]世世代代都是缘
  215. [00:31.200]流着相同的血
  216. [00:34.200]喝着相同的水
  217. [00:37.980]这条路漫漫又长远
  218. [00:43.350]红花当然配绿叶
  219. [00:46.380]这一辈子谁来陪
  220. [00:50.160]渺渺茫茫来又回
  221. [00:55.500]往日情景再浮现
  222. [00:58.500]藕虽断了丝还连
  223. [01:01.890]轻叹世间事多变迁
  224. [01:07.620]爱江山更爱美人
  225. [01:13.740]哪个英雄好汉宁愿孤单
  226. [01:19.800]好儿郎浑身是胆
  227. [01:26.190]壮志豪情四海远名扬
  228. [01:31.950]人生短短几个秋啊
  229. [01:35.730]不醉不罢休
  230. [01:38.820]东边儿我的美人儿
  231. [01:41.490]那西边儿黄河流
  232. [01:44.850]来呀来个酒啊
  233. [01:46.710]啊不醉不罢休
  234. [01:50.880]愁情烦事别放心头
  235. [02:20.580]道不尽红尘奢恋
  236. [02:23.610]诉不完人间恩怨
  237. [02:27.300]世世代代都是缘
  238. [02:32.730]流着相同的血
  239. [02:35.700]喝着相同的水
  240. [02:39.510]这条路漫漫又长远
  241. [02:44.880]红花当然配绿叶
  242. [02:47.880]这一辈子谁来陪
  243. [02:51.690]渺渺茫茫来又回
  244. [02:57.000]往日情景再浮现
  245. [03:00.060]藕虽断了丝还连
  246. [03:03.420]轻叹世间事多变迁
  247. [03:09.120]爱江山更爱美人
  248. [03:15.240]哪个英雄好汉宁愿孤单
  249. [03:21.300]好儿郎浑身是胆
  250. [03:27.720]壮志豪情四海远名扬
  251. [03:33.780]人生短短几个秋啊
  252. [03:37.290]不醉不罢休
  253. [03:40.350]东边儿我的美人儿
  254. [03:42.960]那西边儿黄河流
  255. [03:46.380]来呀来个酒啊
  256. [03:48.270]啊不醉不罢休
  257. [03:52.410]愁情烦事别放心头
  258. [03:58.560]来呀来个酒啊
  259. [04:01.590]不醉不罢休
  260. [04:04.590]愁情烦事别放心头
  261. `;
  262. const audio = document.getElementById('audio');
  263. const lyrics = parseLyrics(lrc);
  264. const lyricMask = document.querySelector('.lyric-mask');
  265. const lyricOriginal = document.querySelector('.lyric-original');        
  266. let currentIndex = -1;
  267. let currentLyric = null;        
  268. // 解析歌词(支持两种格式)
  269. function parseLyrics(lrcText) {
  270. const lyrics = [];
  271. if (lrcText.includes('karaoke.add')) {
  272. const lineRegex = /karaoke\.add\('([^']+)', '([^']+)', '([^']+)', '([^']+)'\);/g;
  273. let match;
  274. while ((match = lineRegex.exec(lrcText)) !== null) {
  275. const startTime = timeToMs(match[1]);
  276. const endTime = timeToMs(match[2]);
  277. const text = match[3].replace(/\[|\]/g, '').trim();
  278. const durations = match[4].split(',').map(Number);
  279. if (text) {
  280. lyrics.push({startTime, endTime, text, durations});
  281. }
  282. }
  283. }
  284. else if (lrcText.includes('[')) {
  285. const lines = lrcText.split('\n').filter(line => line.trim());
  286. lines.forEach((line, index) => {
  287. const timeMatch = line.match(/\[(\d+:\d+\.\d+)\]/);
  288. if (timeMatch) {
  289. const timeStr = timeMatch[1];
  290. const text = line.replace(/\[.*?\]/, '').trim();
  291. if (text) {
  292. const startTime = timeToMs(timeStr);
  293. const nextLine = lines[index + 1];
  294. const nextTimeMatch = nextLine ? nextLine.match(/\[(\d+:\d+\.\d+)\]/) : null;
  295. const endTime = nextTimeMatch ? timeToMs(nextTimeMatch[1]) : startTime + 5000;
  296. lyrics.push({
  297. startTime,
  298. endTime,
  299. text,
  300. durations: calculateCharDurations(text, startTime, endTime)
  301. });
  302. }
  303. }
  304. });
  305. }
  306. return lyrics;
  307. }
  308. function calculateCharDurations(text, startTime, endTime) {
  309. const totalDuration = endTime - startTime;
  310. const charCount = text.length;
  311. const baseDur = Math.floor(totalDuration / charCount);
  312. const durations = new Array(charCount).fill(baseDur);
  313. const remainder = totalDuration % charCount;
  314. for (let i = 0; i < remainder; i++) {
  315. durations++;
  316. }
  317. return durations;
  318. }
  319. function timeToMs(timeStr) {
  320. const parts = timeStr.split(':');
  321. const minutes = parseInt(parts[0], 10);
  322. const secondsAndMs = parts[1].split('.');
  323. const seconds = parseInt(secondsAndMs[0], 10);
  324. const ms = parseInt(secondsAndMs[1] || 0, 10);
  325. return minutes * 60 * 1000 + seconds * 1000 + ms;
  326. }
  327. function getCurrentLyricIndex(lyrics, currentTimeMs) {
  328. for (let i = 0; i < lyrics.length; i++) {
  329. if (currentTimeMs >= lyrics.startTime && currentTimeMs <= lyrics.endTime) {
  330. return i;
  331. }
  332. }
  333. return -1;
  334. }
  335. function updateLyricDisplay(index) {
  336. if (index < 0 || index >= lyrics.length) return;
  337. currentIndex = index;
  338. currentLyric = lyrics[index];
  339. lyricOriginal.textContent = currentLyric.text;
  340. lyricMask.textContent = currentLyric.text;
  341. lyricMask.style.width = '0%';
  342. }
  343. function updateLyricMask(currentTimeMs) {
  344. if (!currentLyric) return;
  345. const lyricStartTime = currentLyric.startTime;
  346. const elapsed = currentTimeMs - lyricStartTime;
  347. const totalDuration = currentLyric.durations.reduce((sum, d) => sum + d, 0);
  348. let charIndex = 0;
  349. let accumulatedTime = 0;
  350. for (let i = 0; i < currentLyric.durations.length; i++) {
  351. accumulatedTime += currentLyric.durations;
  352. if (elapsed <= accumulatedTime) {
  353. charIndex = i + 1;
  354. break;
  355. }
  356. }
  357. if (elapsed >= totalDuration) {
  358. charIndex = currentLyric.text.length;
  359. }
  360. charIndex = Math.min(charIndex, currentLyric.text.length);            
  361. const tempSpan = document.createElement('span');
  362. tempSpan.style.visibility = 'hidden';
  363. tempSpan.style.position = 'absolute';
  364. tempSpan.style.fontSize = '50px';
  365. tempSpan.style.fontWeight = '800';
  366. document.body.appendChild(tempSpan);            
  367. const visibleText = currentLyric.text.substring(0, charIndex);
  368. tempSpan.textContent = visibleText;
  369. const width = tempSpan.offsetWidth;
  370. document.body.removeChild(tempSpan);            
  371. lyricMask.style.width = `${width}px`;
  372. }
  373. // 监听更新歌词
  374. audio.addEventListener('timeupdate', () => {
  375. const currentTimeMs = audio.currentTime * 1000;
  376. const index = getCurrentLyricIndex(lyrics, currentTimeMs);            
  377. if (index !== currentIndex) {
  378. updateLyricDisplay(index);
  379. }
  380. updateLyricMask(currentTimeMs);
  381. });
  382. updateLyricDisplay(0);
  383. </script>
  384. </td></tr></table>

复制代码

发表于 2025-9-10 23:03 | 显示全部楼层
老歌好听,猫头鹰播放器别具一格。
发表于 2025-9-10 23:04 | 显示全部楼层
园弄桥 发表于 2025-9-10 21:17
#gc{margin: 120px -25%;position: relative;z-index: 1;width: 750px;}
.lyrics{margin: 0;
top: 0p ...

这些代码我不懂,会制作的朋友懂,谢谢老师!
 楼主| 发表于 2025-9-10 23:36 | 显示全部楼层
真真 发表于 2025-9-10 23:03
老歌好听,猫头鹰播放器别具一格。

点赞是快递佬的最爱,否则如何面对老板,如何抚养一家老小?
 楼主| 发表于 2025-9-10 23:42 | 显示全部楼层
本帖最后由 园弄桥 于 2025-9-10 23:43 编辑
真真 发表于 2025-9-10 23:04
这些代码我不懂,会制作的朋友懂,谢谢老师!

只需动mp3和LRC两项,其他不用管。我也不怎么懂,有拉大旗作虎皮,用来吓唬人的嫌疑。
发表于 2025-9-11 04:54 | 显示全部楼层
园弄桥 发表于 2025-9-10 21:17
#gc{margin: 120px -25%;position: relative;z-index: 1;width: 750px;}
.lyrics{margin: 0;
top: 0p ...

最近流行,好像见过,谢谢老师宣传推广,向你学习了,清晨问好!
发表于 2025-9-11 09:51 | 显示全部楼层
告园弄桥老师,您的回帖乱码太多。
 楼主| 发表于 2025-9-11 10:03 | 显示全部楼层
汉风 发表于 2025-9-11 09:51
告园弄桥老师,您的回帖乱码太多。

真是这样就不好了,我不知原因也就不好处理,麻烦您把这个帖子删了,拜托。谢谢。
        
下一页 发布主题 快速回复

手机版|公众号|小黑屋|可爱老人网

GMT+8, 2025-10-14 03:42

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表