花下醉(4首)
本帖最后由 马黑黑 于 2023-2-26 08:45 编辑 <br /><br /><style>#papa {
margin: -80px 0 0 calc(50% - 593px);
width: 1024px;
height: 640px;
background: lightblue url('https://638183.freep.cn/638183/t23/webp/hxz.webp') no-repeat center/cover;
box-shadow: 3px 3px 20px #000;
position: relative;
user-select: none;
z-index: 1;
--state: paused;
}
#fly {
position: absolute;
left: 0;
width: 360px;
height: 200px;
animation: fly 100s infinite alternate var(--state);
}
.mplayer {
--tt: 6s;
position: absolute;
left: 0;
width: 200px;
height: 200px;
border-radius: 50%;
transform: perspective(1000px) rotateX(45deg) rotateY(30deg);
animation: rot var(--tt) infinite var(--state);
cursor: pointer;
transition: .45s;
}
.mplayer:hover { filter: drop-shadow(0 0 80px green) brightness(200%); }
.mplayer:nth-of-type(2) {
--tt: 4s;
left: 210px;
width: 150px;
height: 150px;
}
.mplayer:nth-of-type(3) {
--tt: 2s;
left: 130px;
width: 100px;
height: 100px;
}
#drunken {
position: absolute;
bottom: 60px;
left: 23%;
mix-blend-mode: multiply;
cursor: pointer;
}
#btnFs {
position: absolute;
left: 50%;
transform: translate(-50%);
bottom: 20px;
width: fit-content;
height: fit-content;
padding: 6px;
border-radius: 6px;
border: 2px solid snow;
color: snow;
display: none;
cursor: pointer;
}
@keyframes rot { to { transform: perspective(1000px) rotateX(45deg) rotateY(30deg) rotateZ(360deg); } }
@keyframes fly { to { left: calc(50% - 360px); } }
</style>
<div id="papa">
<div id="fly">
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/rose.png" alt="" />
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/toui.png" alt="" />
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/7sh-1.png" alt="" />
</div>
<img id="drunken" src="/static/image/smiley/hcbiaoqing2/130.gif" title="下一首" alt="" />
<div id="btnFs">全屏观赏</div>
</div>
<audio id="aud"></audio>
<script>
(function() {
let fs = false, timerId;
let ypAr = ['38392980','158378','315691','1907058655'];
let mState = () => papa.style.setProperty('--state', aud.paused ? 'paused' : 'running');
let playNext = () => {
aud.src = 'https://music.163.com/song/media/outer/url?id=' + ypAr + '.mp3';
aud.play();
}
let btns = document.querySelectorAll('.mplayer');
[...btns].forEach((item) => item.onclick = () => aud.paused ? aud.play() : aud.pause());
aud.addEventListener('play', () => mState());
aud.addEventListener('pause', () => mState());
aud.addEventListener('ended', () => playNext());
drunken.addEventListener('click', () => playNext());
btnFs.addEventListener('click', () => fs ? document.exitFullscreen() : papa.requestFullscreen());
document.addEventListener('fullscreenchange', () => document.fullscreenElement !== null ? (fs = true, btnFs.innerText = '退出全屏') : (fs = false, btnFs.innerText = '全屏观赏'));
papa.addEventListener('mousemove', (e) => {
clearTimeout(timerId);
btnFs.style.display = 'block';
timerId = setTimeout('btnFs.style.display = "none"', 3000);
});
playNext();
})();
</script>
帖子代码
<style>
#papa {
margin: -80px 0 0 calc(50% - 593px);
width: 1024px;
height: 640px;
background: lightblue url('https://638183.freep.cn/638183/t23/webp/hxz.webp') no-repeat center/cover;
box-shadow: 3px 3px 20px #000;
position: relative;
user-select: none;
z-index: 1;
--state: paused;
}
#fly {
position: absolute;
left: 0;
width: 360px;
height: 200px;
animation: fly 100s infinite alternate var(--state);
}
.mplayer {
--tt: 6s;
position: absolute;
left: 0;
width: 200px;
height: 200px;
border-radius: 50%;
transform: perspective(1000px) rotateX(45deg) rotateY(30deg);
animation: rot var(--tt) infinite var(--state);
cursor: pointer;
transition: .45s;
}
.mplayer:hover { filter: drop-shadow(0 0 80px green) brightness(200%); }
.mplayer:nth-of-type(2) {
--tt: 4s;
left: 210px;
width: 150px;
height: 150px;
}
.mplayer:nth-of-type(3) {
--tt: 2s;
left: 130px;
width: 100px;
height: 100px;
}
#drunken {
position: absolute;
bottom: 60px;
left: 23%;
mix-blend-mode: multiply;
cursor: pointer;
}
#btnFs {
position: absolute;
left: 50%;
transform: translate(-50%);
bottom: 20px;
width: fit-content;
height: fit-content;
padding: 6px;
border-radius: 6px;
border: 2px solid snow;
color: snow;
display: none;
cursor: pointer;
}
@keyframes rot { to { transform: perspective(1000px) rotateX(45deg) rotateY(30deg) rotateZ(360deg); } }
@keyframes fly { to { left: calc(50% - 360px); } }
</style>
<div id="papa">
<div id="fly">
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/rose.png" alt="" />
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/toui.png" alt="" />
<img class="mplayer" src="https://638183.freep.cn/638183/t23/1/7sh-1.png" alt="" />
</div>
<img id="drunken" src="/static/image/smiley/hcbiaoqing2/130.gif" title="下一首" alt="" />
<div id="btnFs">全屏观赏</div>
</div>
<audio id="aud"></audio>
<script>
(function() {
let fs = false, timerId;
let ypAr = ['38392980','158378','315691','1907058655'];
let mState = () => papa.style.setProperty('--state', aud.paused ? 'paused' : 'running');
let playNext = () => {
aud.src = 'https://music.163.com/song/media/outer/url?id=' + ypAr + '.mp3';
aud.play();
}
let btns = document.querySelectorAll('.mplayer');
[...btns].forEach((item) => item.onclick = () => aud.paused ? aud.play() : aud.pause());
aud.addEventListener('play', () => mState());
aud.addEventListener('pause', () => mState());
aud.addEventListener('ended', () => playNext());
drunken.addEventListener('click', () => playNext());
btnFs.addEventListener('click', () => fs ? document.exitFullscreen() : papa.requestFullscreen());
document.addEventListener('fullscreenchange', () => document.fullscreenElement !== null ? (fs = true, btnFs.innerText = '退出全屏') : (fs = false, btnFs.innerText = '全屏观赏'));
papa.addEventListener('mousemove', (e) => {
clearTimeout(timerId);
btnFs.style.display = 'block';
timerId = setTimeout('btnFs.style.display = "none"', 3000);
});
playNext();
})();
</script>
全屏、音乐控制均未使用插件,便于大家观察、学习。解释一下JS代码:
83行:两个变量,fs 是 全屏依赖变量,布尔类型(true 或 false);timeId 是定时器依赖变量,setTimeout 定时器清除和启用句柄,控制全屏相关的按钮显示/隐藏的依托。
84行:声明wyy音乐id数组;
85行:自定义函数,音乐控制器的关键帧动画控制预设;
86行 - 89行:自定义函数,播放音乐,随机播放。几个地方会用到它,一是页面打开时(103行),二是一支曲子播放完毕时(94行),三是点击小醉鬼时(95行);
90行:声明音频播放控制器句柄,这是三个“按钮”,所以放入集合变量中;
91行:“按钮”集合点击事件。btns 变量属对象变量,将之变成可操作的数组,所以使用扩展运算符 ... 将其变为数组对象,即[...btns] ,这样就可以用 forEach 方法对数组元素(按钮)进行操作;
92行 - 94行:audio 控件监听事件,各行分别监听 audio 控件的 play(播放)、pause(暂停)和 ended(播放结束)三个事件,前两个事件运行 85 行的 mState() 函数,即驱动播放控制器的状态,后一个事件运行 86 行开始的函数 playNext() 即播放音乐函数;
95行:监听小醉鬼点击事件,运行的是 playNext() 函数。任何时候都可以点击它更换音乐;
96行:监听全屏按钮点击事件,依据 fs 变量值驱动全屏/窗口模式切换;
97行:监听 document 的 fullscreen 事件,即监听文档的全屏事件,若文档有元素处于全屏状态,则令 fs 变量为真,且设置按钮文本为“退出全屏”,反之,若没有元素处于全屏状态,则令 fs 变量为假,且设置按钮文本为“全屏观赏”;
98行 - 102行:监听帖子父元素 papa 的鼠标指针滑过事件,这里要干的事情是,一是清除定时器记录以便重新计时(99行),二是令全屏按钮现身(100行),三是启动定时器(101行),定时器所做的事情是3秒后令全屏按钮消失。这部分,呈现在web中的效果是,鼠标在帖子区域一旦移动,全屏按钮就会华丽现身,如果鼠标指针静止,3秒钟后按钮消失。
103行:运行一次 playNext() 函数,令页面打开时随机播放四支曲子中的一支。 手机测试点击了按钮和小酒鬼,效果不错{:4_187:} 这个帖子信息量很大,黑黑解说得也特别详细。真棒{:4_199:} 黑黑真的千变万化的效果层出不穷,厉害的 三个不一样小图片了 原来这个多首音乐,在四首音乐里随机切换。
ypAr 这句没看懂,为什么这句就能对应音乐id数组? 小醉鬼能换音乐,三个旋转播放器能暂停和播放音乐{:4_187:} 马黑黑 发表于 2023-2-26 08:37
全屏、音乐控制均未使用插件,便于大家观察、学习。解释一下JS代码:
83行:两个变量,fs 是 全屏依赖变 ...
这个讲得真详细,太棒了{:4_199:} 马黑黑 发表于 2023-2-26 08:37
全屏、音乐控制均未使用插件,便于大家观察、学习。解释一下JS代码:
83行:两个变量,fs 是 全屏依赖变 ...
这样的讲解太仔细的,黑黑教授有水平{:4_178:} 红影 发表于 2023-2-26 09:33
这个讲得真详细,太棒了
大概逻辑讲了,细节哪儿不懂的说一声 小辣椒 发表于 2023-2-26 09:26
手机测试点击了按钮和小酒鬼,效果不错
还木起来呀{:5_106:} 红影 发表于 2023-2-26 09:33
小醉鬼能换音乐,三个旋转播放器能暂停和播放音乐
这正常的呀 转动的图片,感谢老师的精彩分享,问好!{:4_204:} 真不错的代码,感谢分享!{:4_180:} 红影 发表于 2023-2-26 09:26
这个帖子信息量很大,黑黑解说得也特别详细。真棒
重点讲了JS部分,其他的应该都能懂就不讲了 红影 发表于 2023-2-26 09:30
原来这个多首音乐,在四首音乐里随机切换。
ypAr 这句没看懂,为 ...
Math.random() 是JS随机数,其值范围在 0 到 0.999... 之间,如此,Math.random()*ypAr.length 得到的数,在这里,在0 - 3.x 之间,因为数组总数是 4 ;
Math.floor(数字) 往下取整(floor是地板),那么,Math.floor(Math.random()*ypAr.length),得到的是 0 和 3 之间的整数(包含 0 和 3 )。
数组下标从 0 开始,0 是数组的第一个元素,3 是数组的第四个元素。 梦缘 发表于 2023-2-26 09:36
真不错的代码,感谢分享!
上午好 小辣椒 发表于 2023-2-26 09:35
这样的讲解太仔细的,黑黑教授有水平
不嫌啰嗦就好{:5_106:}