Element UI表格横向滚动条固定底部实现方案
1. 问题场景当表格“跑”出了屏幕在后台管理系统、数据报表这类前端开发中Element UI 的el-table组件绝对是高频选手。它功能强大开箱即用极大地提升了我们处理表格数据的效率。但不知道你有没有遇到过这样一个让人有点“抓狂”的场景一个列数超多的宽表格用户必须水平滚动才能看完所有列。当用户向下滚动页面去看表格下方的其他内容时那个控制表格左右滚动的横向滚动条会跟着表格一起“跑”到屏幕上方甚至完全消失在视野之外。这时候用户如果想调整查看表格的某几列就必须先向上滚动页面找到表格再操作横向滚动条然后再向下滚动继续看下面的内容。这个交互过程非常割裂体验极差。尤其是在展示大量监控数据、财务对账表格时用户的核心诉求是能随时对照表头和数据这种上下反复的跳动会严重打断工作流。所以我们今天要解决的核心需求就很明确了如何让el-table的横向滚动条始终固定在浏览器窗口的底部即视口底部无论用户如何上下滚动页面这个滚动条都触手可及实现类似 Excel 冻结窗格下滚动条的效果。这不是 Element UI 官方提供的功能但却是提升复杂表格用户体验的一个关键细节。实现它需要我们深入理解el-table的 DOM 结构、CSS 布局和滚动机制并进行一些“外科手术”式的 DOM 操作与样式覆盖。2. 核心原理解剖 el-table 的滚动结构要实现滚动条固定首先得知道它在哪里以及它是如何工作的。一个渲染了横向滚动条的el-table其生成的 DOM 结构大致如下经过简化div classel-table !-- 表格头部 -- div classel-table__header-wrapper table.../table /div !-- 表格主体 -- div classel-table__body-wrapper table.../table !-- 横向滚动条容器 -- div classel-table__body-scrollbar el-table__scrollbar div classel-table__scrollbar-wrap div classel-table__scrollbar-thumb styletransform: translateX(0%);/div /div /div /div /div关键点在于那个.el-table__body-scrollbar的div。它就是横向滚动条的视觉载体。在默认情况下这个div是position: absolute定位的它相对于其父容器.el-table__body-wrapper进行定位。而.el-table__body-wrapper又是.el-table的一部分。当我们滚动页面时整个.el-table节点会随着文档流移动。.el-table__body-scrollbar虽然绝对定位于其父级但父级在动它自然也跟着动。这就是为什么滚动条会“跑”掉的根本原因。那么解决的思路就清晰了“剥离”将这个滚动条节点从原来的 DOM 树中“取出来”。“移植”将它放置到一个新的、位置固定的容器中。“联动”确保新位置的滚动条拖动时能精确控制原表格内容的横向滚动反之当表格因其他方式如编程式滚动滚动时新滚动条的位置也要同步更新。这听起来有点像器官移植手术我们需要确保神经事件和血管数据的连接不能断。3. 方案选型CSS 魔法还是 JS 操控面对这个问题通常有两种实现思路方案一纯 CSSposition: fixed这是最直观的想法。我们通过 CSS 选择器找到那个滚动条元素直接给它加上position: fixed; bottom: 0;之类的样式。然而这条路几乎走不通。原因有三层级与裁剪问题el-table的.el-table__body-wrapper很可能设置了overflow: hidden或存在层级上下文导致fixed定位的滚动条部分被遮挡或显示异常。事件绑定失效滚动条的拖拽事件是直接绑定在原 DOM 节点上的。仅仅通过 CSS 改变其视觉位置无法改变其事件触发的作用域拖动操作很可能无法正确触发表格滚动。多实例冲突如果一个页面有多个需要固定滚动条的表格简单的fixed定位会导致所有滚动条堆叠在同一个位置无法区分。方案二JS 动态移植与同步推荐这是更可靠、更可控的方案。我们使用 JavaScript 来执行前面提到的“剥离-移植-联动”三部曲。具体步骤是使用MutationObserver或组件生命周期钩子在表格渲染完成后获取到原生的横向滚动条 DOM 节点。创建一个新的、position: fixed定位的容器div将其插入到body末尾。将原滚动条节点append到这个新的固定容器中。此时原节点从旧父级中移除并加入了新父级。监听新滚动条的拖拽事件并手动计算拖动比例同步设置原表格容器的scrollLeft属性。监听原表格的横向滚动事件反过来更新新滚动条滑块的位置。这个方案虽然代码量稍多但能完全掌控滚动逻辑完美解决事件同步和多实例问题是生产环境下的首选。4. 手把手实现完整的代码与步骤我们来一步步实现方案二。这里以 Vue 3 组合式 API 为例但核心逻辑同样适用于 Vue 2 或其它框架。4.1 组件封装与基础结构首先我们创建一个名为FixedScrollbarTable.vue的组件它包裹了el-table并增加了固定滚动条的功能。template div classfixed-scrollbar-table-container refcontainerRef el-table v-bind$attrs :datatableData scrollhandleTableScroll reftableRef !-- 透传所有插槽保证灵活性 -- slot/slot /el-table /div /template script setup import { ref, onMounted, onUnmounted, nextTick, watch } from vue; import { ElTable } from element-plus; // 如果是 Element UI 2.x导入方式不同 const props defineProps({ data: { type: Array, default: () [] } }); const containerRef ref(null); const tableRef ref(null); const tableData ref(props.data); // 核心变量 let originalScrollbarEl null; // 原生的滚动条元素 let fixedContainerEl null; // 固定的容器元素 let isDragging false; // 是否正在拖拽 let startX 0; // 拖拽起始位置 let startScrollLeft 0; // 拖拽起始时表格的scrollLeft // 初始化固定滚动条 const initFixedScrollbar async () { await nextTick(); // 等待表格渲染完成 const tableEl tableRef.value?.$el; if (!tableEl) return; // 1. 查找原生的横向滚动条元素 // 注意Element Plus 和 Element UI 的类名可能略有不同这里是 Element Plus 的 originalScrollbarEl tableEl.querySelector(.el-table__body-scrollbar.el-table__scrollbar:not(.is-vertical)); if (!originalScrollbarEl) { // 可能表格宽度不足未生成滚动条 return; } // 2. 创建固定的容器 fixedContainerEl document.createElement(div); fixedContainerEl.className fixed-horizontal-scrollbar-container; Object.assign(fixedContainerEl.style, { position: fixed, bottom: 0, left: 0, width: 100%, height: 12px, // 滚动条高度 backgroundColor: #f5f7fa, // 与el-table背景色协调 zIndex: 2000, // 确保在最上层 display: flex, alignItems: center, justifyContent: center, boxSizing: border-box, borderTop: 1px solid #ebeef5 }); // 3. 将原滚动条移植到固定容器 // 先隐藏原位置滚动条避免重复出现通过CSS originalScrollbarEl.style.opacity 0; fixedContainerEl.appendChild(originalScrollbarEl); document.body.appendChild(fixedContainerEl); // 4. 恢复滚动条在固定容器内的样式 Object.assign(originalScrollbarEl.style, { position: relative, width: calc(100% - 40px), // 留出边距 margin: 0 auto, opacity: 1 }); // 5. 绑定拖拽事件 bindScrollbarEvents(); // 初始同步一次位置 syncScrollbarPosition(); }; // 同步滚动条滑块位置 const syncScrollbarPosition () { const tableBodyWrapper tableRef.value?.$el?.querySelector(.el-table__body-wrapper); if (!tableBodyWrapper || !originalScrollbarEl) return; const scrollLeft tableBodyWrapper.scrollLeft; const scrollWidth tableBodyWrapper.scrollWidth; const clientWidth tableBodyWrapper.clientWidth; const maxScrollLeft scrollWidth - clientWidth; if (maxScrollLeft 0) { // 无需滚动隐藏固定容器 fixedContainerEl.style.display none; return; } fixedContainerEl.style.display flex; const ratio scrollLeft / maxScrollLeft; const scrollbarWrap originalScrollbarEl.querySelector(.el-table__scrollbar-wrap); const scrollbarThumb originalScrollbarEl.querySelector(.el-table__scrollbar-thumb); if (scrollbarWrap scrollbarThumb) { const thumbMaxTranslate scrollbarWrap.clientWidth - scrollbarThumb.offsetWidth; const translateX ratio * thumbMaxTranslate; scrollbarThumb.style.transform translateX(${translateX}px); } }; // 处理表格自身的滚动事件 const handleTableScroll (event) { // 注意Element Table的scroll事件参数可能包含scrollLeft信息也可能需要从DOM读取 syncScrollbarPosition(); }; // 绑定固定滚动条的拖拽事件 const bindScrollbarEvents () { const scrollbarThumb originalScrollbarEl?.querySelector(.el-table__scrollbar-thumb); const scrollbarWrap originalScrollbarEl?.querySelector(.el-table__scrollbar-wrap); if (!scrollbarThumb || !scrollbarWrap) return; const onMouseDown (e) { isDragging true; startX e.clientX; const tableBodyWrapper tableRef.value?.$el?.querySelector(.el-table__body-wrapper); startScrollLeft tableBodyWrapper?.scrollLeft || 0; document.addEventListener(mousemove, onMouseMove); document.addEventListener(mouseup, onMouseUp); e.preventDefault(); }; const onMouseMove (e) { if (!isDragging) return; const deltaX e.clientX - startX; const scrollbarWrapWidth scrollbarWrap.clientWidth; const thumbWidth scrollbarThumb.offsetWidth; const thumbMaxTranslate scrollbarWrapWidth - thumbWidth; if (thumbMaxTranslate 0) return; // 计算拖动比例 const dragRatio deltaX / thumbMaxTranslate; const tableBodyWrapper tableRef.value?.$el?.querySelector(.el-table__body-wrapper); if (tableBodyWrapper) { const scrollWidth tableBodyWrapper.scrollWidth; const clientWidth tableBodyWrapper.clientWidth; const maxScrollLeft scrollWidth - clientWidth; const newScrollLeft startScrollLeft dragRatio * maxScrollLeft; // 设置表格滚动 tableBodyWrapper.scrollLeft Math.max(0, Math.min(newScrollLeft, maxScrollLeft)); // 同步更新滑块位置虽然handleTableScroll会触发但这里直接更新更跟手 syncScrollbarPosition(); } }; const onMouseUp () { isDragging false; document.removeEventListener(mousemove, onMouseMove); document.removeEventListener(mouseup, onMouseUp); }; scrollbarThumb.addEventListener(mousedown, onMouseDown); // 点击滚动条轨道也可以跳转可选功能 scrollbarWrap.addEventListener(mousedown, (e) { if (e.target scrollbarWrap) { const rect scrollbarWrap.getBoundingClientRect(); const clickX e.clientX - rect.left; const wrapWidth rect.width; const thumbWidth scrollbarThumb.offsetWidth; const targetRatio (clickX - thumbWidth / 2) / (wrapWidth - thumbWidth); const tableBodyWrapper tableRef.value?.$el?.querySelector(.el-table__body-wrapper); if (tableBodyWrapper) { const scrollWidth tableBodyWrapper.scrollWidth; const clientWidth tableBodyWrapper.clientWidth; const maxScrollLeft scrollWidth - clientWidth; tableBodyWrapper.scrollLeft targetRatio * maxScrollLeft; } } }); }; // 监听窗口变化重新同步 const handleResize () { syncScrollbarPosition(); }; onMounted(() { initFixedScrollbar(); window.addEventListener(resize, handleResize); }); onUnmounted(() { // 组件销毁时清理DOM和事件 if (fixedContainerEl document.body.contains(fixedContainerEl)) { // 可以考虑将滚动条移回原处但更简单的做法是直接移除 document.body.removeChild(fixedContainerEl); } window.removeEventListener(resize, handleResize); }); // 监听数据变化表格可能重新渲染 watch(() props.data, (newVal) { tableData.value newVal; // 数据更新后DOM会变需要重新初始化滚动条 nextTick(() { // 简单的做法先清理旧的再初始化新的 if (fixedContainerEl document.body.contains(fixedContainerEl)) { document.body.removeChild(fixedContainerEl); originalScrollbarEl null; fixedContainerEl null; } initFixedScrollbar(); }); }, { deep: true }); /script style scoped .fixed-scrollbar-table-container { position: relative; } /* 隐藏原表格位置的滚动条避免出现两个 */ :deep(.el-table__body-scrollbar.el-table__scrollbar:not(.is-vertical)) { opacity: 0 !important; pointer-events: none !important; } /style4.2 关键代码段解析initFixedScrollbar函数这是核心初始化函数。它通过querySelector精准找到横向滚动条。创建fixedContainerEl时我们将其样式设置为position: fixed; bottom: 0; width: 100%这正是实现“固定在底部”的关键。appendChild操作会将原节点从 DOM 树中移动到新容器下。syncScrollbarPosition函数负责同步。它计算表格内容区域的滚动比例(scrollLeft / maxScrollLeft)然后将这个比例应用到固定滚动条滑块的transform: translateX上实现视觉同步。bindScrollbarEvents函数负责事件联动。它为固定滚动条的滑块绑定了mousedown、mousemove、mouseup事件。在拖动时计算鼠标移动距离相对于滚动条可拖动总长度的比例然后将这个比例换算成表格应该滚动的距离(deltaX / thumbMaxTranslate) * maxScrollLeft并设置表格的scrollLeft。同时也为滚动条轨道添加了点击跳转功能提升用户体验。样式覆盖:deep()在style scoped中我们使用:deep()选择器Vue 3或/deep/、::v-deepVue 2来穿透作用域将原表格位置的滚动条隐藏opacity: 0并禁用指针事件防止出现“重影”。生命周期与响应式在onMounted中初始化在onUnmounted中清理防止内存泄漏。通过watch监听表格数据变化并在nextTick后重新初始化以应对动态数据加载的场景。监听window.resize事件确保窗口大小变化后滚动条位置和状态依然正确。5. 避坑指南与实战心得在实际使用和封装这个功能的过程中我踩过不少坑也总结出一些让组件更健壮、更通用的经验。5.1 坑点一滚动条元素获取时机与异步渲染el-table的内部滚动条并非在组件挂载后立即生成。它的渲染取决于表格的最终布局宽度和列宽总和。如果列宽是自适应的或者表格容器宽度在挂载后发生了变化滚动条可能会在下一帧或更晚才出现。我的解决方案不要只在onMounted里调用一次initFixedScrollbar。我采用了“轮询观察”的组合拳。首先在onMounted中尝试初始化如果没找到滚动条则启动一个短暂的setInterval例如每100ms检查一次持续尝试3-5秒。更优雅的方式是结合MutationObserver来监听.el-table__body-wrapper的子节点变化一旦发现滚动条元素被添加就立刻初始化。在上面的示例中我们依赖nextTick和数据变化的watch来重新初始化对于大多数场景已经足够但对于极其动态的布局可能需要更强大的监听机制。5.2 坑点二多表格实例的冲突与 z-index 战争当一个页面有多个FixedScrollbarTable时每个组件都会创建一个position: fixed的容器并且默认都堆叠在屏幕底部。如果不加处理它们会相互重叠最后一个组件的滚动条会盖住前面的。我的解决方案为每个固定容器动态计算bottom值。第一个表格的滚动条在bottom: 0第二个表格的滚动条应该在bottom: 12px假设滚动条高度12px以此类推。我们可以在组件内部维护一个全局或通过 Provide/Inject的计数器或者根据组件在页面中的位置顺序来计算bottom。更简单粗暴但有效的方法是给固定容器一个足够大的z-index如2000并确保其背景色不透明这样即使重叠用户也只能看到最上面一个但这显然不是最佳体验。推荐实现动态bottom计算。5.3 坑点三与页面其他固定元素的兼容性如果页面本身有固定在底部的页脚栏Footer或者使用了el-main等有自身滚动区域的布局组件我们的固定滚动条可能会与之发生重叠。我的解决方案组件应该提供一个offsetBottom的 prop允许使用者根据实际情况设置滚动条距离窗口底部的偏移量。例如如果有一个高度为 60px 的页脚就可以设置:offset-bottom60。在创建fixedContainerEl时将bottom样式设置为${offsetBottom}px即可。这增加了组件的灵活性。5.4 坑点四性能与频繁的 DOM 操作在表格数据频繁更新如实时数据推送的场景下我们的watch会反复触发销毁和重建滚动条可能引起性能问题或视觉闪烁。我的解决方案实现一个“智能更新”策略。在watch回调中不要总是先removeChild再init。可以先检查新的表格渲染后是否仍然需要横向滚动条比较scrollWidth和clientWidth。如果不需要则隐藏固定容器如果需要则尝试复用现有的fixedContainerEl和originalScrollbarEl只更新其内部滑块的同步逻辑避免不必要的 DOM 增删。这需要对el-table的更新机制有更细粒度的把握。5.5 一个实用的进阶技巧滚动条样式美化原生的 Element 滚动条样式可能和你的项目设计风格不搭。既然我们已经接管了滚动条就可以轻松地美化它。你可以在fixedContainerEl的样式和originalScrollbarEl的内部样式上做文章。// 在创建 fixedContainerEl 后可以添加自定义类名 fixedContainerEl.classList.add(custom-scrollbar-container); // 然后在外部的全局或组件样式表中定义 .custom-scrollbar-container { background-color: #2c3e50 !important; height: 10px !important; border-radius: 5px !important; } .custom-scrollbar-container .el-table__scrollbar-thumb { background-color: #3498db !important; border-radius: 5px !important; }这样固定滚动条就能完美融入你的 UI 设计体系了。6. 替代方案与边界情况思考虽然我们实现了一个相对完整的解决方案但也要知道它的局限性和其他可能性。方案局限复杂度引入了额外的 DOM 操作和事件监听增加了代码复杂度和潜在的 bug 点。框架耦合实现深度依赖 Element UI/Plus 的内部 DOM 结构如果未来组件库版本升级导致类名或结构变化我们的组件可能会失效。移动端适配上述事件监听是基于鼠标的在移动端触摸屏上需要额外处理touchstart、touchmove、touchend事件。替代思路CSSposition: sticky尝试理论上可以将.el-table__body-wrapper的父级设置为position: relative然后尝试给滚动条元素加上position: sticky; bottom: 0;。但在el-table复杂的布局上下文和overflow设置下成功率很低不推荐作为主要方案。完全自定义滚动条放弃使用el-table自带的滚动条使用如better-scroll、perfect-scrollbar等第三方库或者自己完全重写一个滚动条组件。这种方式解耦最彻底定制性最强但实现成本也最高需要自己处理所有滚动逻辑和同步。调整布局设计从根本上思考是否必须展示如此多列的表格能否通过“列筛选”、“列固定冻结”、“详情展开”等方式来减少横向滚动这通常是用户体验更优的解。边界情况处理表格初始无滚动条缩放窗口后出现需要监听window.resize事件并重新执行检查与初始化逻辑。表格在弹窗Dialog或抽屉Drawer中这时固定滚动条的参考视口可能不是window而是弹窗容器。你需要计算滚动条相对于弹窗底部的距离这会使问题复杂化数倍。在这种情况下可能需要放弃全局固定转而寻求将滚动条固定在弹窗容器底部的方案这需要获取弹窗容器的 DOM 引用并计算相对位置。实现一个健壮的el-table横向滚动条固定功能远不止把元素定位到bottom: 0那么简单。它涉及到对现有组件 DOM 结构的深度干预、精确的事件同步、以及各种边界条件的妥善处理。上面的代码和方案提供了一个坚实可靠的起点你可以根据自己项目的具体需求在此基础上进行扩展和优化。记住好的用户体验往往就藏在这些“费力”的细节里。当你把这个功能打磨稳定后它将成为你组件库中一个非常提效的利器。

相关新闻

openGauss数据库安全架构与实战指南

openGauss数据库安全架构与实战指南

1. openGauss数据库安全架构全景解析在企业级数据库应用中,安全性始终是核心考量因素。作为国产数据库的代表作,openGauss通过"纵深防御"理念构建了四层安全防护体系:1.1 基础设施安全层这是整个安全架构的基石,包含&am…

2026/10/19 11:23:18 阅读更多 →
从零构建短视频AI自动化生成流水线:技术原理与Python实战

从零构建短视频AI自动化生成流水线:技术原理与Python实战

1. 这篇文章真正要解决的问题 如果你是一名开发者,尤其是对音视频处理、社交媒体内容生成或AI应用集成感兴趣的开发者,最近可能被一个听起来有点“怪”的词刷屏了——“短卡甩饼”。它不是一道菜,也不是网络黑话,而是一个在技术圈…

2026/10/15 14:27:49 阅读更多 →
AI驱动3D数字人舞蹈生成:从音乐到动作的完整技术实现

AI驱动3D数字人舞蹈生成:从音乐到动作的完整技术实现

最近,你是不是也刷到过那个“古风旗袍摇”的短视频?一个身着旗袍的虚拟形象,伴随着动感的音乐,跳出极具节奏感和力量感的舞蹈。它不像传统古风舞蹈那样柔美,反而充满现代街舞的“劲儿”,这种强烈的反差感瞬…

2026/10/19 12:01:34 阅读更多 →

最新新闻

AIGC降重工具横评:十大免费与付费平台选型指南

AIGC降重工具横评:十大免费与付费平台选型指南

1. 为什么“AI写的内容”突然需要“降重” 1.1 AIGC降重到底是什么 AIGC降重,字面上就是把AI生成的内容重新“加工一遍”,让它看起来不像AI一口气写出来的。很多人第一次听到这个词,第一反应是“AI写的东西还要改?不是直接用吗&a…

2026/10/20 23:47:42 阅读更多 →
多智能体系统架构选型:自研编排与通用框架的混合架构实践

多智能体系统架构选型:自研编排与通用框架的混合架构实践

1. 多智能体系统架构选型的真实困境1.1 从一个踩坑项目说起去年下半年,我接手了一个内部工具链的智能化改造项目。需求说起来不复杂:让几个不同职责的智能体协作完成一份技术调研报告的生成——一个负责检索资料,一个负责归纳整理&#xff0c…

2026/10/20 23:47:42 阅读更多 →
小丑排序(Bozo Sort)的C语言实现与时间复杂度分析

小丑排序(Bozo Sort)的C语言实现与时间复杂度分析

看到作业列表里出现“小丑排序”四个字的时候,我第一反应是题目排版出了问题:小丑怎么会跟排序沾边?后来把猴子排序(Bogo Sort)和小丑排序(Bozo Sort)放在一起看才明白,这道题根本不…

2026/10/20 23:47:42 阅读更多 →
Java后端生成PDF报表并返回前端预览下载的完整实现指南

Java后端生成PDF报表并返回前端预览下载的完整实现指南

最近在做一个管理系统,遇到一个很典型的需求:后端用Java生成PDF报表,然后直接返回给前端,让用户在浏览器里预览或者下载。这个需求在项目里太常见了——订单导出、合同生成、数据报表、发票打印,基本每个后台系统都会碰…

2026/10/20 23:47:42 阅读更多 →
Wireshark抓包实战:VXLAN协议解析与故障排查

Wireshark抓包实战:VXLAN协议解析与故障排查

从某天深夜开始,我的工作群里突然炸了锅:某个跨机房的业务系统出现间歇性不通,虚拟机迁移后全网段丢包,底层物理网络看起来一切正常,ping网关也通,但业务就是像被什么东西掐住了脖子。我第一反应不是重启任…

2026/10/20 23:47:42 阅读更多 →
Linux内核挂死全解析:从现象到kdump实战排查

Linux内核挂死全解析:从现象到kdump实战排查

干内核这一行的人,最怕的其实不是进程崩溃,也不是磁盘写满,而是那种半夜被电话叫醒,电话那头只说一句“机器连不上了,ping 不通,屏幕卡死,按什么都没反应”。这种时候,十有八九是 Li…

2026/10/20 23:46:41 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →