Skip to content

Commit eacc320

Browse files
committed
feat(语言切换): 为语言切换功能添加动画效果和视觉反馈
- 添加点击波纹动画效果增强交互体验 - 实现语言切换时的页面过渡动画 - 增加切换成功后的提示弹窗 - 为语言按钮添加国旗图标 - 优化下拉菜单的显示动画 - 添加内容淡入动画提升用户体验
1 parent 49333d4 commit eacc320

File tree

1 file changed

+194
-33
lines changed

1 file changed

+194
-33
lines changed

index.html

Lines changed: 194 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,18 +1308,44 @@
13081308
font-size: 0.9rem;
13091309
font-weight: 500;
13101310
backdrop-filter: blur(10px);
1311+
position: relative;
1312+
overflow: hidden;
1313+
}
1314+
1315+
/* 添加点击波纹效果 */
1316+
.language-trigger::before {
1317+
content: "";
1318+
position: absolute;
1319+
top: 50%;
1320+
left: 50%;
1321+
width: 0;
1322+
height: 0;
1323+
background: rgba(59, 130, 246, 0.3);
1324+
border-radius: 50%;
1325+
transform: translate(-50%, -50%);
1326+
transition: width 0.6s, height 0.6s;
1327+
z-index: 0;
1328+
}
1329+
1330+
.language-trigger.clicked::before {
1331+
width: 200px;
1332+
height: 200px;
13111333
}
13121334

13131335
.language-trigger:hover {
13141336
background: rgba(255, 255, 255, 0.1);
13151337
border-color: rgba(59, 130, 246, 0.3);
13161338
color: var(--text-primary);
1339+
transform: translateY(-1px);
1340+
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.2);
13171341
}
13181342

13191343
.language-trigger::after {
13201344
content: "▼";
13211345
font-size: 0.8rem;
13221346
transition: transform 0.3s ease;
1347+
z-index: 1;
1348+
position: relative;
13231349
}
13241350

13251351
.language-switcher.show .language-trigger::after {
@@ -1340,15 +1366,15 @@
13401366
backdrop-filter: blur(20px);
13411367
opacity: 0;
13421368
visibility: hidden;
1343-
transform: translateY(-10px);
1369+
transform: translateY(-10px) scale(0.95);
13441370
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
13451371
z-index: 1000;
13461372
}
13471373

13481374
.language-switcher.show .language-dropdown {
13491375
opacity: 1;
13501376
visibility: visible;
1351-
transform: translateY(0);
1377+
transform: translateY(0) scale(1);
13521378
}
13531379

13541380
.lang-btn {
@@ -1366,26 +1392,65 @@
13661392
font-size: 0.9rem;
13671393
font-weight: 500;
13681394
text-align: left;
1395+
position: relative;
1396+
overflow: hidden;
1397+
}
1398+
1399+
/* 语言按钮图标 */
1400+
.lang-btn::before {
1401+
content: "";
1402+
width: 20px;
1403+
height: 15px;
1404+
background-size: cover;
1405+
background-position: center;
1406+
border-radius: 2px;
1407+
flex-shrink: 0;
1408+
}
1409+
1410+
.lang-btn[data-lang="zh"]::before {
1411+
content: "🇨🇳";
1412+
font-size: 16px;
1413+
width: auto;
1414+
height: auto;
1415+
}
1416+
1417+
.lang-btn[data-lang="en"]::before {
1418+
content: "🇺🇸";
1419+
font-size: 16px;
1420+
width: auto;
1421+
height: auto;
1422+
}
1423+
1424+
.lang-btn[data-lang="ja"]::before {
1425+
content: "🇯🇵";
1426+
font-size: 16px;
1427+
width: auto;
1428+
height: auto;
13691429
}
13701430

13711431
.lang-btn:hover {
13721432
background: rgba(255, 255, 255, 0.1);
13731433
color: var(--text-primary);
1434+
transform: translateX(4px);
13741435
}
13751436

13761437
.lang-btn.active {
13771438
background: rgba(59, 130, 246, 0.2);
13781439
color: #60a5fa;
13791440
font-weight: 600;
1441+
transform: translateX(4px);
13801442
}
13811443

1382-
/* 隐藏非当前语言的内容 */
1444+
/* 内容切换动画 */
13831445
.lang-content {
13841446
display: none;
1447+
opacity: 0;
1448+
transition: opacity 0.3s ease-in-out;
13851449
}
13861450

13871451
.lang-content.active {
13881452
display: block;
1453+
animation: fadeInContent 0.5s ease-out forwards;
13891454
}
13901455

13911456
.lang-content.active.inline {
@@ -1399,6 +1464,49 @@
13991464
.lang-content.active.grid {
14001465
display: grid;
14011466
}
1467+
1468+
@keyframes fadeInContent {
1469+
from {
1470+
opacity: 0;
1471+
transform: translateY(10px);
1472+
}
1473+
to {
1474+
opacity: 1;
1475+
transform: translateY(0);
1476+
}
1477+
}
1478+
1479+
/* 语言切换成功提示 */
1480+
.language-toast {
1481+
position: fixed;
1482+
top: 100px;
1483+
right: 20px;
1484+
background: rgba(59, 130, 246, 0.9);
1485+
color: white;
1486+
padding: 12px 20px;
1487+
border-radius: 8px;
1488+
font-size: 0.9rem;
1489+
font-weight: 500;
1490+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
1491+
backdrop-filter: blur(10px);
1492+
transform: translateX(100%);
1493+
transition: transform 0.3s ease;
1494+
z-index: 10000;
1495+
}
1496+
1497+
.language-toast.show {
1498+
transform: translateX(0);
1499+
}
1500+
1501+
/* 页面切换时的整体动画 */
1502+
.page-transition {
1503+
transition: all 0.3s ease;
1504+
}
1505+
1506+
.page-transition.switching {
1507+
opacity: 0.7;
1508+
transform: scale(0.98);
1509+
}
14021510
</style>
14031511
</head>
14041512

@@ -2301,10 +2409,17 @@ <h3 class="contact-subtitle">
23012409
<script>
23022410
// 语言切换功能
23032411
let currentLang = "zh";
2412+
let isTransitioning = false;
23042413

23052414
// 切换语言切换器显示/隐藏
23062415
function toggleLanguageSwitcher() {
23072416
const switcher = document.getElementById("languageSwitcher");
2417+
const trigger = switcher.querySelector(".language-trigger");
2418+
2419+
// 添加点击效果
2420+
trigger.classList.add("clicked");
2421+
setTimeout(() => trigger.classList.remove("clicked"), 600);
2422+
23082423
switcher.classList.toggle("show");
23092424
}
23102425

@@ -2313,58 +2428,104 @@ <h3 class="contact-subtitle">
23132428
document.getElementById("languageSwitcher").classList.remove("show");
23142429
}
23152430

2431+
// 显示切换成功提示
2432+
function showLanguageToast(langName) {
2433+
// 移除已存在的提示
2434+
const existingToast = document.querySelector(".language-toast");
2435+
if (existingToast) {
2436+
existingToast.remove();
2437+
}
2438+
2439+
// 创建新提示
2440+
const toast = document.createElement("div");
2441+
toast.className = "language-toast";
2442+
toast.textContent = `已切换到 ${langName}`;
2443+
document.body.appendChild(toast);
2444+
2445+
// 显示动画
2446+
setTimeout(() => toast.classList.add("show"), 100);
2447+
2448+
// 3秒后自动隐藏
2449+
setTimeout(() => {
2450+
toast.classList.remove("show");
2451+
setTimeout(() => toast.remove(), 300);
2452+
}, 3000);
2453+
}
2454+
23162455
// 修改现有的switchLanguage函数
23172456
function switchLanguage(lang) {
2457+
if (isTransitioning || currentLang === lang) return;
2458+
2459+
isTransitioning = true;
23182460
currentLang = lang;
23192461

2462+
// 添加页面切换动画
2463+
document.body.classList.add("page-transition", "switching");
2464+
23202465
// 更新触发按钮文本
23212466
const triggerBtn = document.querySelector(".language-trigger");
23222467
const langNames = {
23232468
zh: "中文",
23242469
en: "English",
23252470
ja: "日本語",
23262471
};
2327-
triggerBtn.textContent = langNames[lang];
23282472

2329-
// 更新下拉选项的激活状态
2330-
document.querySelectorAll(".lang-btn").forEach((btn) => {
2331-
btn.classList.remove("active");
2332-
if (btn.dataset.lang === lang) {
2333-
btn.classList.add("active");
2334-
}
2335-
});
2473+
setTimeout(() => {
2474+
triggerBtn.textContent = langNames[lang];
2475+
2476+
// 更新下拉选项的激活状态
2477+
document.querySelectorAll(".lang-btn").forEach((btn) => {
2478+
btn.classList.remove("active");
2479+
if (btn.dataset.lang === lang) {
2480+
btn.classList.add("active");
2481+
}
2482+
});
23362483

2337-
// 隐藏下拉菜单
2338-
hideLanguageSwitcher();
2484+
// 隐藏下拉菜单
2485+
hideLanguageSwitcher();
23392486

2340-
// 更新HTML lang属性
2341-
document.documentElement.lang =
2342-
lang === "zh" ? "zh-CN" : lang === "en" ? "en-US" : "ja-JP";
2487+
// 更新HTML lang属性
2488+
document.documentElement.lang =
2489+
lang === "zh" ? "zh-CN" : lang === "en" ? "en-US" : "ja-JP";
23432490

2344-
// 更新页面标题
2345-
const titles = {
2346-
zh: "RushDB - 无限进步",
2347-
en: "RushDB - Unlimited Progress",
2348-
ja: "RushDB - 無限の進歩",
2349-
};
2350-
document.title = titles[lang];
2491+
// 更新页面标题
2492+
const titles = {
2493+
zh: "RushDB - 无限进步",
2494+
en: "RushDB - Unlimited Progress",
2495+
ja: "RushDB - 無限の進歩",
2496+
};
2497+
document.title = titles[lang];
23512498

2352-
// 隐藏所有语言内容
2353-
document.querySelectorAll(".lang-content").forEach((el) => {
2354-
el.classList.remove("active");
2355-
});
2499+
// 隐藏所有语言内容
2500+
document.querySelectorAll(".lang-content").forEach((el) => {
2501+
el.classList.remove("active");
2502+
});
23562503

2357-
// 显示当前语言内容
2358-
document.querySelectorAll(`.lang-${lang}`).forEach((el) => {
2359-
el.classList.add("active");
2360-
});
2504+
// 显示当前语言内容
2505+
document.querySelectorAll(`.lang-${lang}`).forEach((el) => {
2506+
el.classList.add("active");
2507+
});
2508+
2509+
// 保存语言选择到localStorage
2510+
localStorage.setItem("rushdb-language", lang);
23612511

2362-
// 保存语言选择到localStorage
2363-
localStorage.setItem("rushdb-language", lang);
2512+
// 显示切换成功提示
2513+
showLanguageToast(langNames[lang]);
2514+
2515+
// 移除切换动画
2516+
document.body.classList.remove("switching");
2517+
setTimeout(() => {
2518+
document.body.classList.remove("page-transition");
2519+
isTransitioning = false;
2520+
}, 300);
2521+
}, 150);
23642522
}
23652523

23662524
// 初始化语言
23672525
document.addEventListener("DOMContentLoaded", function () {
2526+
// 添加页面切换类
2527+
document.body.classList.add("page-transition");
2528+
23682529
const savedLang = localStorage.getItem("rushdb-language") || "zh";
23692530
switchLanguage(savedLang);
23702531

0 commit comments

Comments
 (0)