探照灯动画
这篇教学会使用 CSS 的裁切路径 clip-path 和图像遮罩 mask,将虚拟元素转换成“探照灯”,做出有趣又吸睛的 CSS 探照灯动画,最后还会搭配 JavaScript 让探照灯可以跟随鼠标移动。
快速导览:
探照灯动画 ( 虚拟元素 + 裁切路径 clip-path )
制作探照灯的第一种方法为“虚拟元素 + 裁切路径”,透过 clip-path 样式属性,将盖在背景图上的虚拟元素 ::before 裁切出一个圆形,搭配半透明的黑色 ::after,就能做出探照灯,最后只要搭配动画,就能让探照灯动起来,详细说明写在下方范例注解中。
- 这种做法如果要加入文字,必须得将文字写在虚拟元素的
content里,换行时需要使用white-space: pre;搭配换行符\A。- 参考:虚拟元素选择器 ( 伪元素 )、裁切路径 clip-path。
<!-- HTML 程式碼 -->
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
position: relative; /* 讓虛擬元素定位參考 */
width: 450px;
height: 300px;
background: url("https://steam.oxxostudio.tw/image/index-css.jpg");
background-size: contain; /* 背景填滿設定 */
}
div::before, div::after {
position: absolute; /* 絕對定位產生重疊 */
white-space: pre; /* 讓 content 支援換行符 */
content: "Hello World\A\A\A oxxo.studio"; /* 加入文字 */
line-height: 1.5;
width: 100%; /* 尺寸與底圖大小相同 */
height: 100%;
text-align: center;
font-size: 50px;
}
div::before {
color: #fff3; /* 文字較暗,像是被遮住 */
background: #000c; /* 半透明黑色遮住底圖 */
}
div::after {
color: #fff; /* 文字較亮,像是被燈照到 */
background: url("https://steam.oxxostudio.tw/image/index-css.jpg"); /* 和底圖相同的圖 */
background-size: contain; /* 和底圖相同的填滿設定 */
clip-path: circle(120px at 50% 50%); /* 使用圓形裁切路徑 */
animation: oxxo 3s alternate infinite ease-in-out;
}
@keyframes oxxo {
0% {clip-path: circle(120px at 10% 50%);} /* 動畫改變圓心位置 */
100% {clip-path: circle(120px at 90% 50%);}
}
</style>
探照灯动画 ( 虚拟元素 + 图像遮罩 mask )
制作探照灯的第二种方法为“虚拟元素 + 图像遮罩”,透过 mask-image 样式属性读取圆形渐层 radial-gradient,将盖在背景图上黑色半透明的虚拟元素 ::before 裁切出一个圆形,就能做出探照灯,最后只要搭配动画,就能让探照灯动起来,详细说明写在下方范例注解中。
- 这种做法非常直觉,且可以在元素里加上其他内容,内容也会一并套用探照灯效,但要额外使用子定属性
@property,才能透过动画改变渐层位置。- 参考:虚拟元素选择器 ( 伪元素 )、图像遮罩 mask、radial-gradient()、@property 自订属性值。
<!-- HTML 程式碼 -->
<div>
<h1>Hello World</h1>
<h2>oxxo.studio</h2>
</div>
<!-- CSS 程式碼 -->
<style>
/* 百分比自訂屬性 */
@property --x {
syntax: "<percentage>";
inherits: true;
initial-value: 10%;
}
/* 百分比自訂屬性 */
@property --y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
/* 放在探照燈效果中的內容 */
h1, h2 {
text-align: center;
margin: 0;
padding: 0;
font-size: 50px;
line-height: 1;
}
h2 {margin-top: 160px;}
div {
position: relative; /* 提供虛擬元素定位參考 */
width: 450px;
height: 300px;
background: url("https://steam.oxxostudio.tw/image/index-css.jpg");
background-size: contain;
box-sizing: border-box; /* 寬度包含 padding */
padding: 20px;
color: #fff;
}
div::before {
position: absolute; /* 絕對定位覆蓋底圖 */
content: "";
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000c; /* 半透明黑色 */
mask-mode: luminance; /* 設定遮罩圖片為亮度模式 */
mask-image: radial-gradient(circle at var(--x) var(--y), #000 120px, #fff 120px); /* 遮罩效果 */
animation: oxxo 3s alternate infinite ease-in-out;
}
@keyframes oxxo {
0% {--x: 10%;} /* 動畫改變圓心位置 */
100% {--x: 90%;}
}
</style>
JavaScript 鼠标控制探照灯 ( 裁切版 )
延伸上述“虚拟元素 + 裁切路径 clip-path”范例程序码,先将 CSS 中圆心位置改用“CSS 变数”,接着就能透过 JavaScript 把鼠标座标的值赋予给 CSS 变数,探照灯也就会跟着鼠标移动,详细说明参考下方范例注解。
参考:CSS 变数
<!-- HTML 程式碼 -->
<div></div>
<!-- CSS 程式碼 -->
<style>
div {
position: relative;
width: 450px;
height: 300px;
background: url("https://steam.oxxostudio.tw/image/index-css.jpg");
background-size: contain;
box-sizing: border-box;
--x: 50%;
--y: 50%;
}
div::before, div::after {
box-sizing: border-box;
position: absolute;
white-space: pre;
content: "Hello World\A\A\A oxxo.studio";
line-height: 1.5;
width: 100%;
height: 100%;
text-align: center;
font-size: 50px;
}
div::before {
color: #fff3;
background: #000c;
}
div::after {
color: #fff;
background: url("https://steam.oxxostudio.tw/image/index-css.jpg");
background-size: contain;
clip-path: circle(120px at var(--x) var(--y));
animation: oxxo 3s alternate infinite ease-in-out;
}
</style>
<script>
const item = document.querySelector('div');
let ox = item.offsetLeft; // 取得這個元素的座標,方便轉換為遮罩相對位置
let oy = item.offsetTop;
item.addEventListener('mousemove', function(e){
let x = e.pageX - ox; // 計算滑鼠與座標的相對位置,也就是實際點擊圖片的位置
let y = e.pageY - oy; // 計算滑鼠與座標的相對位置,也就是實際點擊圖片的位置
item.style.setProperty('--x',`${x}px`); // 替換 CSS 變數內容
item.style.setProperty('--y',`${y}px`); // 替換 CSS 變數內容
});
</script>
JavaScript 鼠标控制探照灯 ( 遮罩版 )
延伸上述“虚拟元素 + 图像遮罩 mask”范例程序码,因为已经使用 CSS 自订属性作圆心位置,可以直接里用 JavaScript 把鼠标座标的值赋予给 CSS 属性,探照灯也就会跟着鼠标移动,详细说明参考下方范例注解。
需要特别注意自订属性的 syntax 要改为“
length”,参考:@property 自订属性值
<!-- HTML 程式碼 -->
<div>
<h1>Hello World</h1>
<h2>oxxo.studio</h2>
</div>
<!-- CSS 程式碼 -->
<style>
/* 長度自訂屬性 */
@property --x {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
/* 長度比自訂屬性 */
@property --y {
syntax: "<length>";
inherits: true;
initial-value: 0px;
}
h1, h2 {
text-align: center;
margin: 0;
padding: 0;
font-size: 50px;
line-height: 1;
}
h2 {margin-top: 160px;}
div {
position: relative;
width: 450px;
height: 300px;
background: url("https://steam.oxxostudio.tw/image/index-css.jpg");
background-size: contain;
box-sizing: border-box;
padding: 20px;
color: #fff;
}
div::before {
position: absolute;
content: "";
top: 0;
left: 0;
background: #000c;
width: 100%;
height: 100%;
mask-mode: luminance; /* 設定遮罩圖片為亮度模式 */
mask-image: radial-gradient(circle at var(--x) var(--y), #000 120px, #fff 120px);
}
</style>
<script>
const item = document.querySelector('div');
let ox = item.offsetLeft; // 取得這個元素的座標,方便轉換為遮罩相對位置
let oy = item.offsetTop;
item.addEventListener('mousemove', function(e){
let x = e.pageX - ox; // 計算滑鼠與座標的相對位置,也就是實際點擊圖片的位置
let y = e.pageY - oy; // 計算滑鼠與座標的相對位置,也就是實際點擊圖片的位置
item.style.setProperty('--x',`${x}px`); // 替換 CSS 屬性內容
item.style.setProperty('--y',`${y}px`); // 替換 CSS 屬性內容
});
</script>
小结
这篇教学介绍了两种制作遮罩的方法,不外乎都是需要将黑色或图形裁切成圆形,相信只要运用得当,一定能在网站中产生有趣又吸睛的效果喔。
微信扫码关注
抖音扫码关注