Purple Magic
<style>#pa { --per: 0%; margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover, rgba(0,128,0,.45); background-blend-mode: difference; box-shadow: 2px 2px 8px #000; z-index: 1; overflow: hidden; position: relative; }
#pa::after { content: ''; position: absolute; width: 100%; height: 100%; background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover; clip-path: polygon(0 calc(100% - var(--per)), var(--per) 100%, 100% 100%, 100% var(--per), calc(100% - var(--per)) 0, 0 0); transition: 1s; }
#pa:hover { --per: 100%; }
#player { position: absolute; bottom: 100px; left: 100px; height: 120px; width: 120px; cursor: pointer; transform-style: preserve-3d; animation: rot 6s linear infinite var(--state); }
li-zi { --hh: 35%; position: absolute; left: -50%; top: calc(50% - var(--hh)); width: 100%; height: var(--hh); background: radial-gradient(circle at 10% 10%, red, purple); border-radius: 50% 100% 0 100%; box-shadow: inset 0 0 30px lightblue, 2px 4px 16px rgba(0,0,0,.35); transform-origin: 100% 100%; }
#btnFs { left: 20px; bottom: 20px; color: #eee; }
.vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .45; z-index: 9; pointer-events: none; }
@keyframes rot {
to { transform: rotate(1turn); }
}
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2697499554" autoplay loop></audio>
<video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/25/03/05/12/16/26/video67c7d01a5fa5e.mp4" autoplay loop muted></video>
<div id="player"></div>
</div>
<script type="module">
import { FS } from 'https://638183.freep.cn/638183/web/js/fullscreen.js';
FS(pa, player);
const tt = 12;
Array.from({length: tt}).forEach( (lz,idx) => {
lz = document.createElement('li-zi');
lz.style.cssText += `transform: rotate3d(0, 0.1, 1, ${idx * 360 / tt}deg);`;
player.appendChild(lz);
});
</script> 参考代码
<style>
#pa { --per: 0%; margin: 30px 0; left: calc(50% - 81px); transform: translateX(-50%); width: clamp(600px, 90vw, 1400px); height: auto; aspect-ratio: 16/9; background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover, rgba(0,128,0,.45); background-blend-mode: difference; box-shadow: 2px 2px 8px #000; z-index: 1; overflow: hidden; position: relative; }
#pa::after { content: ''; position: absolute; width: 100%; height: 100%; background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover; clip-path: polygon(0 calc(100% - var(--per)), var(--per) 100%, 100% 100%, 100% var(--per), calc(100% - var(--per)) 0, 0 0); transition: 1s; }
#pa:hover { --per: 100%; }
#player { position: absolute; bottom: 100px; left: 100px; height: 120px; width: 120px; cursor: pointer; transform-style: preserve-3d; animation: rot 6s linear infinite var(--state); }
li-zi { --hh: 35%; position: absolute; left: -50%; top: calc(50% - var(--hh)); width: 100%; height: var(--hh); background: radial-gradient(circle at 10% 10%, red, purple); border-radius: 50% 100% 0 100%; box-shadow: inset 0 0 30px lightblue, 2px 4px 16px rgba(0,0,0,.35); transform-origin: 100% 100%; }
#btnFs { left: 20px; bottom: 20px; color: #eee; }
.vid {position: absolute; width: 100%; height: 100%; object-fit: cover; mask: radial-gradient(transparent 20%, red); -webkit-mask: radial-gradient(transparent 20%, red); opacity: .45; z-index: 9; pointer-events: none; }
@keyframes rot {
to { transform: rotate(1turn); }
}
</style>
<div id="pa">
<audio id="aud" src="https://music.163.com/song/media/outer/url?id=2697499554" autoplay loop></audio>
<video class="vid" src="https://bpic.588ku.com/video_listen/588ku_video/25/03/05/12/16/26/video67c7d01a5fa5e.mp4" autoplay loop muted></video>
<div id="player"></div>
</div>
<script type="module">
import { FS } from 'https://638183.freep.cn/638183/web/js/fullscreen.js';
FS(pa, player);
const tt = 12;
Array.from({length: tt}).forEach( (lz,idx) => {
lz = document.createElement('li-zi');
lz.style.cssText += `transform: rotate3d(0, 0.1, 1, ${idx * 360 / tt}deg);`;
player.appendChild(lz);
});
</script>
本帖最后由 马黑黑 于 2025-7-27 11:11 编辑
帖子容器使用 background-blend-mode 将背景图片与设定颜色融合;帖子容器伪元素使用正常的同图背景并覆盖整个帖子容器,伪元素同时使用 clip-path(裁剪路径)属性对自身进行 polygon(多边形)裁剪,通过变量 --per 来达成:开始时 0% 表示什么都不裁剪,然后指针(移入移出容器)交互时 100% 表示全裁剪(露出容器真容)。
全屏时由于鼠标指针就在容器上方移不出来,伪元素头巾自动揭掉。
也可以考虑使用不同的背景图于容器和伪元素,以便令帖子的表现力更为丰厚。裁剪方式也可以是别样的。
小播设计非新,但实现细节自有特色。 真漂亮!欣赏老师的精彩音画。祝夏安!{:4_190:} 这个挺奇妙,还没整明白,我得想想这个怎么实现的{:4_187:} 本帖最后由 马黑黑 于 2025-7-27 11:32 编辑
红影 发表于 2025-7-27 11:00
这个挺奇妙,还没整明白,我得想想这个怎么实现的
一切通过CSS操作,核心代码拆解如下:
/* 容器元素核心设置 */
#pa {
--per: 0%; /* 设置一个百分比变量(用于裁剪) */
/* ... 其它代码 */
/* 背景图片 */
background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover, rgba(0,128,0,.45);
/* ... 其它代码 */
}
/* 伪元素核心设置 */
#pa::after {
/* ... 其它代码 */
/* 背景图片和容器一样 */
background: url('https://638183.freep.cn/638183/t24/6/rc02.jpg') no-repeat center/cover;
/* 多边形裁剪路径,从矩形ABCD的左下、右上往AC对角线裁剪,例如:
0 95%,
5% 100,
100% 100%,
100% 5%,
95% 0,
0 0
注意:0 和 100% 固定不变,5% 及 95% 和 100 存在算法关系
下面用变量和式子替代非 0 非 100% 的数字
*/
clip-path: polygon(
0 calc(100% - var(--per)),
var(--per) 100%,
100% 100%,
100% var(--per),
calc(100% - var(--per)) 0,
0 0
);
transition: 1s; /* 动画时长 */
}
/* 容器伪类选择器 :hover 改变 --per 变量值 */
#pa:hover { --per: 100%; }
马黑黑 发表于 2025-7-27 08:02
帖子容器使用 background-blend-mode 将背景图片与设定颜色融合;帖子容器伪元素使用正常的同图背景并覆盖 ...
终于看明白了,开始--per为0 ,多边形切割的六个点都在四个顶角上,所以不切割,那么伪元素(没混合颜色的)就覆盖了底图(混合颜色了的)也遮挡了小播。随着鼠标触动,在1s的时间里,--per从0变化到100,六个点的左下和右上开始分别顺着相邻两条边朝(0 0)和(100 100)运动,直到重合,这时伪元素被完全切割掉了,底图和小播全部出现。
鼠标移开是反向运动,重复上述过程。
开始我弄错了,还以为切了两个三角形,还在奇怪多边形只能切一个形状,这里为什么出现两个。是那个混合色把我弄糊涂了,以为是它覆盖上来了。错得离谱。现在明白了{:4_173:}
马黑黑 发表于 2025-7-27 11:30
一切通过CSS操作,核心代码拆解如下:
吃完饭过来就继续使劲看了,没刷新,回复完了才看到这个解说,不好意思。
嗯,开始没看到 --per: 0%; 其实在帖子代码的嘴上头,然后以为带底色的来覆盖,所以开始时弄错,弄得自己没想明白{:4_173:} 小播是用粒子组成的。粒子的形状和颜色设计很漂亮。
lz.style.cssText += `transform: rotate3d(0, 0.1, 1, ${idx * 360 / tt}deg);`;这里的数字也挺有讲究。 红影 发表于 2025-7-27 12:01
终于看明白了,开始--per为0 ,多边形切割的六个点都在四个顶角上,所以不切割,那么伪元素(没混合颜色 ...
这个设计你应该是容易理解的,难不倒高级空间测算工程师。主要是代码多了会形成理解上的干扰,加上又是连在一起些不很分明。 红影 发表于 2025-7-27 12:13
小播是用粒子组成的。粒子的形状和颜色设计很漂亮。
lz.style.cssText += `transform: rotate3d(0, 0.1, 1 ...
其实也不是粒子,就用了 li-zi 这样的标签,标准的规范应用用 impeller、petal 乃至 leaf 这样的英文名称。主要是图个方便,不用声明 className 红影 发表于 2025-7-27 12:08
吃完饭过来就继续使劲看了,没刷新,回复完了才看到这个解说,不好意思。
嗯,开始没看到 --per: 0%; 其 ...
理解他人的代码,尤其是没有注释说明的,一般都是个难题呢,即便是同做一个项目的同事 效果惊艳,很有特色,谢谢马老师经典讲授与分享{:4_190:} 马黑黑 发表于 2025-7-27 12:43
这个设计你应该是容易理解的,难不倒高级空间测算工程师。主要是代码多了会形成理解上的干扰,加上又是连 ...
开始看时弄错了,后来整明白了,谢谢黑黑{:4_187:} 马黑黑 发表于 2025-7-27 12:46
其实也不是粒子,就用了 li-zi 这样的标签,标准的规范应用用 impeller、petal 乃至 leaf 这样的英文名称 ...
嗯嗯,名称是自设的,其实用什么都行{:4_173:} 马黑黑 发表于 2025-7-27 12:47
理解他人的代码,尤其是没有注释说明的,一般都是个难题呢,即便是同做一个项目的同事
黑黑的代码逻辑清晰、严谨,设计也很奇妙,很值得学习呢和理解呢{:4_187:} 精彩,学生已交作业,请老师指正{:4_190:} 红影 发表于 2025-7-27 15:03
黑黑的代码逻辑清晰、严谨,设计也很奇妙,很值得学习呢和理解呢
果酱果酱 红影 发表于 2025-7-27 15:02
嗯嗯,名称是自设的,其实用什么都行
一般建议语义化,这是为了好理解 红影 发表于 2025-7-27 15:01
开始看时弄错了,后来整明白了,谢谢黑黑
这个正常现象