Skip to content

Commit 86d838a

Browse files
calderbuildclaude
andcommitted
添加更多交互动画效果
- 平滑滚动和高亮效果 - 标签悬停动画 - 图片加载淡入效果 - 打字机效果 - 数字计数动画 - 回到顶部按钮 - 文章阅读进度条 - 深色模式支持 - 视差滚动效果 - 脉冲和加载动画 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent e7c9b7b commit 86d838a

File tree

2 files changed

+370
-0
lines changed

2 files changed

+370
-0
lines changed

css/jason-blog.css

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,3 +2126,217 @@ img::-moz-selection {
21262126
font-size: 13px;
21272127
}
21282128
}
2129+
2130+
/* 交互动画样式 */
2131+
2132+
/* 平滑滚动高亮效果 */
2133+
.highlighted {
2134+
animation: highlightPulse 2s ease;
2135+
}
2136+
2137+
@keyframes highlightPulse {
2138+
0% {
2139+
background-color: rgba(91, 33, 182, 0.2);
2140+
}
2141+
100% {
2142+
background-color: transparent;
2143+
}
2144+
}
2145+
2146+
/* 标签动画 */
2147+
.tag-animate {
2148+
animation: tagBounce 0.5s ease;
2149+
}
2150+
2151+
@keyframes tagBounce {
2152+
0%, 100% {
2153+
transform: scale(1);
2154+
}
2155+
50% {
2156+
transform: scale(1.1);
2157+
}
2158+
}
2159+
2160+
/* 图片加载动画 */
2161+
.post-container img {
2162+
opacity: 0;
2163+
transition: opacity 0.5s ease;
2164+
}
2165+
2166+
.post-container img.img-loaded {
2167+
opacity: 1;
2168+
}
2169+
2170+
/* 淡入动画 */
2171+
.fade-in {
2172+
opacity: 0;
2173+
transform: translateY(20px);
2174+
transition: all 0.6s ease;
2175+
}
2176+
2177+
.fade-in.visible {
2178+
opacity: 1;
2179+
transform: translateY(0);
2180+
}
2181+
2182+
/* 回到顶部按钮 */
2183+
.back-to-top {
2184+
position: fixed;
2185+
bottom: 30px;
2186+
right: 30px;
2187+
width: 50px;
2188+
height: 50px;
2189+
background: linear-gradient(135deg, #5b21b6 0%, #7c3aed 100%);
2190+
color: white;
2191+
border-radius: 50%;
2192+
display: flex;
2193+
align-items: center;
2194+
justify-content: center;
2195+
text-decoration: none;
2196+
opacity: 0;
2197+
visibility: hidden;
2198+
transition: all 0.3s ease;
2199+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
2200+
z-index: 1000;
2201+
}
2202+
2203+
.back-to-top.show {
2204+
opacity: 1;
2205+
visibility: visible;
2206+
}
2207+
2208+
.back-to-top:hover {
2209+
transform: translateY(-3px);
2210+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
2211+
background: linear-gradient(135deg, #7c3aed 0%, #5b21b6 100%);
2212+
}
2213+
2214+
/* 阅读进度条 */
2215+
.reading-progress {
2216+
position: fixed;
2217+
top: 0;
2218+
left: 0;
2219+
height: 3px;
2220+
background: linear-gradient(90deg, #5b21b6 0%, #7c3aed 100%);
2221+
transition: width 0.3s ease;
2222+
z-index: 9999;
2223+
}
2224+
2225+
/* 深色模式样式 */
2226+
body.dark-mode {
2227+
background-color: #1a1a1a;
2228+
color: #e0e0e0;
2229+
}
2230+
2231+
body.dark-mode .post-container {
2232+
background-color: #2a2a2a;
2233+
color: #e0e0e0;
2234+
}
2235+
2236+
body.dark-mode code {
2237+
background: rgba(124, 58, 237, 0.2);
2238+
color: #a78bfa;
2239+
}
2240+
2241+
body.dark-mode pre {
2242+
background: #333;
2243+
border-color: #444;
2244+
}
2245+
2246+
body.dark-mode pre code {
2247+
color: #e0e0e0;
2248+
}
2249+
2250+
body.dark-mode blockquote {
2251+
background: rgba(124, 58, 237, 0.1);
2252+
color: #b0b0b0;
2253+
}
2254+
2255+
body.dark-mode table {
2256+
background: #2a2a2a;
2257+
}
2258+
2259+
body.dark-mode table.table > tbody tr {
2260+
background: #2a2a2a;
2261+
}
2262+
2263+
body.dark-mode table.table > tbody tr:nth-child(even) {
2264+
background: #333;
2265+
}
2266+
2267+
body.dark-mode .sidebar-container {
2268+
background: #2a2a2a;
2269+
color: #e0e0e0;
2270+
}
2271+
2272+
body.dark-mode .intro-header {
2273+
background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%);
2274+
}
2275+
2276+
/* 视差效果容器 */
2277+
.parallax-element {
2278+
position: relative;
2279+
overflow: hidden;
2280+
}
2281+
2282+
.parallax-layer {
2283+
position: absolute;
2284+
top: 0;
2285+
left: 0;
2286+
width: 100%;
2287+
height: 100%;
2288+
transition: transform 0.1s ease-out;
2289+
}
2290+
2291+
/* 数字计数器样式 */
2292+
.counter {
2293+
display: inline-block;
2294+
font-weight: bold;
2295+
color: #5b21b6;
2296+
}
2297+
2298+
/* 悬浮卡片效果 */
2299+
.hover-card {
2300+
transition: all 0.3s ease;
2301+
}
2302+
2303+
.hover-card:hover {
2304+
transform: translateY(-5px);
2305+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
2306+
}
2307+
2308+
/* 脉冲动画 */
2309+
@keyframes pulse {
2310+
0% {
2311+
transform: scale(1);
2312+
opacity: 1;
2313+
}
2314+
50% {
2315+
transform: scale(1.05);
2316+
opacity: 0.8;
2317+
}
2318+
100% {
2319+
transform: scale(1);
2320+
opacity: 1;
2321+
}
2322+
}
2323+
2324+
.pulse {
2325+
animation: pulse 2s infinite;
2326+
}
2327+
2328+
/* 加载动画 */
2329+
.loader {
2330+
border: 3px solid #f3f3f3;
2331+
border-top: 3px solid #5b21b6;
2332+
border-radius: 50%;
2333+
width: 40px;
2334+
height: 40px;
2335+
animation: spin 1s linear infinite;
2336+
margin: 20px auto;
2337+
}
2338+
2339+
@keyframes spin {
2340+
0% { transform: rotate(0deg); }
2341+
100% { transform: rotate(360deg); }
2342+
}

js/jason-blog.js

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,162 @@ jQuery(document).ready(function($) {
9090
$(this).toggleClass('active');
9191
$catalogBody.slideToggle(300);
9292
});
93+
94+
// 平滑滚动
95+
$('a[href*="#"]:not([href="#"])').on('click', function(e) {
96+
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
97+
|| location.hostname == this.hostname) {
98+
99+
var target = $(this.hash);
100+
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
101+
102+
if (target.length) {
103+
e.preventDefault();
104+
$('html,body').animate({
105+
scrollTop: target.offset().top - 70
106+
}, 800, 'swing');
107+
108+
// 高亮目标元素
109+
target.addClass('highlighted');
110+
setTimeout(function() {
111+
target.removeClass('highlighted');
112+
}, 2000);
113+
}
114+
}
115+
});
116+
117+
// 标签动画效果
118+
$('.tags a, #tag_cloud a').on('mouseenter', function() {
119+
$(this).addClass('tag-animate');
120+
}).on('mouseleave', function() {
121+
$(this).removeClass('tag-animate');
122+
});
123+
124+
// 图片懒加载动画
125+
$('.post-container img').on('load', function() {
126+
$(this).addClass('img-loaded');
127+
});
128+
129+
// 打字机效果
130+
function typeWriter(element, text, speed = 50) {
131+
var i = 0;
132+
element.text('');
133+
134+
function type() {
135+
if (i < text.length) {
136+
element.append(text.charAt(i));
137+
i++;
138+
setTimeout(type, speed);
139+
}
140+
}
141+
142+
type();
143+
}
144+
145+
// 应用打字机效果到特定元素
146+
$('.typewriter').each(function() {
147+
var text = $(this).text();
148+
typeWriter($(this), text, 30);
149+
});
150+
151+
// 数字计数动画
152+
function animateValue(element, start, end, duration) {
153+
var startTimestamp = null;
154+
155+
var step = function(timestamp) {
156+
if (!startTimestamp) startTimestamp = timestamp;
157+
var progress = Math.min((timestamp - startTimestamp) / duration, 1);
158+
element.text(Math.floor(progress * (end - start) + start));
159+
160+
if (progress < 1) {
161+
window.requestAnimationFrame(step);
162+
}
163+
};
164+
165+
window.requestAnimationFrame(step);
166+
}
167+
168+
// 滚动时触发计数动画
169+
$('.counter').each(function() {
170+
var $this = $(this);
171+
var end = parseInt($this.text());
172+
173+
$this.waypoint(function() {
174+
animateValue($this, 0, end, 2000);
175+
this.destroy();
176+
}, {
177+
offset: '80%'
178+
});
179+
});
180+
181+
// 页面加载动画
182+
$(window).on('load', function() {
183+
$('.fade-in').each(function(index) {
184+
var $this = $(this);
185+
setTimeout(function() {
186+
$this.addClass('visible');
187+
}, index * 100);
188+
});
189+
});
190+
191+
// 鼠标移动视差效果
192+
$('.parallax-element').on('mousemove', function(e) {
193+
var $this = $(this);
194+
var x = e.clientX / window.innerWidth;
195+
var y = e.clientY / window.innerHeight;
196+
197+
$this.find('.parallax-layer').each(function() {
198+
var speed = $(this).data('speed') || 10;
199+
var xPos = -(x * speed);
200+
var yPos = -(y * speed);
201+
202+
$(this).css({
203+
'transform': 'translate(' + xPos + 'px, ' + yPos + 'px)'
204+
});
205+
});
206+
});
207+
208+
// 回到顶部按钮
209+
var $backToTop = $('<a href="#" class="back-to-top"><i class="fa fa-arrow-up"></i></a>').appendTo('body');
210+
211+
$(window).on('scroll', function() {
212+
if ($(this).scrollTop() > 300) {
213+
$backToTop.addClass('show');
214+
} else {
215+
$backToTop.removeClass('show');
216+
}
217+
});
218+
219+
$backToTop.on('click', function(e) {
220+
e.preventDefault();
221+
$('html, body').animate({
222+
scrollTop: 0
223+
}, 800, 'swing');
224+
});
225+
226+
// 文章阅读进度条
227+
var $progressBar = $('<div class="reading-progress"></div>').appendTo('body');
228+
229+
$(window).on('scroll', function() {
230+
var winHeight = $(window).height();
231+
var docHeight = $(document).height();
232+
var scrollTop = $(window).scrollTop();
233+
var trackLength = docHeight - winHeight;
234+
var percent = Math.floor((scrollTop / trackLength) * 100);
235+
236+
$progressBar.css('width', percent + '%');
237+
});
238+
239+
// 深色模式切换(如果需要)
240+
$('.dark-mode-toggle').on('click', function() {
241+
$('body').toggleClass('dark-mode');
242+
localStorage.setItem('darkMode', $('body').hasClass('dark-mode'));
243+
});
244+
245+
// 检查本地存储的深色模式设置
246+
if (localStorage.getItem('darkMode') === 'true') {
247+
$('body').addClass('dark-mode');
248+
}
93249

94250
// 搜索功能增强
95251
$('.search-toggle').on('click', function() {

0 commit comments

Comments
 (0)