透過 jQuery AJAX 定時輪詢 PHP 後端,配合 animate() 數字滾動動畫,打造無需重新整理頁面的線上人數即時顯示功能。適用於統計儀表板、直播間觀看數、電商搶購人氣指標等場景。
<div class="count">
當前在線:<span id="number">0</span>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
function magic_number(value) {
var num = $("#number");
$({count: parseInt(num.text())}).animate({count: value}, {
duration: 500,
step: function() {
num.text(Math.floor(this.count));
},
complete: function() {
num.text(value);
}
});
}
function update() {
$.getJSON("number.php?callback=?", function(data) {
magic_number(data.n);
});
}
setInterval(update, 5000); // 每 5 秒輪詢一次
update(); // 頁面載入立即執行一次
</script>
number.php實際專案中應從資料庫、Redis 或 Session 讀取真實線上人數,此處示範隨機數:
<?php
// number.php
header('Content-Type: application/json; charset=utf-8');
// 實際應用:從 Redis/資料庫獲取真實線上人數
// $online = $redis->get('online_users');
// $count = $online ? (int)$online : 0;
// 示範用隨機數
$count = rand(100, 9999);
$data = array('n' => $count);
// 支援 JSONP 跨域
if (isset($_GET['callback'])) {
echo $_GET['callback'] . '(' . json_encode($data) . ')';
} else {
echo json_encode($data);
}
?>
| 方案 | 原理 | 優點 | 缺點 |
|---|---|---|---|
| 短輪詢 | 固定間隔 AJAX 請求 | 實作簡單、相容性佳 | 延遲較高、請求數大 |
| 長輪詢 | Server 持有請求直到有資料 | 即時性好、減少空請求 | 佔用連線、Server 壓力大 |
| Server-Sent Events (SSE) | 單向持久 HTTP 連線 | 原生支援、自動重連、輕量 | 單向、IE 不支援 |
| WebSocket | 全雙工持久連線 | 真即時、雙向、低延遲 | 需專用 Server、實作複雜 |
INCR/DECR 或 HyperLogLog (PFADD/PFCOUNT) 統計線上人數,效能極佳Cache-Control: max-age=5,配合 Nginx proxy_cache 減輕 PHP 壓力$.getJSON 加入 .fail() 處理網路異常,避免動畫卡死aria-live="polite",螢幕閱讀器可即時播報<div class="count" aria-live="polite">
當前在線:<span id="number">--</span>
<span id="status" class="text-muted"></span>
</div>
<script>
var $num = $('#number'), $status = $('#status');
var requestTimer = null;
function animateNumber(target) {
$({val: parseInt($num.text()) || 0}).animate({val: target}, {
duration: 600,
easing: 'swing',
step: function() { $num.text(Math.floor(this.val)); },
complete: function() { $num.text(target); }
});
}
function fetchCount() {
$status.text('更新中...').show();
$.getJSON('number.php?callback=?')
.done(function(data) {
animateNumber(data.n);
$status.text('更新於 ' + new Date().toLocaleTimeString()).fadeOut(3000);
})
.fail(function() {
$status.text('連線失敗,重試中...').css('color', 'red');
})
.always(function() {
requestTimer = setTimeout(fetchCount, 5000);
});
}
$(function() {
fetchCount();
// 頁面可見時才輪詢 (Page Visibility API)
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
clearTimeout(requestTimer);
} else {
fetchCount();
}
});
});
</script>
從簡單的輪詢起步,逐步演進至 WebSocket 或 SSE,即可根據業務規模與即時性需求選擇最適合的技術方案。