jQuery 動畫效果 (Effects)
jQuery 提供了豐富的動畫效果方法,讓你能夠輕鬆地為網頁元素添加視覺動畫效果,包括顯示/隱藏、淡入淡出、滑動效果,以及自訂動畫。
顯示與隱藏
show() 和 hide()
// 立即顯示/隱藏
$('#box').show();
$('#box').hide();
// 帶有動畫效果
$('#box').show('slow'); // 慢速
$('#box').hide('fast'); // 快速
$('#box').show(400); // 400 毫秒
// 帶回呼函式
$('#box').show(400, function () {
console.log('顯示動畫完成');
});
// 指定 easing
$('#box').show(400, 'swing', function () {
console.log('完成');
});
toggle()
切換顯示/隱藏狀態:
// 切換顯示狀態
$('#box').toggle();
// 帶動畫
$('#box').toggle(400);
// 根據條件顯示/隱藏
$('#box').toggle(shouldShow); // shouldShow 為 true 則顯示
速度參數
| 參數 | 說明 |
|---|---|
'slow' | 600 毫秒 |
'fast' | 200 毫秒 |
| 數字 | 毫秒數 |
淡入淡出
fadeIn() 和 fadeOut()
// 淡入
$('#box').fadeIn();
$('#box').fadeIn('slow');
$('#box').fadeIn(400);
// 淡出
$('#box').fadeOut();
$('#box').fadeOut(400, function () {
$(this).remove(); // 淡出後移除
});
fadeToggle()
切換淡入/淡出:
$('#box').fadeToggle();
$('#box').fadeToggle(400);
fadeTo()
淡入/淡出到指定的透明度:
// 淡到 50% 透明度
$('#box').fadeTo(400, 0.5);
// 淡到完全透明
$('#box').fadeTo(400, 0);
// 淡到完全不透明
$('#box').fadeTo(400, 1);
// 帶回呼函式
$('#box').fadeTo(400, 0.5, function () {
console.log('完成');
});
fadeOut() 在動畫完成後會設定 display: none,而 fadeTo(duration, 0) 只會將透明度設為 0,元素仍佔據空間。滑動效果
slideDown() 和 slideUp()
// 向下滑動顯示
$('#box').slideDown();
$('#box').slideDown(400);
// 向上滑動隱藏
$('#box').slideUp();
$('#box').slideUp(400, function () {
console.log('滑動完成');
});
slideToggle()
切換滑動顯示/隱藏:
$('#box').slideToggle();
$('#box').slideToggle(400);
手風琴選單範例
$('.accordion-header').on('click', function () {
// 關閉其他面板
$(this).siblings('.accordion-header').next('.accordion-content').slideUp(300);
// 切換當前面板
$(this).next('.accordion-content').slideToggle(300);
});
自訂動畫
animate()
animate() 讓你可以建立自訂的動畫效果:
// 基本語法
$(selector).animate(properties, duration, easing, callback);
// 移動元素
$('#box').animate(
{
left: '250px',
top: '100px',
},
400
);
// 改變尺寸
$('#box').animate(
{
width: '300px',
height: '200px',
},
400
);
// 改變透明度
$('#box').animate(
{
opacity: 0.5,
},
400
);
// 多個屬性同時動畫
$('#box').animate(
{
left: '250px',
opacity: 0.5,
width: '150px',
height: '150px',
},
400
);
相對值
使用 += 或 -= 進行相對動畫:
$('#box').animate(
{
left: '+=50px', // 向右移動 50px
top: '-=30px', // 向上移動 30px
width: '+=100px', // 寬度增加 100px
},
400
);
預設值
使用 'show'、'hide'、'toggle' 作為屬性值:
$('#box').animate(
{
width: 'toggle', // 切換寬度
opacity: 'toggle', // 切換透明度
},
400
);
Easing 函式
jQuery 內建兩種 easing 函式:
'swing'(預設)- 開始和結束較慢,中間較快'linear'- 等速
$('#box').animate(
{
left: '250px',
},
400,
'linear'
);
如需更多 easing 效果,可以使用 jQuery UI 或其他 easing 插件。
可動畫的 CSS 屬性
animate() 只能用於數值型的 CSS 屬性,例如:
- 位置:left、top、right、bottom
- 尺寸:width、height、padding、margin
- 透明度:opacity
- 字體:fontSize、lineHeight
- 邊框:borderWidth
不支援的屬性:
- 顏色(需要 jQuery Color 插件)
- transform(需要插件)
動畫佇列
連續的動畫會依序執行:
// 動畫會依序執行
$('#box')
.animate({ left: '100px' }, 400)
.animate({ top: '100px' }, 400)
.animate({ left: '0' }, 400)
.animate({ top: '0' }, 400);
同時執行動畫
使用物件一次傳入所有屬性:
// 同時動畫
$('#box').animate(
{
left: '100px',
top: '100px',
opacity: 0.5,
},
400
);
或使用 queue: false:
$('#box')
.animate({ left: '100px' }, { duration: 400, queue: false })
.animate({ top: '100px' }, { duration: 400, queue: false });
動畫控制
stop() - 停止動畫
// 停止當前動畫
$('#box').stop();
// 停止並清除佇列
$('#box').stop(true);
// 停止、清除佇列,並跳到動畫結束狀態
$('#box').stop(true, true);
stop() 參數說明:
| 參數 | 說明 |
|---|---|
stop() | 停止當前動畫,繼續執行佇列中的下一個 |
stop(true) | 停止當前動畫並清空佇列 |
stop(true, true) | 停止並跳到當前動畫的結束狀態 |
finish() - 立即完成
立即完成所有排隊的動畫,並跳到最終狀態:
$('#box').finish();
delay() - 延遲
在動畫佇列中插入延遲:
$('#box')
.fadeOut(400)
.delay(1000) // 等待 1 秒
.fadeIn(400);
動畫佇列操作
// 加入自訂函式到佇列
$('#box')
.animate({ left: '100px' }, 400)
.queue(function (next) {
$(this).addClass('moved');
next(); // 必須呼叫 next() 以繼續佇列
})
.animate({ top: '100px' }, 400);
// 清空佇列
$('#box').clearQueue();
// 取得佇列
var queue = $('#box').queue();
console.log('佇列長度:', queue.length);
回呼函式與 Promise
回呼函式
$('#box').fadeIn(400, function () {
// 動畫完成後執行
console.log('fadeIn 完成');
});
// 多個元素時,回呼會在每個元素完成後各執行一次
$('.items').fadeIn(400, function () {
console.log('一個元素完成'); // 每個元素都會觸發
});
Promise 風格
使用 .promise() 取得動畫的 Promise 物件:
// 等待所有元素動畫完成
$('.items')
.fadeIn(400)
.promise()
.done(function () {
console.log('所有元素都完成了');
});
// 使用 then()
$('#box')
.animate({ left: '100px' }, 400)
.promise()
.then(function () {
console.log('第一段動畫完成');
return $('#box').animate({ top: '100px' }, 400).promise();
})
.then(function () {
console.log('第二段動畫完成');
});
全域設定
$.fx.off - 關閉所有動畫
// 關閉所有動畫(動畫會立即完成)
$.fx.off = true;
// 開啟動畫
$.fx.off = false;
// 根據使用者偏好設定
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {
$.fx.off = true;
}
$.fx.interval - 動畫間隔
注意:
$.fx.interval 在 jQuery 3.0+ 已不建議使用,因為 jQuery 已改用 requestAnimationFrame。實用範例
手風琴選單
$('.accordion-toggle').on('click', function () {
var $panel = $(this).next('.accordion-panel');
// 關閉其他
$('.accordion-panel').not($panel).slideUp(300);
// 切換當前
$panel.slideToggle(300);
// 切換箭頭
$(this).toggleClass('open');
$(this).siblings('.accordion-toggle').removeClass('open');
});
平滑捲動
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
var target = $(this.hash);
if (target.length) {
$('html, body').animate(
{
scrollTop: target.offset().top - 60,
},
500
);
}
});
圖片輪播
var $slides = $('.slide');
var current = 0;
function showSlide(index) {
$slides.fadeOut(300).eq(index).fadeIn(300);
}
$('#next').on('click', function () {
current = (current + 1) % $slides.length;
showSlide(current);
});
$('#prev').on('click', function () {
current = (current - 1 + $slides.length) % $slides.length;
showSlide(current);
});
// 自動播放
setInterval(function () {
current = (current + 1) % $slides.length;
showSlide(current);
}, 5000);
通知訊息
function showNotification(message, type) {
var $notification = $('<div>', {
class: 'notification ' + type,
text: message,
});
$notification
.appendTo('body')
.hide()
.fadeIn(300)
.delay(3000)
.fadeOut(300, function () {
$(this).remove();
});
}
// 使用
showNotification('儲存成功!', 'success');
showNotification('發生錯誤', 'error');
數字動畫
function animateNumber($element, target) {
$({ value: 0 }).animate(
{ value: target },
{
duration: 1000,
step: function () {
$element.text(Math.floor(this.value));
},
complete: function () {
$element.text(target);
},
}
);
}
// 使用
animateNumber($('#counter'), 1000);
防止動畫堆疊
// 使用 stop() 防止動畫堆疊
$('.item').hover(
function () {
$(this).stop().animate({ marginLeft: '20px' }, 200);
},
function () {
$(this).stop().animate({ marginLeft: '0' }, 200);
}
);