先看效果圖(說明:小鬼影會飄來飄去,長時間停留會有小驚喜,具體大家跑一下就知道):
代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-459806.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>403頁面</title>
<style>
@import url('https://fonts.googleapis.com/css?family=Open+Sans|Nova+Mono');
:root {
--font-header: 'Nova Mono', monospace;
--font-text: 'Open Sans', sans-serif;
--color-theme: #F1EEDB;
--color-bg: #282B24;
--animation-sentence: '你知道你應(yīng)該離開,對吧?';
--animation-duration: 40s;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
width: 100%;
font-family: var(--font-text);
color: var(--color-theme);
background: var(--color-bg);
overflow: hidden;
}
.container {
text-align: center;
margin: 1rem 0.5rem 0;
}
.container h1 {
font-family: var(--font-header);
font-size: calc(4rem + 2vw);
text-transform: uppercase;
}
.container p {
text-transform: uppercase;
letter-spacing: 0.2rem;
font-size: 2rem;
margin: 1.5rem 0 3rem;
}
svg.keyhole {
height: 82px;
width: 82px;
opacity: 0;
visibility: hidden;
/* 為鑰匙孔定義一個動畫,以引入默認(rèn)情況下暫停的動畫,在JavaScript中超時運(yùn)行*/
animation: showKey 0.5s 0.5s paused ease-out forwards;
}
svg.key {
height: 164px;
width: 164px;
position: absolute;
opacity: 0;
visibility: hidden;
/* 為鑰匙孔定義一個動畫,以引入默認(rèn)情況下暫停的動畫,在JavaScript中超時運(yùn)行*/
animation: showKey 0.5s 0.5s paused ease-out forwards;
}
.ghost {
/* border: 1px solid tomato; */
position: absolute;
bottom: 5px;
left: calc(50% - 100px);
width: 200px;
height: 200px;
/* 讓鬼影移動到屏幕的右側(cè)和左側(cè),轉(zhuǎn)到其中心位置并重復(fù)動畫兩次 */
animation: hoverGhost calc(var(--animation-duration)/2) ease-in-out 2;
}
/* 通過連接到動畫div的偽元素引入文本 */
.ghost:before {
content: var(--animation-sentence);
color: var(--color-theme);
border-radius: 50%;
position: absolute;
bottom: 100%;
text-align: center;
line-height: 2;
padding: 1rem;
visibility: hidden;
opacity: 0;
/* 當(dāng)鬼影從屏幕右邊緣返回時,引入每一個文本字符串,以及覆蓋中心部分所需的時間長度(第四個字符串,由于動畫長度是總持續(xù)時間的一半,因此變?yōu)榘藗€字符串)
/* 假設(shè)持續(xù)時間為40秒的情況下,第一個延遲為7.5秒,第二個延遲為27.5秒,最后一個延遲為40秒,經(jīng)過運(yùn)算,可以歸結(jié)為316、2740和1
// 記得在鑰匙和鑰匙孔的動畫中加入一點(diǎn)延遲
*/
animation:
showText calc(var(--animation-duration)/8) calc(var(--animation-duration)*3/16) ease-out forwards,
showNewText calc(var(--animation-duration)/8) calc(var(--animation-duration)*27/40) ease-out forwards,
showFinalText calc(var(--animation-duration)/8) var(--animation-duration) ease-out forwards;
}
/* 定義關(guān)鍵幀動畫-懸停鬼影使鬼影向右、向左移動,然后返回到其默認(rèn)位置
-showKey將鑰匙(和鑰匙孔)svg引入視圖
-showText、showNewText、showFinalText顯示不同的字符串*/
@keyframes hoverGhost {
25% {
transform: translateX(20vw);
}
75% {
transform: translateX(-20vw);
}
}
@keyframes showKey {
to {
opacity: 1;
visibility: visible;
}
}
/* 更改文本,更改自定義屬性的值,厭倦了在隱藏偽元素時更改其值,以及在最后一個關(guān)鍵幀中更改其值(因為動畫根據(jù)填充模式屬性的“向前”值給出該值)*/
@keyframes showText {
2% {
opacity: 1;
visibility: visible;
}
98% {
opacity: 1;
visibility: visible;
}
99% {
--animation-sentence: '你知道你應(yīng)該離開,對吧?';
opacity: 0;
visibility: hidden;
}
100% {
--animation-sentence: '這么多事情要做,這么少時間...';
}
}
@keyframes showNewText {
2% {
--animation-sentence: '這么多事情要做,這么少時間...';
opacity: 1;
visibility: visible;
}
98% {
opacity: 1;
visibility: visible;
}
99% {
--animation-sentence: '這么多事情要做,這么少時間...';
opacity: 0;
visibility: hidden;
}
100% {
--animation-sentence: '好吧,你似乎很關(guān)心這個.這是一把只給你的鑰匙..';
}
}
@keyframes showFinalText {
2% {
opacity: 1;
visibility: visible;
}
98% {
opacity: 1;
visibility: visible;
}
100% {
opacity: 0;
visibility: hidden;
}
}
</style>
</head>
<body>
<!-- 包括在項目中使用的svg -->
<svg style="display: none;">
<symbol id="keyhole" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 26.458333 26.458334"><g transform="translate(0 -270.542)"><circle cx="13.229" cy="279.141" r="8.599" fill="#f1eedb" paint-order="stroke fill markers"/><path d="M10.516 283.271h5.427c1.164 0 1.768.861 2.102 1.802l3.59 10.125c.334.94-.937 1.802-2.102 1.802H6.926c-1.165 0-2.437-.861-2.103-1.802l3.59-10.125c.334-.94.938-1.802 2.103-1.802z" fill="#f1eedb" paint-order="stroke fill markers"/><circle r="6.06" cy="279.141" cx="13.229" fill="#282b24" paint-order="stroke fill markers"/><path d="M11.502 283.76h3.455c.741 0 1.126.733 1.338 1.534l2.286 8.614c.213.8-.597 1.534-1.338 1.534H9.216c-.742 0-1.551-.733-1.339-1.534l2.286-8.614c.212-.8.597-1.534 1.339-1.534z" fill="#282b24" paint-order="stroke fill markers"/></g></symbol>
<symbol id="key" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 26.458333 26.458334"><circle cx="13.229" cy="279.141" r="8.599" paint-order="stroke fill markers" transform="matrix(0 -.76923 .7499 0 -202.882 23.405)" fill="#f1eedb"/><circle r="8.599" cy="279.141" cx="13.229" paint-order="stroke fill markers" transform="matrix(0 -.5887 .57392 0 -153.756 21.017)" fill="#282b24"/><path fill="#f1eedb" paint-order="stroke fill markers" d="M12.03 12.13h14.428v2.2H12.03z"/><path fill="#f1eedb" paint-order="stroke fill markers" d="M18.147 12.13h2.895v6.772h-2.895zM22.113 12.13h2.716v5.065h-2.716z"/></symbol>
<symbol id="ghost" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 26.458333 26.458334"><g transform="translate(0 -270.542)"><path d="M4.63 279.293c0-4.833 3.85-8.751 8.6-8.751 4.748 0 8.598 3.918 8.598 8.75H13.23zM4.725 279.293h16.914c.052 0 .19.043.19.096l-.095 14.329c0 .026-.011.05-.028.068a.093.093 0 0 1-.067.028c-.881 0-1.235-1.68-2.114-1.616-.995.072-1.12 2.082-2.114 2.154-.88.064-1.233-1.615-2.115-1.615-.881 0-1.233 1.615-2.114 1.615-.881 0-1.233-1.615-2.114-1.615-.882 0-1.236 1.679-2.115 1.615-.994-.072-1.12-2.082-2.114-2.154-.88-.063-1.41 1.077-2.114 1.616-.021.016-.05-.01-.067-.028a.097.097 0 0 1-.028-.068v-14.33c0-.052.042-.095.095-.095z" fill="#f1eedb" paint-order="stroke fill markers"/><path d="M15.453 281.27a1.987 1.94 0 0 1-.994 1.68 1.987 1.94 0 0 1-1.987 0 1.987 1.94 0 0 1-.994-1.68h1.988z" fill="#282b24" paint-order="stroke fill markers"/><g fill="#282b24" transform="matrix(1 0 0 1.0177 .283 -5.653)"><ellipse cx="10.205" cy="278.668" rx="1.231" ry="1.181" paint-order="stroke fill markers"/><ellipse ry="1.181" rx="1.231" cy="278.668" cx="16.159" paint-order="stroke fill markers"/><ellipse ry=".331" rx=".853" cy="280.936" cx="10.205" opacity=".5" paint-order="stroke fill markers"/><ellipse cx="16.159" cy="280.936" rx=".853" ry=".331" opacity=".5" paint-order="stroke fill markers"/></g><ellipse ry=".614" rx="8.082" cy="296.386" cx="13.229" opacity=".1" fill="#f1eedb" paint-order="stroke fill markers"/></g></symbol>
</svg>
<!-- 在一個容器中包括一個標(biāo)題、段落和鎖眼的svg -->
<div class="container">
<h1>403</h1>
<p>access not granted</p>
<svg class="keyhole">
<use href="#keyhole"/>
</svg>
</div>
<!-- 在容器外部,使它們相對于主體絕對定位,包括一個用于鑰匙的svg和一個用于鬼影的svg -->
<svg class="key">
<use href="#key"/>
</svg>
<!--
將svg嵌套在div中,為svg和div提供相同的類div和svg在通過transform屬性轉(zhuǎn)換元素時表現(xiàn)不同,
從而在文本(包含在div上的偽元素中)和svg之間提供了很好的距離
-->
<div class="ghost">
<svg class="ghost">
<use href="#ghost"/>
</svg>
</div>
</body>
<script>
// 以項目中使用的DOM中的元素為目標(biāo)
/**
* 鑰匙和鑰匙孔的svg
* 標(biāo)題和段落
*/
const key = document.querySelector(".key");
const keyhole = document.querySelector(".keyhole");
const ghost = document.querySelector(".ghost");
const heading = document.querySelector("h1");
const paragraph = document.querySelector("p");
// 對于timout的長度,請考慮--animation-duration自定義屬性,并在根元素上添加一個小延遲檢索屬性
const root = document.querySelector(":root");
const rootStyles = getComputedStyle(root);
// 檢索動畫持續(xù)時間自定義屬性
// 這被指定為“40s”,以秒為單位,因此解析數(shù)字并以毫秒為單位將其包括在內(nèi)
const animationDuration = parseInt(rootStyles.getPropertyValue("--animation-duration"))*1000;
let keyTimer = animationDuration*9/8;
// 檢索鑰匙的尺寸(使鑰匙正好位于光標(biāo)所在的位置)
const keyBox = key.getBoundingClientRect();
// console.log(keyBox);
// 鑰匙和鑰匙孔動畫
// 在指定的時間范圍內(nèi)包括超時
const timeoutID = setTimeout(() => {
// 在指定的時間后,將光標(biāo)更改為似乎抓住了鑰匙
key.parentElement.parentElement.style.cursor = "grab";
// 通過觸發(fā)默認(rèn)情況下暫停的動畫,引入鑰匙和鑰匙孔svg元素
key.style.animationPlayState = "running";
keyhole.style.animationPlayState = "running";
// 將鑰匙上的指針事件設(shè)置為none,以允許在鑰匙孔上發(fā)生鼠標(biāo)懸停事件
// 鑰匙實際上是代替普通光標(biāo)使用的,并且會重疊在所有內(nèi)容的頂部
key.style.pointerEvents = "none";
// 當(dāng)光標(biāo)懸停在窗口中的任何位置時,調(diào)用一個函數(shù)來更新鑰匙的位置并使其與光標(biāo)匹配
window.addEventListener("mousemove", updateKeyPosition);
// 當(dāng)光標(biāo)懸停在鑰匙孔上時,調(diào)用一個函數(shù)來授予訪問權(quán)限并刪除當(dāng)前偵聽器
keyhole.addEventListener("mouseover", grantAccess);
clearTimeout(timeoutID);
}, keyTimer);
// 定義根據(jù)鼠標(biāo)坐標(biāo)(以及鑰匙自身的尺寸)更新絕對定位鑰匙的位置的功能
const updateKeyPosition = (e) => {
let x = e.clientX;
let y = e.clientY;
key.style.left = x - keyBox.width/1.5;
key.style.top = y - keyBox.height/2;
};
// 定義通知用戶授予訪問權(quán)限的功能
const grantAccess = () => {
// 恢復(fù)光標(biāo)
key.parentElement.parentElement.style.cursor = "default";
// 更改標(biāo)題和段落元素的文本
heading.textContent = '?? yay ??';
paragraph.textContent = 'access granted';
// 從文檔流中刪除鑰匙和鑰匙孔的svg元素
keyhole.style.display = "none";
key.style.display = "none";
// 刪除事件偵聽器,尤其是窗口上的偵聽器
window.removeEventListener("mousemove", updateKeyPosition);
keyhole.removeEventListener("mouseover", grantAccess);
};
</script>
</html>
PS:發(fā)現(xiàn)我用文字寫太生硬了,干的噎嗓子,干脆在代碼里加注釋了。文章來源地址http://www.zghlxwxcb.cn/news/detail-459806.html
到了這里,關(guān)于分享一個403界面給大家的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!