fix: 进度条平滑过渡 — force reflow 技巧确保 CSS transition 生效
- 临时关 transition → 设旧值 → offsetWidth reflow → 开 transition → 设新值 - DOM 复用: 首次 innerHTML 创建, 后续只改属性 - 进度条从旧值滑到新值, 不再闪现 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
1 parent
417213096f
commit
3ca001b938
4 files changed
+59
-23
No files matched your search
@@ -262,5 +262,27 @@
|
||||
"framework.command.execute"
|
||||
],
|
||||
"timestamp": 27544.2709947
|
||||
},
|
||||
"29ffcf99": {
|
||||
"plugin_name": "example_plugin",
|
||||
"permissions": [
|
||||
"plugin.example.read",
|
||||
"plugin.example.write",
|
||||
"plugin.example.execute",
|
||||
"framework.event.subscribe",
|
||||
"framework.command.execute"
|
||||
],
|
||||
"timestamp": 27821.237625479
|
||||
},
|
||||
"bd46f35e": {
|
||||
"plugin_name": "sentinel",
|
||||
"permissions": [
|
||||
"plugin.sentinel.read",
|
||||
"plugin.sentinel.write",
|
||||
"plugin.network.access",
|
||||
"framework.event.subscribe",
|
||||
"framework.command.execute"
|
||||
],
|
||||
"timestamp": 27821.239961313
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ commands:
|
||||
permissions:
|
||||
- framework.command.test
|
||||
source: internal
|
||||
last_updated: 27544.226537616
|
||||
last_updated: 27821.221132094
|
||||
plugin_commands:
|
||||
example_plugin:
|
||||
echo: *id001
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
http_port: 4200
|
||||
last_updated: 27544.261331002
|
||||
last_updated: 27821.238246209
|
||||
plugin_routes:
|
||||
example_plugin:
|
||||
- methods:
|
||||
|
||||
@@ -164,27 +164,41 @@
|
||||
var oldMem = parseFloat((body.getAttribute('data-mem')||memVal));
|
||||
body.setAttribute('data-cpu', cpuVal);
|
||||
body.setAttribute('data-mem', memVal);
|
||||
body.innerHTML =
|
||||
'<div class="metric-row">'+
|
||||
'<div class="metric"><div class="metric-label">CPU</div><div class="metric-value cpu-val">'+oldCpu.toFixed(1)+'%</div><div class="metric-bar"><div class="metric-bar-fill '+cpuBarCls+'" style="width:'+oldCpu+'%"></div></div></div>'+
|
||||
'<div class="metric"><div class="metric-label">MEM</div><div class="metric-value mem-val">'+oldMem.toFixed(1)+'%</div><div class="metric-bar"><div class="metric-bar-fill '+memBarCls+'" style="width:'+oldMem+'%"></div></div></div>'+
|
||||
'</div>'+
|
||||
'<div class="metric-row">'+
|
||||
'<div class="metric"><div class="metric-label">NET ↓</div><div class="metric-value" style="font-size:.9rem">'+fmtSpeed(net.rx_bytes_sec||0)+'</div></div>'+
|
||||
'<div class="metric"><div class="metric-label">NET ↑</div><div class="metric-value" style="font-size:.9rem">'+fmtSpeed(net.tx_bytes_sec||0)+'</div></div>'+
|
||||
'</div>'+
|
||||
'<div style="font-size:.7rem;color:var(--text-dim);margin-top:8px">内存 '+(mem.used_gb||0).toFixed(1)+'/'+(mem.total_gb||0).toFixed(1)+' GB</div>';
|
||||
// 动画计数
|
||||
var cpuEl = body.querySelector('.cpu-val');
|
||||
var memEl = body.querySelector('.mem-val');
|
||||
animateValue(cpuEl, oldCpu, cpuVal, 1, '%');
|
||||
animateValue(memEl, oldMem, memVal, 1, '%');
|
||||
// 进度条平滑过渡 (CSS transition 自动处理)
|
||||
requestAnimationFrame(function(){
|
||||
var fills = body.querySelectorAll('.metric-bar-fill');
|
||||
if (fills[0]) { fills[0].style.width = cpuVal+'%'; fills[0].className = 'metric-bar-fill '+cpuBarCls; }
|
||||
if (fills[1]) { fills[1].style.width = memVal+'%'; fills[1].className = 'metric-bar-fill '+memBarCls; }
|
||||
});
|
||||
var isNew = !body.querySelector('.cpu-val');
|
||||
if (isNew) {
|
||||
body.innerHTML =
|
||||
'<div class="metric-row">'+
|
||||
'<div class="metric"><div class="metric-label">CPU</div><div class="metric-value cpu-val">0%</div><div class="metric-bar"><div class="metric-bar-fill" style="width:0%"></div></div></div>'+
|
||||
'<div class="metric"><div class="metric-label">MEM</div><div class="metric-value mem-val">0%</div><div class="metric-bar"><div class="metric-bar-fill" style="width:0%"></div></div></div>'+
|
||||
'</div>'+
|
||||
'<div class="metric-row">'+
|
||||
'<div class="metric"><div class="metric-label">NET ↓</div><div class="metric-value net-down" style="font-size:.9rem"></div></div>'+
|
||||
'<div class="metric"><div class="metric-label">NET ↑</div><div class="metric-value net-up" style="font-size:.9rem"></div></div>'+
|
||||
'</div>'+
|
||||
'<div class="mem-detail"></div>';
|
||||
}
|
||||
// 更新 NET
|
||||
body.querySelector('.net-down').textContent = fmtSpeed(net.rx_bytes_sec||0);
|
||||
body.querySelector('.net-up').textContent = fmtSpeed(net.tx_bytes_sec||0);
|
||||
body.querySelector('.mem-detail').innerHTML = '<div style="font-size:.7rem;color:var(--text-dim);margin-top:8px">内存 '+(mem.used_gb||0).toFixed(1)+'/'+(mem.total_gb||0).toFixed(1)+' GB</div>';
|
||||
// 进度条: 先设旧值 → force reflow → 设新值
|
||||
var barCpu = body.querySelectorAll('.metric-bar-fill')[0];
|
||||
var barMem = body.querySelectorAll('.metric-bar-fill')[1];
|
||||
barCpu.style.transition = 'none';
|
||||
barMem.style.transition = 'none';
|
||||
barCpu.style.width = oldCpu+'%';
|
||||
barMem.style.width = oldMem+'%';
|
||||
barCpu.className = 'metric-bar-fill '+cpuBarCls;
|
||||
barMem.className = 'metric-bar-fill '+memBarCls;
|
||||
barCpu.offsetWidth; // force reflow
|
||||
barMem.offsetWidth;
|
||||
barCpu.style.transition = '';
|
||||
barMem.style.transition = '';
|
||||
barCpu.style.width = cpuVal+'%';
|
||||
barMem.style.width = memVal+'%';
|
||||
// 数字跳动
|
||||
animateValue(body.querySelector('.cpu-val'), oldCpu, cpuVal, 1, '%');
|
||||
animateValue(body.querySelector('.mem-val'), oldMem, memVal, 1, '%');
|
||||
} else {
|
||||
body.innerHTML = '<div style="color:var(--error);font-size:.85rem">'+(n.error||'离线')+'</div>';
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user