宋婷婷·知音
<style>#mydiv { margin: 30px 0 30px calc(50% - 721px); width: 1280px; height:720px; background: url('https://638183.freep.cn/638183/t24/2/viyb.jpg') no-repeat 0/cover; border: thick groove lightpink; overflow: hidden; transition: 1s; z-index: 1; user-select: none; position: relative; }
#mydiv:hover { background-size: 120%; background-position: center; }
.txtbox { position: absolute; display: grid; place-items: center; left: var(--x1); top: 20px; width: 50px; height: 50px; font: normal 30px sans-serif; text-align: center; color: white; box-sizing: border-box; cursor: pointer; }
.txtbox::after { position: absolute; content: ''; inset: -2px; border: 2px dashed gray; border-color: green lightgreen yellow orange; border-radius: 50%; box-shadow: inset 0 0 20px plum; transition: 1s; animation: rot 8s linear var(--delay) infinite var(--state); }
.txtbox:hover::after { box-shadow: inset 0 0 30px green, 0 0 60px white; }
#vid { position: absolute; bottom: 0; width: 100%; height: calc(100% + 60px); object-fit: cover; mix-blend-mode: screen; pointer-events: none; }
@keyframes move1 { to { left: var(--x2); } }
@keyframes move2 { to { left: var(--x1); } }
@keyframes rot { to { transform: rotate(var(--deg)); } }
</style>
<div id="mydiv">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=406737036" autoplay></audio>
<video id="vid" src="https://img.tukuppt.com/video_show/2269348/00/14/66/5e5a2c53955d7.mp4" loop muted></video>
</div>
<script>
(function() {
const ar = '高山流水覓知音'.split('');
const ww = 1280, duTime = 16, deTime = 0.5;
const total = duTime + ar.length * deTime + deTime;
let sAr = [], step = 0;//, aniName = 'move1';
ar.forEach((t,k) => {
let span = document.createElement('span');
span.className = 'txtbox';
span.textContent = t;
span.style.cssText += `
--x1: ${ww + k * 60 - ar.length * 60 - 20}px;
--x2: ${k * 60 + 10}px;
--deg: -1turn;
--delay: -${Math.random() * k}s;
`;
sAr.push(span);
mydiv.appendChild(span);
});
let playAni = () => {
let aniName = ['move1','move2'];
let deg = ['-1turn','1turn'];
sAr.forEach((item,key) => {
item.style.left = ['var(--x1)','var(--x2)'];
item.style.setProperty('--deg', deg);
let delay = step % 2 > 0 ? deTime * (sAr.length - key - 1) : deTime * key;
item.style.animation = `${aniName} ${duTime}s ${delay}s linear forwards var(--state)`;
});
step ++;
};
let mState = () => {
mydiv.style.setProperty('--state', ['running','paused'][+aud.paused]);
sAr.forEach(item => item.title = ['暂停','播放'][+aud.paused]);
aud.paused ? vid.pause() : vid.play();
};
aud.loop = false;
aud.onplaying = aud.onpause = () => mState();
aud.onended = () => { step = 0; aud.play(); }
aud.ontimeupdate = () => { if(aud.currentTime >= total * step) playAni(); };
sAr.forEach(item => item.onclick = () =>aud.paused ? aud.play(): aud.pause());
})();
</script>
<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"> #mydiv { <span class="tBlue">margin:</span> 30px 0 30px 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/2/viyb.jpg'</span>) no-repeat 0/cover; <span class="tBlue">border:</span> thick groove lightpink; <span class="tBlue">overflow:</span> hidden; <span class="tBlue">transition:</span> 1s; <span class="tBlue">z-index:</span> 1; <span class="tBlue">user-select:</span> none; <span class="tBlue">position:</span> relative; }</cl-cd>
<cl-cd data-idx="3"> #<span class="tBlue">mydiv:</span>hover { <span class="tBlue">background-size:</span> 120%; <span class="tBlue">background-position:</span> center; }</cl-cd>
<cl-cd data-idx="4"> .txtbox { <span class="tBlue">position:</span> absolute; <span class="tBlue">display:</span> grid; <span class="tBlue">place-items:</span> center; <span class="tBlue">left:</span> <span class="tBlue">var</span>(--x1); <span class="tBlue">top:</span> 20px; <span class="tBlue">width:</span> 50px; <span class="tBlue">height:</span> 50px; <span class="tBlue">font:</span> normal 30px sans-serif; <span class="tBlue">text-align:</span> center; <span class="tBlue">color:</span> white; <span class="tBlue">box-sizing:</span> border-box; <span class="tBlue">cursor:</span> pointer; }</cl-cd>
<cl-cd data-idx="5"> .txtbox::after { <span class="tBlue">position:</span> absolute; <span class="tBlue">content:</span> <span class="tMagenta">''</span>; <span class="tBlue">inset:</span> -2px; <span class="tBlue">border:</span> 2px dashed gray; <span class="tBlue">border-color:</span> green lightgreen yellow orange; <span class="tBlue">border-radius:</span> 50%; <span class="tBlue">box-shadow:</span> inset 0 0 20px plum; <span class="tBlue">transition:</span> 1s; <span class="tBlue">animation:</span> rot 8s linear <span class="tBlue">var</span>(--delay) infinite <span class="tBlue">var</span>(--state); }</cl-cd>
<cl-cd data-idx="6"> .<span class="tBlue">txtbox:</span>hover::after { <span class="tBlue">box-shadow:</span> inset 0 0 30px green, 0 0 60px white; }</cl-cd>
<cl-cd data-idx="7"> #vid { <span class="tBlue">position:</span> absolute; <span class="tBlue">bottom:</span> 0; <span class="tBlue">width:</span> 100%; <span class="tBlue">height:</span> calc(100% + 60px); <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="8"> @keyframes move1 { to { <span class="tBlue">left:</span> <span class="tBlue">var</span>(--x2); } }</cl-cd>
<cl-cd data-idx="9"> @keyframes move2 { to { <span class="tBlue">left:</span> <span class="tBlue">var</span>(--x1); } }</cl-cd>
<cl-cd data-idx="10"> @keyframes rot { to { <span class="tBlue">transform:</span> rotate(<span class="tBlue">var</span>(--deg)); } }</cl-cd>
<cl-cd data-idx="11"><<span class="tDarkRed">/style</span>></cl-cd>
<cl-cd data-idx="12"> </cl-cd>
<cl-cd data-idx="13"><<span class="tDarkRed">div</span> <span class="tRed">id</span>=<span class="tMagenta">"mydiv"</span>></cl-cd>
<cl-cd data-idx="14"> <<span class="tDarkRed">audio</span> <span class="tRed">id</span>=<span class="tMagenta">"aud"</span> src=<span class="tMagenta">"https://music.163.com/song/media/outer/url?<span class="tRed">id</span>=406737036"</span> autoplay><<span class="tDarkRed">/audio</span>></cl-cd>
<cl-cd data-idx="15"> <<span class="tDarkRed">video</span> <span class="tRed">id</span>=<span class="tMagenta">"vid"</span> src=<span class="tMagenta">"https://img.tukuppt.com/video_show/2269348/00/14/66/5e5a2c53955d7.mp4"</span> loop muted><<span class="tDarkRed">/video</span>></cl-cd>
<cl-cd data-idx="16"><<span class="tDarkRed">/div</span>></cl-cd>
<cl-cd data-idx="17"> </cl-cd>
<cl-cd data-idx="18"><<span class="tDarkRed">script</span>></cl-cd>
<cl-cd data-idx="19">(<span class="tBlue">function</span>() {</cl-cd>
<cl-cd data-idx="20"> <span class="tBlue">const</span> ar = <span class="tMagenta">'高山流水覓知音'</span>.split(<span class="tMagenta">''</span>);</cl-cd>
<cl-cd data-idx="21"> <span class="tBlue">const</span> ww = 1280, duTime = 16, deTime = 0.5;</cl-cd>
<cl-cd data-idx="22"> <span class="tBlue">const</span> total = duTime + ar.length * deTime + deTime;</cl-cd>
<cl-cd data-idx="23"> <span class="tBlue">let</span> sAr = [], step = 0;<span class="tGreen">//, aniName = <span class="tMagenta">'move1'</span>;</span></cl-cd>
<cl-cd data-idx="24"> </cl-cd>
<cl-cd data-idx="25"> ar.forEach((t,k) => {</cl-cd>
<cl-cd data-idx="26"> <span class="tBlue">let</span> span = <span class="tRed">document</span>.createElement(<span class="tMagenta">'span'</span>);</cl-cd>
<cl-cd data-idx="27"> span.className = <span class="tMagenta">'txtbox'</span>;</cl-cd>
<cl-cd data-idx="28"> span.textContent = t;</cl-cd>
<cl-cd data-idx="29"> span.style.cssText += `</cl-cd>
<cl-cd data-idx="30"> --x1: ${ww + k * 60 - ar.length * 60 - 20}px;</cl-cd>
<cl-cd data-idx="31"> --x2: ${k * 60 + 10}px;</cl-cd>
<cl-cd data-idx="32"> <span class="tBlue">--deg:</span> -1turn;</cl-cd>
<cl-cd data-idx="33"> <span class="tBlue">--delay:</span> -${<span class="tRed">Math</span>.random() * k}s;</cl-cd>
<cl-cd data-idx="34"> `;</cl-cd>
<cl-cd data-idx="35"> sAr.push(span);</cl-cd>
<cl-cd data-idx="36"> mydiv.appendChild(span);</cl-cd>
<cl-cd data-idx="37"> });</cl-cd>
<cl-cd data-idx="38"> </cl-cd>
<cl-cd data-idx="39"> <span class="tBlue">let</span> playAni = () => {</cl-cd>
<cl-cd data-idx="40"> <span class="tBlue">let</span> aniName = [<span class="tMagenta">'move1'</span>,<span class="tMagenta">'move2'</span>];</cl-cd>
<cl-cd data-idx="41"> <span class="tBlue">let</span> deg = [<span class="tMagenta">'-1turn'</span>,<span class="tMagenta">'1turn'</span>];</cl-cd>
<cl-cd data-idx="42"> sAr.forEach((item,key) => {</cl-cd>
<cl-cd data-idx="43"> item.style.left = [<span class="tMagenta">'<span class="tBlue">var</span>(--x1)'</span>,<span class="tMagenta">'<span class="tBlue">var</span>(--x2)'</span>];</cl-cd>
<cl-cd data-idx="44"> item.style.setProperty(<span class="tMagenta">'--deg'</span>, deg);</cl-cd>
<cl-cd data-idx="45"> <span class="tBlue">let</span> delay = step % 2 > 0 ? deTime * (sAr.length - key - 1) : deTime * key;</cl-cd>
<cl-cd data-idx="46"> item.style.animation = `${aniName} ${duTime}s ${delay}s linear forwards <span class="tBlue">var</span>(--state)`;</cl-cd>
<cl-cd data-idx="47"> });</cl-cd>
<cl-cd data-idx="48"> step ++;</cl-cd>
<cl-cd data-idx="49"> };</cl-cd>
<cl-cd data-idx="50"> </cl-cd>
<cl-cd data-idx="51"> <span class="tBlue">let</span> mState = () => {</cl-cd>
<cl-cd data-idx="52"> mydiv.style.setProperty(<span class="tMagenta">'--state'</span>, [<span class="tMagenta">'running'</span>,<span class="tMagenta">'paused'</span>][+aud.paused]);</cl-cd>
<cl-cd data-idx="53"> sAr.forEach(item => item.title = [<span class="tMagenta">'暂停'</span>,<span class="tMagenta">'播放'</span>][+aud.paused]);</cl-cd>
<cl-cd data-idx="54"> aud.paused ? vid.pause() : vid.play();</cl-cd>
<cl-cd data-idx="55"> };</cl-cd>
<cl-cd data-idx="56"> </cl-cd>
<cl-cd data-idx="57"> aud.loop = false;</cl-cd>
<cl-cd data-idx="58"> aud.onplaying = aud.onpause = () => mState();</cl-cd>
<cl-cd data-idx="59"> aud.onended = () => { step = 0; aud.play(); }</cl-cd>
<cl-cd data-idx="60"> aud.ontimeupdate = () => { <span class="tBlue">if</span>(aud.currentTime >= total * step) playAni(); };</cl-cd>
<cl-cd data-idx="61"> </cl-cd>
<cl-cd data-idx="62"> sAr.forEach(item => item.onclick = () =>aud.paused ? aud.play(): aud.pause());</cl-cd>
<cl-cd data-idx="63">})();</cl-cd>
<cl-cd data-idx="64"><<span class="tDarkRed">/script</span>></cl-cd>
</div>
本帖主要特点:
利用文本生成若干个 span 标签,这些标签可以装饰帖子,同时充当音频的播放控制按钮。
span 标签绝对定位,先排列在帖子的靠右区域,音乐播放时交替运行两套CSS关键帧动画从而左右逐个移动。动画机制算法上似乎不太理想,不过又不是不可以动,将就着用。
span 标签的伪元素 ::after 运行自己的关键帧动画,它可以根据行进方向改变旋转方向。
另,设备指针移入帖子时,:hover 触发的是 background-size 和 background-position 两个属性,前者不响应 transition 时间设定,指针移入移出的动画显得有些突兀,完美的解决方案应该是用伪元素放图、伪元素宽高尺寸变更。 原来这些字也是小播按纽,功能扩展啦。。
刚才只顾点上去看内光晕和外光晕的变化。。{:4_199:} 背景触碰可以放大缩小,从右往左移动位置~~
user-select: none;这句没见过,不知道干 啥用的。{:4_173:} 南无月 发表于 2024-6-4 12:47
背景触碰可以放大缩小,从右往左移动位置~~
user-select: none;这句没见过,不知道干 啥用的。
禁止选择 南无月 发表于 2024-6-4 12:42
原来这些字也是小播按纽,功能扩展啦。。
刚才只顾点上去看内光晕和外光晕的变化。。
齿轮形状挺好看的,全网木有 马黑黑 发表于 2024-6-4 12:05
本帖主要特点:
利用文本生成若干个 span 标签,这些标签可以装饰帖子,同时充当音频的播放控制按钮。
#mydiv::before { position: absolute; content: ''; inset: 0; transition: 7s; mix-blend-mode: screen; background: url('https://638183.freep.cn/638183/t24/2/viyb.jpg') no-repeat center/cover; }
#mydiv:hover::before { transform: scale(1.2); }
用伪元素放图、伪元素宽高尺寸变更,缩放大小很漂亮了。
但从右往左移的动画不见了。。
这两个不能同时存在的么。 #mydiv:hover::before { transform: scale(1.2); }
#mydiv:hover:before { background-position: center; }
#mydiv:hover::before { transform: scale(1.2); background-position: center; }
分开合起来都不行。。{:4_170:}反正试过了~~ 欣赏老师的又一新作!辛苦了! 梦江南 发表于 2024-6-4 13:18
欣赏老师的又一新作!辛苦了!
{:4_190:} 南无月 发表于 2024-6-4 13:04
#mydiv:hover::before { transform: scale(1.2); }
#mydiv:hover:before { background-position: center;...
css3还是有缺陷的:对 background-* 的绝大多数都不能相应 transition 设定 南无月 发表于 2024-6-4 13:02
#mydiv::before { position: absolute; content: ''; inset: 0; transition: 7s; mix-blend-mode:...
background 图片的位置和样纸应设为 center/cover 醉美水芙蓉 发表于 2024-6-4 16:54
欣赏老师带来的精彩!
{:4_190:} 马黑黑 发表于 2024-6-4 12:51
禁止选择
保护措施{:4_173:} 马黑黑 发表于 2024-6-4 12:52
齿轮形状挺好看的,全网木有
黑氏独创。。独一无二,是真的非常好看。。{:4_199:}。。 马黑黑 发表于 2024-6-4 13:21
css3还是有缺陷的:对 background-* 的绝大多数都不能相应 transition 设定
好吧,抄个别的代码过来还行。。。
说到更深的就溜了溜了{:4_170:} 马黑黑 发表于 2024-6-4 13:21
background 图片的位置和样纸应设为 center/cover
这俩常见的样子。。{:4_170:} 南无月 发表于 2024-6-4 17:50
这俩常见的样子。。
position/size
意思是 位置 / 尺寸
center / cover ,就是背景图片居中摆放,以封面(cover)女郎的样纸做尺寸,cover大致意思是保持封面女郎不变形,以最短边为依据,按比例截取最长边