成吉思汗(碰撞小球+歌词同步演示)
本帖最后由 马黑黑 于 2024-4-19 10:05 编辑 <br /><br /><style>#papa { margin: 0 0 0 calc(50% - 721px); width: 1280px; height: 720px; background: url('https://638183.freep.cn/638183/t24/webp/ijsh.webp') no-repeat center/cover; display: grid; place-items: center; overflow: hidden; user-select: none; position: relative; }
#play { position: absolute; left: 230px; top: 120px; animation: rot 6s linear infinite var(--state); z-index: 9; cursor: pointer; }
#papa video { position: absolute; top: -200px; width: 100%; height: 100%; object-fit: cover; mix-blend-mode: screen; pointer-events: none; }
@Keyframes rot { to { transform: rotate(360deg); } }
</style>
<div id="papa">
<audio id="aud" src="https://file.uhsea.com/2404/b8719ccade383eb311011e81bd4aca1bE4.mp3" autoplay loop></audio>
<video src="https://img.tukuppt.com/video_show/2475824/00/01/58/5b56a385e42de.mp4" loop muted></video>
<imgid="play" src="https://638183.freep.cn/638183/small/dcjm.webp" width="150" height="150" alt="" />
</div>
<script>
//函数 :加载JS资源
var loadJs = (file, callback) => {
var sc = document.createElement('script');
sc.src = file;
sc.charset = 'utf-8';
document.body.appendChild(sc);
sc.onload = () => callback();
};
var js1 = 'https://638183.freep.cn/638183/web/api/lrc.js';
var js2 = 'https://638183.freep.cn/638183/web/js/ball-lz.js';
//歌词js先加载并用回调方式配置参数
loadJs(js1, () => {
LRC({
papa: '#papa',
lrcAr: lrcAr,
btn: '#play',
lrc_css: 'top: 20px;',
});
});
//粒子js后加载,
loadJs(js2, () => {});
//配置粒子
var lz = {papa: '#papa', total: 40, maxsize: 20, speed: 1, move: true};
var lrcAr = [
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
];
papa.onclick = () => lz.move = !aud.paused; //控制粒子
</script>
本帖最后由 马黑黑 于 2024-4-19 10:05 编辑 <br /><br /><style>
.mum { position: relative; margin: 0; padding: 10px; font: normal 16px/20px Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; color: black; background: rgba(240, 240, 240,.95); box-shadow: 2px 2px 4px gray; border: thick groove lightblue; border-radius: 6px; }
.mum ::selection { background-color: rgba(0,100,100,.35); }
.mum div { margin: 0; padding: 0; }
.mum cl-cd { display: block; position: relative; margin: 0 0 0 50px; padding: 0 0 0 10px; white-space: pre-wrap; overflow-wrap: break-word; border-left: 1px solid silver; }
.mum cl-cd::before { position: absolute; content: attr(data-idx); width: 50px; color: gray; text-align: right; transform: translate(-70px); }
.tRed { color: red; }
.tBlue { color: blue; }
.tGreen { color: green; }
.tDarkRed { color: darkred; }
.tMagenta { color: magenta; }
</style>
<h2>完整代码</h2>
<div class='mum'>
<cl-cd data-idx="1"><<span class="tDarkRed">style</span>></cl-cd>
<cl-cd data-idx="2"> #papa { <span class="tBlue">margin:</span> 0 0 0 calc(50% - 721px); <span class="tBlue">width:</span> 1280px; <span class="tBlue">height:</span> 720px; <span class="tBlue">background:</span> url(<span class="tMagenta">'https://638183.freep.cn/638183/t24/webp/ijsh.webp'</span>) no-repeat center/cover; <span class="tBlue">display:</span> grid; <span class="tBlue">place-items:</span> center; <span class="tBlue">overflow:</span> hidden; <span class="tBlue">user-select:</span> none; <span class="tBlue">position:</span> relative; }</cl-cd>
<cl-cd data-idx="3"> #play { <span class="tBlue">position:</span> absolute; <span class="tBlue">left:</span> 230px; <span class="tBlue">top:</span> 120px; <span class="tBlue">animation:</span> rot 6s linear infinite <span class="tBlue">var</span>(--state); <span class="tBlue">z-index:</span> 9; <span class="tBlue">cursor:</span> pointer; }</cl-cd>
<cl-cd data-idx="4"> #papa video { <span class="tBlue">position:</span> absolute; <span class="tBlue">top:</span> -200px; <span class="tBlue">width:</span> 100%; <span class="tBlue">height:</span> 100%; <span class="tBlue">object-fit:</span> cover; <span class="tBlue">mix-blend-mode:</span> screen; <span class="tBlue">pointer-events:</span> none; }</cl-cd>
<cl-cd data-idx="5"> @Keyframes rot { to { <span class="tBlue">transform:</span> rotate(360deg); } }</cl-cd>
<cl-cd data-idx="6"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="7"> </cl-cd>
<cl-cd data-idx="8"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"papa"</span>></cl-cd>
<cl-cd data-idx="9"> <<span class="tDarkRed">audio</span> <span class="tRed">id</span>=<span class="tMagenta">"aud"</span> src=<span class="tMagenta">"https://file.uhsea.com/2404/b8719ccade383eb311011e81bd4aca1bE4.mp3"</span> autoplay loop><<span class="tDarkRed">/audio</span>></cl-cd>
<cl-cd data-idx="10"> <<span class="tDarkRed">video</span> src=<span class="tMagenta">"https://img.tukuppt.com/video_show/2475824/00/01/58/5b56a385e42de.mp4"</span> loop muted><<span class="tDarkRed">/video</span>></cl-cd>
<cl-cd data-idx="11"> <<span class="tDarkRed">img</span><span class="tRed">id</span>=<span class="tMagenta">"play"</span> src=<span class="tMagenta">"https://638183.freep.cn/638183/small/dcjm.webp"</span> width=<span class="tMagenta">"150"</span> height=<span class="tMagenta">"150"</span> alt=<span class="tMagenta">""</span> /></cl-cd>
<cl-cd data-idx="12"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="13"> </cl-cd>
<cl-cd data-idx="14"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="15"> </cl-cd>
<cl-cd data-idx="16"><span class="tGreen">//函数 :加载JS资源</span></cl-cd>
<cl-cd data-idx="17"><span class="tBlue">var</span> loadJs = (file, callback) => {</cl-cd>
<cl-cd data-idx="18"> <span class="tBlue">var</span> sc = <span class="tRed">document</span>.createElement(<span class="tMagenta">'script'</span>);</cl-cd>
<cl-cd data-idx="19"> sc.src = file;</cl-cd>
<cl-cd data-idx="20"> sc.charset = <span class="tMagenta">'utf-8'</span>;</cl-cd>
<cl-cd data-idx="21"> <span class="tRed">document</span>.body.appendChild(sc);</cl-cd>
<cl-cd data-idx="22"> sc.onload = () => callback();</cl-cd>
<cl-cd data-idx="23">};</cl-cd>
<cl-cd data-idx="24"> </cl-cd>
<cl-cd data-idx="25"><span class="tBlue">var</span> js1 = <span class="tMagenta">'https://638183.freep.cn/638183/web/api/lrc.js'</span>;</cl-cd>
<cl-cd data-idx="26"><span class="tBlue">var</span> js2 = <span class="tMagenta">'https://638183.freep.cn/638183/web/js/ball-lz.js'</span>;</cl-cd>
<cl-cd data-idx="27"> </cl-cd>
<cl-cd data-idx="28"><span class="tGreen">//歌词js先加载并用回调方式配置参数</span></cl-cd>
<cl-cd data-idx="29">loadJs(js1, () => {</cl-cd>
<cl-cd data-idx="30"> LRC({</cl-cd>
<cl-cd data-idx="31"> <span class="tBlue">papa:</span> <span class="tMagenta">'#papa'</span>,</cl-cd>
<cl-cd data-idx="32"> <span class="tBlue">lrcAr:</span> lrcAr,</cl-cd>
<cl-cd data-idx="33"> <span class="tBlue">btn:</span> <span class="tMagenta">'#play'</span>,</cl-cd>
<cl-cd data-idx="34"> lrc_<span class="tBlue">css:</span> <span class="tMagenta">'<span class="tBlue">top:</span> 20px;'</span>,</cl-cd>
<cl-cd data-idx="35"> });</cl-cd>
<cl-cd data-idx="36">});</cl-cd>
<cl-cd data-idx="37"> </cl-cd>
<cl-cd data-idx="38"><span class="tGreen">//粒子js后加载,</span></cl-cd>
<cl-cd data-idx="39">loadJs(js2, () => {});</cl-cd>
<cl-cd data-idx="40"><span class="tGreen">//配置粒子</span></cl-cd>
<cl-cd data-idx="41"><span class="tBlue">var</span> lz = {<span class="tBlue">papa:</span> <span class="tMagenta">'#papa'</span>, <span class="tBlue">total:</span> 40, <span class="tBlue">maxsize:</span> 20, <span class="tBlue">speed:</span> 1, <span class="tBlue">move:</span> true};</cl-cd>
<cl-cd data-idx="42"> </cl-cd>
<cl-cd data-idx="43"><span class="tBlue">var</span> lrcAr = [</cl-cd>
<cl-cd data-idx="44"> ,</cl-cd>
<cl-cd data-idx="45"> ,</cl-cd>
<cl-cd data-idx="46"> ,</cl-cd>
<cl-cd data-idx="47"> ,</cl-cd>
<cl-cd data-idx="48"> ,</cl-cd>
<cl-cd data-idx="49"> ,</cl-cd>
<cl-cd data-idx="50"> ,</cl-cd>
<cl-cd data-idx="51"> ,</cl-cd>
<cl-cd data-idx="52"> ,</cl-cd>
<cl-cd data-idx="53"> ,</cl-cd>
<cl-cd data-idx="54"> ,</cl-cd>
<cl-cd data-idx="55"> ,</cl-cd>
<cl-cd data-idx="56"> ,</cl-cd>
<cl-cd data-idx="57"> ,</cl-cd>
<cl-cd data-idx="58"> ,</cl-cd>
<cl-cd data-idx="59"> ,</cl-cd>
<cl-cd data-idx="60"> ,</cl-cd>
<cl-cd data-idx="61"> ,</cl-cd>
<cl-cd data-idx="62"> ,</cl-cd>
<cl-cd data-idx="63"> ,</cl-cd>
<cl-cd data-idx="64"> ,</cl-cd>
<cl-cd data-idx="65"> ,</cl-cd>
<cl-cd data-idx="66"> ,</cl-cd>
<cl-cd data-idx="67"> ,</cl-cd>
<cl-cd data-idx="68"> ,</cl-cd>
<cl-cd data-idx="69"> ,</cl-cd>
<cl-cd data-idx="70"> ,</cl-cd>
<cl-cd data-idx="71"> ,</cl-cd>
<cl-cd data-idx="72"> ,</cl-cd>
<cl-cd data-idx="73"> ,</cl-cd>
<cl-cd data-idx="74"> ,</cl-cd>
<cl-cd data-idx="75"> ,</cl-cd>
<cl-cd data-idx="76"> ,</cl-cd>
<cl-cd data-idx="77"> ,</cl-cd>
<cl-cd data-idx="78"> ,</cl-cd>
<cl-cd data-idx="79"> ,</cl-cd>
<cl-cd data-idx="80"> ,</cl-cd>
<cl-cd data-idx="81"> ,</cl-cd>
<cl-cd data-idx="82"> ,</cl-cd>
<cl-cd data-idx="83"> ,</cl-cd>
<cl-cd data-idx="84"> ,</cl-cd>
<cl-cd data-idx="85"> ,</cl-cd>
<cl-cd data-idx="86"> ,</cl-cd>
<cl-cd data-idx="87"> ,</cl-cd>
<cl-cd data-idx="88"> ,</cl-cd>
<cl-cd data-idx="89"> ,</cl-cd>
<cl-cd data-idx="90"> ,</cl-cd>
<cl-cd data-idx="91"> ,</cl-cd>
<cl-cd data-idx="92"> ,</cl-cd>
<cl-cd data-idx="93"> ,</cl-cd>
<cl-cd data-idx="94"> ,</cl-cd>
<cl-cd data-idx="95"> ,</cl-cd>
<cl-cd data-idx="96"> ,</cl-cd>
<cl-cd data-idx="97"> ,</cl-cd>
<cl-cd data-idx="98"> ,</cl-cd>
<cl-cd data-idx="99"> </cl-cd>
<cl-cd data-idx="100">];</cl-cd>
<cl-cd data-idx="101"> </cl-cd>
<cl-cd data-idx="102">papa.onclick = () => lz.move = !aud.paused; <span class="tGreen">//控制粒子</span></cl-cd>
<cl-cd data-idx="103"> </cl-cd>
<cl-cd data-idx="104"><<span class="tDarkRed">/script</span>></cl-cd>
</div> 重要说明:
(一)CSS
播放器元素需要提升元素Z轴上的层级级别,代码在第 3 行,z-index: 9;。一般来说,如果其他元素设置了 z-index,且可能会出现在播放器元素的范围,则其他元素的 z-index 不能大于播放器元素的 z-index,当然,通过HTML代码流的次序关系,让播放器元素在最后加载,也能确保 z-index 保持在较高的层级,除非在CSS里设置了其他元素的z-index。
视频应阻止UI交互功能,代码在第 4 行,pointer-events: none; 这句必须存在。这样设置可以,一是令小球粒子的点击交互不受视频拦截,二是右击帖子的鼠标操作菜单由画布接管从而避免可能存在的对视频的进一步操作。
(二)HTML
视频标签 video 可以不设置 autoplay 属性,因为在 lrc.js 插件里已经全方位接管了帖子的所有视频的播放/暂停操作。
(三)JS
我使用回调函数加载两个JS资源文档,写了一个简短的 loadJS(file, callback) 函数。加载JS资源讲究次序,先加载 lrc.js,并通过回调方式配置lrc歌词相关参数;再加载 ball-lz.js,该资源不是插件,所以配置粒子不能通过回调方式实现而是单独配置,加载 ball-lz.js 时就给一个空的回调函数(代码第 39 行)。
ball-lz.js 需要粒子对象 lz 的键值对 move: true/false 做小球运动与否的开关,开关的控制 lrc.js 不存在,所以自己想办法,可以利用帖子容器元素的点击操作来完成。父子关系的元素,在子元素上点击会冒泡到父元素,所以,点击小球也好,点击播放器元素也好,帖子容器元素 papa 都会知道“我被点击了”,然后它依据 audio 控件的暂停与否来控制 lz.move 开关(代码第 102 行)。 很棒的效果,欣赏学习下{:4_190:} 朵拉 发表于 2024-4-19 10:01
很棒的效果,欣赏学习下
{:4_191:} 马黑黑 发表于 2024-4-19 09:47
重要说明:
(一)CSS
{:4_170:}
JS部分好复杂啊。。。
用了回调函数,还新写了一个函数。。
烧脑的跳过。。
小白抄二楼代码就好
南无月 发表于 2024-4-19 11:33
JS部分好复杂啊。。。
用了回调函数,还新写了一个函数。。
烧脑的跳过。。
这个是高级组装了,函数能理解理解,不能理解留着,懂得改哪里就好 朵拉 发表于 2024-4-19 10:01
很棒的效果,欣赏学习下
{:4_191:} 这个背景和歌曲都很提气呢,看这样的帖子让人热血沸腾{:4_199:} 这个帖子里有按钮有歌词和粒子,还有视频,非常齐全。太棒了{:4_199:} 发现个问题,暂停后去点击小球,可以让小球放大和变色。当两个临近小球放大后有交叠,则再播放,这两个小球就都不动了呢。{:4_173:} 继续去点放大的小球,当它变小,脱离交叠了,又可以飞起来了{:4_173:} 马黑黑 发表于 2024-4-19 11:52
这个是高级组装了,函数能理解理解,不能理解留着,懂得改哪里就好
好哒,我就觉得两个JS的很高级。
反正我一惯懒洋洋,望难而退的。。就留着吧。{:4_170:} 南无月 发表于 2024-4-19 17:41
好哒,我就觉得两个JS的很高级。
反正我一惯懒洋洋,望难而退的。。就留着吧。
留着就好 红影 发表于 2024-4-19 17:14
继续去点放大的小球,当它变小,脱离交叠了,又可以飞起来了
这叫顶牛。牛者大,大者路窄不能过。 红影 发表于 2024-4-19 17:12
这个背景和歌曲都很提气呢,看这样的帖子让人热血沸腾
足踏中亚,一切源于马背 红影 发表于 2024-4-19 17:14
发现个问题,暂停后去点击小球,可以让小球放大和变色。当两个临近小球放大后有交叠,则再播放,这两个小球 ...
看 15 楼回复 马黑黑 发表于 2024-4-19 18:20
留着就好
我现在才看到这个贴子全貌。。
这歌听真是带劲。。
但之前听过的好象不是这组歌词。。 双剑小播也是特别,视频节奏感强,跟音乐挺合拍。。{:4_199:} 南无月 发表于 2024-4-19 20:12
我现在才看到这个贴子全貌。。
这歌听真是带劲。。
但之前听过的好象不是这组歌词。。
有多种版本的