请马上登录,朋友们都在花潮里等着你哦:)
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 马黑黑 于 2025-8-10 18:10 编辑
CSS 属性 mask 属性允许用户使用图片去遮罩使用了该属性的元素的指定区域。利用此属性,可以实现美妙的图片转场效果。
实现思路:
多张图片放入数组待用,接着按顺序读取数组图片,第 n 张图片做主元素背景,第 n+1 张图片做伪元素的背景,每间隔一段时间执行一次,如此循环往复。伪元素做图片入场、出场效果,使用 mask 进行线性或其它渐变遮罩(本文使用线性渐变遮罩),非透明渐变区域是伪元素背景图呈现的区域,先从 -2% 开始,0% 开始是透明区域伪元素背景不可见,然后非透明区域递增到 100%,这样伪元素上的背景图片入场方式就是淡入,而上一张图片已是主元素背景图片,它的出场就是淡出。伪元素进出的角度可以随意设计,本文采用矩形四个角作为进出场的地点。
以下是具体代码,可以点击代码框右上角的预览链接查看效果:
<style>
#pa {
margin: 30px auto;
width: 1024px;
height: 640px;
background: var(--bg);
position: relative;
/* 主元素初始背景图片为JS数组中最后一张 */
--bg: url('https://638183.freep.cn/638183/t24/w5/g5.webp') no-repeat center/cover;
--bg1: none; /* 伪元素开始时背景为空 */
}
/* 伪元素使用遮罩 */
#pa::before {
content: '';
position: absolute;
inset: 0;
background: var(--bg1);
mask: linear-gradient(var(--a), red var(--per), transparent calc(var(--per) + 2%), transparent);
/* 兼容版本 < 120 的 Chrome */
-webkit-mask: linear-gradient(var(--a), red var(--per), transparent calc(var(--per) + 2%), transparent);
}
/* 关键帧动画播放控制器 */
#ma {
position: absolute;
left: 40px;
top: 40px;
animation: rot 8s linear infinite;
}
/* 指针移入时暂停关键帧动画 */
#ma:hover {
animation-play-state: paused;
}
@keyframes rot {
to { transform: rotate(1turn); }
}
</style>
<div id="pa">
<img id="ma" src="https://638183.freep.cn/638183/small/780.webp" alt="" title="移出播放/移入暂停" />
</div>
<script>
// per : 遮罩起始点,step : 递增系数,aniCounter : 关键帧动画运行计数器,
// raf : requestAnimationFrame API 计数器
var per = -2, step = 0.5, aniCounter = 0, raf;
// 图片数组
var pics = [
'https://638183.freep.cn/638183/t24/w5/g1.webp',
'https://638183.freep.cn/638183/t24/w5/g2.webp',
'https://638183.freep.cn/638183/t24/w5/g3.webp',
'https://638183.freep.cn/638183/t24/w5/g4.webp',
'https://638183.freep.cn/638183/t24/w5/g5.webp'
];
// 播放控制器关键帧运行迭代事件
ma.onanimationiteration = () => {
// angle : 渐变角度,picIdx : 图片序号
var angle = aniCounter % 4, picIdx = aniCounter % pics.length;
// 更新CSS变量 --a
pa.style.setProperty('--a', `${45 + (angle * 90)}deg`);
// 更新伪元素使用的CSS变量 --bg1
pa.style.setProperty('--bg1', `url(${pics[picIdx]}) no-repeat center/cover`);
picIdx = (picIdx + 1) % pics.length; // 图片序号变更
aniCounter ++; // 关键帧动画计数器递增
changePic(); // 运行图片转场函数
};
// 图片转场函数
function changePic() {
// 遮罩起始点若大于 100
if (per > 100) {
cancelAnimationFrame(raf); // 取消请求关键帧动画API计数器
per = -2; // 遮罩起始点回到原始值
var picIdx = aniCounter % pics.length; // 计算当前图片序号
picIdx = picIdx > 0 ? picIdx - 1: pics.length - 1; // 防止序号超出范围
// 更新主元素背景图
pa.style.setProperty('--bg', `url(${pics[picIdx]}) no-repeat center/cover`);
// 否则
} else {
per += step; // 遮罩起始点递增
pa.style.setProperty('--per', per + '%'); // 更新遮罩起始点
raf = requestAnimationFrame(changePic); // 递归运行函数自身并更新raf计数器
}
}
</script>
mask 遮罩所使用的线性渐变角度可以使用数组替代算式以设计更具个性化的变换方式。此外,可以考虑其它方式的渐变背景,甚至可以使用图片、SVG路径。
|