使用mask-image實(shí)現(xiàn)星球大戰(zhàn)場景過渡效果
前言
大家有看過星球大戰(zhàn)這部電影嗎,里面有許多場景間的過渡效果看起來非常的絲滑,那我們能不能使用CSS來模擬實(shí)現(xiàn)一下呢?
漸變體驗(yàn)
如果mask-image以圖像或漸變的形式出現(xiàn),則我們可以控制與元素的哪些像素是可見的,哪些像素是不可見的(透明)。當(dāng)mask-image應(yīng)用于元素時(shí),它充當(dāng)一種映射,確定每個(gè)元素的可見性。
下面嘗試將兩張圖片使用mask-image實(shí)現(xiàn)交叉淡入淡出效果
<template>
<div :class="$style.xq_outer">
<div :class="$style.xq_bg"></div>
<div :class="$style.xq_women"></div>
</div>
</template>
<style lang="scss" module>
.xq_outer {
position: relative;
width: 600px;
height: 360px;
margin: 20px auto;
background: red;
}
.xq_bg {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_bg.jpeg");
background-size: 100% 100%;
}
.xq_women {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_women.jpeg");
background-size: 100% 100%;
-webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
}
</style>
效果是這樣的:
這里第一眼看上去你不會以為這就是一張圖片吧,其實(shí)這是由星球背景 + 人物兩張圖片“合成”的。
是不是有點(diǎn)PS的感覺了。
「原理是:第一個(gè)場景是星球,第二個(gè)場景是人物,直接位于第一個(gè)場景之上。在第二個(gè)場景中使用漸變蒙版使其左側(cè)透明,從而顯示出第一個(gè)場景。」
-webkit-mask-image為linear-gradient()從左到右漸變。
- 前三分之一是完全透明的,所以這部分人物圖片是不可見的,底下的星球圖片露出。
- 中間的三分之一從透明變?yōu)椴煌该鞯陌咨?,場景逐漸淡入。
- 最后三分之一是完全不透明的白色,導(dǎo)致這部分人物圖片完全可見,底下的星球完全被蓋住。
水平擦除過渡
了解了上面這個(gè)效果的實(shí)現(xiàn)原理,我們就可以來著手實(shí)現(xiàn)第二個(gè)水平擦除效果了,從上面這個(gè)例子我們不難想象到只要蒙版拉伸到比實(shí)際場景更寬,然后動(dòng)畫水平滑動(dòng),就能夠?qū)崿F(xiàn)這個(gè)水平擦除效果了。
.xq_outer {
position: relative;
width: 600px;
height: 360px;
margin: 20px auto;
}
.xq_bg {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_bg.jpeg");
background-size: 100% 100%;
}
.xq_women {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_women.jpeg");
background-size: 100% 100%;
// -webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
-webkit-mask-image: linear-gradient(to right, transparent 48%, #fff 52%);
-webkit-mask-size: 210%;
-webkit-mask-position: left;
}
.xq_outer:is(:hover) .xq_women {
-webkit-mask-position: right;
transition: -webkit-mask-position 2s linear;
}
效果如下:
「原理:蒙版的大小為-webkit-mask-size: 210%- 這為場景提供了 100% 的寬度,最初是完全透明的 + 10% 的淡入淡出 + 另一個(gè) 100% 的場景最終完全不透明?!?/p>
光圈擦除過渡
下面再來看一種光圈擦除效果,這里將會使用到@property自定義屬性,由于這個(gè)屬性還處于實(shí)驗(yàn)階段,所以在將其用于生產(chǎn)之前,請仔細(xì)檢查瀏覽器兼容性表格。
大致的思路是:使用radial-gradient()在其中定義一個(gè)自定義屬性。然后我們可以對該自定義屬性進(jìn)行動(dòng)畫處理以對漸變進(jìn)行動(dòng)畫處理。但在此之前,我們需要將自定義屬性注冊到@property.
@property --r {
syntax: "<percentage>";
inherits: true;
initial-value: -5%;
}
.xq_women {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_women.jpeg");
background-size: 100% 100%;
// -webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
// -webkit-mask-image: linear-gradient(to right, transparent 48%, #fff 52%);
// -webkit-mask-size: 210%;
// -webkit-mask-position: left;
-webkit-mask-image: radial-gradient(
circle,
#fff calc(var(--r) - 5%),
transparent calc(var(--r) + 5%)
);
}
@keyframes circle {
to {
--r: 105%;
}
}
.xq_outer:is(:hover) .xq_women {
// -webkit-mask-position: right;
// transition: -webkit-mask-position 2s linear;
animation: circle 2s linear forwards;
}
再來看看此時(shí)的效果:
「原理:隨著 --radius 的動(dòng)畫化,radial-gradient() 中的色標(biāo)位置也是如此。它們被計(jì)算為 --radius 值的 -5% 和 +5%,以創(chuàng)建漸變淡入淡出,為擦拭提供柔和的邊緣?!?/p>
時(shí)鐘擦除過渡
再來看一個(gè)星球大戰(zhàn)中最具標(biāo)志性的擦除過渡——時(shí)鐘擦除過渡。這次我們使用conic-gradient()和動(dòng)畫化一個(gè)自定義屬性angle值。
@property --angle {
syntax: "<angle>";
inherits: true;
initial-value: -10deg;
}
.xq_women {
position: absolute;
width: 100%;
height: 100%;
background-image: url("/public/xq_women.jpeg");
background-size: 100% 100%;
-webkit-mask-image: conic-gradient(
#fff 0deg,
#fff calc(var(--angle) - 10deg),
transparent calc(var(--angle) + 10deg),
transparent 360deg
),
conic-gradient(transparent 350deg, #fff 360deg);
z-index: -1;
}
@keyframes ang {
to {
--angle: 370deg;
}
}
.xq_outer:is(:hover) .xq_women {
animation: ang 2s linear forwards;
z-index: 1;
}
效果如下:
「原理:第一個(gè)conic-gradient()動(dòng)畫以創(chuàng)建時(shí)鐘擦除效果,但它在其起點(diǎn)(在 處0deg)留下了硬邊。這就是為什么要conic-gradient()在硬邊緣之前創(chuàng)建一個(gè)小的淡入淡出并將其軟化的原因。漸變結(jié)合在一起為場景創(chuàng)建蒙版。」
總結(jié)
現(xiàn)在的CSS功能越來越強(qiáng)大了,在本文中介紹了很多 CSS 成分,包括不同類型的漸變、注冊自定義屬性,當(dāng)然還有遮罩和動(dòng)畫。這在以前,僅僅靠CSS是不可能實(shí)現(xiàn)的效果!