-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
218 lines (196 loc) · 8.71 KB
/
script.js
File metadata and controls
218 lines (196 loc) · 8.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// 模式切換
const modeToggle = document.getElementById('modeToggle');
// 檢查顏色模式
function checkMode() {
if (modeToggle.checked) {
document.body.classList.remove('dark-mode');
document.body.classList.add('light-mode');
} else {
document.body.classList.remove('light-mode');
document.body.classList.add('dark-mode');
}
}
// 監聽切換事件
modeToggle.addEventListener('change', checkMode);
// 頁面加載時檢查顏色模式
checkMode();
// 打字機效果
document.addEventListener("DOMContentLoaded", () => {
const heroText = document.getElementById("heroText");
const ctaGroup = document.getElementById("cta-group");
const seeMoreBtn = document.getElementById("cta-button");
const aboutBtn = document.getElementById("about-button");
const line1 = "Turning Complex Challenges into Simple";
const line2 = "Elegant Experiences";
let charIndex = 0;
// 放入透明佔位,讓光標在左側
if (heroText) {
heroText.innerHTML = `<span class="cursor"></span><span class="ghost">${line1}</span>`;
}
// 等待 2 秒 (CSS動畫處理閃爍)
setTimeout(() => {
if (heroText) typeLine1();
}, 2000);
function typeLine1() {
if (charIndex <= line1.length) {
const typed = line1.substring(0, charIndex);
const ghost = line1.substring(charIndex);
heroText.innerHTML = `<span>${typed}</span><span class="cursor"></span><span class="ghost">${ghost}</span>`;
charIndex++;
setTimeout(typeLine1, 60);
} else {
charIndex = 0;
// 換行時,先準備好第二行的透明佔位
heroText.innerHTML = `<span>${line1}</span><br><span class="cursor"></span><span class="ghost">${line2}</span>`;
setTimeout(typeLine2, 200);
}
}
function typeLine2() {
if (charIndex <= line2.length) {
const typed = line2.substring(0, charIndex);
const ghost = line2.substring(charIndex);
heroText.innerHTML = `<span>${line1}</span><br><span>${typed}</span><span class="cursor"></span><span class="ghost">${ghost}</span>`;
charIndex++;
setTimeout(typeLine2, 60);
} else {
finishTyping();
}
}
function finishTyping() {
// 打完後移除游標與 ghost 標籤,恢復文字展示
heroText.innerHTML = `<span>${line1}</span><br><span>${line2}</span>`;
setTimeout(() => {
if (ctaGroup) ctaGroup.classList.add("show");
}, 500);
}
// Overview 按鈕跳轉
if (aboutBtn) {
aboutBtn.addEventListener("click", () => {
window.location.href = "https://liwei-ji.github.io/about.html";
});
}
// Learn More 平滑捲動
if (seeMoreBtn) {
seeMoreBtn.addEventListener("click", () => {
const nextSection = document.querySelector(".projects-section");
if (nextSection) {
nextSection.scrollIntoView({ behavior: "smooth" });
}
});
}
});
// 卡片數據
const cardData = [
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/fs/de20e0220712515.6999e02704179.png",
title: "Input UX",
subtitle: "Guides users on how to interact with the AI model.",
isLarge: true,
tags: ["AI Agent", "UIUX", "Interactive behavior", "Input"],
url: "https://liwei-ji.github.io/ai-agent-input",
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/e069e4220712515.69b2ca7aeb9a0.png",
title: "DISE AI",
subtitle: "Simplifying DISE video evaluation with real-time AI insights.",
tags: ["AI Agent", "UIUX"],
url: "https://liwei-ji.github.io/projects/dise-ai",
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/45ddd2220712515.695bcbd04ca9a.png",
title: "DISE AI Agent",
subtitle: "DISE AI is a medical AI agent combining U-Net based image recognition, LLMs and retrieval augmented generation RAG.",
tags: ["AI Agent", "Model Training", "LLM", "RAG", ],
url: "https://liwei-ji.github.io/DISE-AI",
banner: "Contact me to use"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/464ea3220712515.67c82815e2868.png",
title: "Review of OSIM Work",
subtitle: "Creating a connected OSIM health ecosystem through cross product integration and intelligent control, delivering a seamless and personalized full body massage experience.",
tags: ["English", "UI/UX", "Website", "APP", "Research"],
url: "https://liwei-ji.github.io/projects/review-of-osim-work"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/293901220712515.67c8224364822.png",
title: "OSIM Well Being App",
subtitle: "Reflecting on Challenges, Achievements, and Lessons Learned Along the Way.",
tags: ["English", "APP", "Research"],
url: "https://liwei-ji.github.io/projects/osim-well-being-app"
},
{
imgSrc: "https://sg.osim.com/partners-program/img/servicedonewell-min.jpg",
title: "How I Helped the CS Team Increase Efficiency",
subtitle: "From workflow design to prototype validation, crafting tools that accelerate issue resolution and deliver actionable user insights.",
tags: ["English", "Website", "Research"],
url: "https://liwei-ji.github.io/projects/osim-onecrm"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/e51e2b220712515.67c81f448fc61.png",
title: "Designing the mmWave Testing Tool GUI",
subtitle: "Users can perform beam control experiments and verify test results through the intuitive TMXLAB Kit graphical interface.",
tags: ["English", "Website", "Research"],
url: "https://liwei-ji.github.io/projects/mmwave"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/e4659a220712515.67c82775b7f34.png",
title: "OPTEX Vision App",
subtitle: "Focused on minimalist design and brand consistency, enhancing operational efficiency and meeting user needs in Japanese and European markets.",
tags: ["English", "APP", "Research"],
url: "https://liwei-ji.github.io/projects/optex-app"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/6f5fbe220712515.69b2cc7c19b28.png",
title: "Toyota New RAV4 In Car System",
subtitle: "Comprehensively optimized in car system interfaces leveraging intuitive design, dynamic information, and feature integration to enhance driving convenience and safety.",
tags: ["Japanese", "Toyota", "NewRav4", "Research"],
url: "https://liwei-ji.github.io/projects/toyota-rav4"
},
{
imgSrc: "https://mir-s3-cdn-cf.behance.net/project_modules/max_1200/b6296d220712515.67c8012021a2c.png",
title: "Toyota New RAV4 In Car App",
subtitle: "Smart app integrating real time vehicle data and interactive workflows, focused on driver experience and user behavior driven design.",
tags: ["Japanese", "Toyota", "NewRav4", "Research", "APP"],
url: "https://liwei-ji.github.io/projects/toyota-app"
}
];
// 創建卡片
function createCard(card) {
const cardElement = document.createElement('div');
cardElement.classList.add('card');
// Add Large card
if (card.isLarge) {
cardElement.classList.add('card-large');
}
cardElement.innerHTML = `
<div class="image-wrapper">
<img src="${card.imgSrc}" alt="${card.title}" class="card-image">
${card.banner ? `<div class="card-banner">${card.banner}</div>` : ""}
</div>
<div class="card-content">
<h2 class="card-title">${card.title}</h2>
${card.subtitle ? `<p class="card-subtitle">${card.subtitle}</p>` : ""}
${card.tags.map(tag => `<span class="card-tag">${tag}</span>`).join('')}
</div>
`;
cardElement.addEventListener('click', () => {
// 點擊卡片時開啟指定的 URL
window.open(card.url, "_self"); // 當前標籤頁中打開
});
return cardElement;
}
// 初始化卡片容器
const cardContainer = document.getElementById('card-container');
cardData.forEach(card => {
cardContainer.appendChild(createCard(card));
});
cardContainer.appendChild(createDashedCard());
// 平滑滾動
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});