要实现类似Excel的精确行列滚动效果,需要考虑以下几个关键点:
双重滚动容器结构:
同步滚动机制:
scrollLeft
和scrollTop
控制精确滚动<div class="excel-container" id="excelContainer">
<!-- 固定表头 -->
<div class="header-container" id="headerContainer">
<table class="header-table">
<!-- 表头内容 -->
</table>
</div>
<!-- 固定左侧列 -->
<div class="left-container" id="leftContainer">
<table class="left-table">
<!-- 左侧列内容 -->
</table>
</div>
<!-- 主内容区域 -->
<div class="content-container" id="contentContainer">
<table class="content-table" id="contentTable">
<!-- 表格内容 -->
</table>
</div>
</div>
.excel-container {
position: relative;
width: 800px;
height: 600px;
overflow: auto;
}
.header-container {
position: absolute;
top: 0;
left: 0;
z-index: 10;
overflow: hidden;
}
.left-container {
position: absolute;
top: 0;
left: 0;
z-index: 5;
overflow: hidden;
}
.content-container {
position: absolute;
top: 0;
left: 0;
overflow: auto;
}
// 获取DOM元素
const excelContainer = document.getElementById('excelContainer');
const headerContainer = document.getElementById('headerContainer');
const leftContainer = document.getElementById('leftContainer');
const contentContainer = document.getElementById('contentContainer');
const contentTable = document.getElementById('contentTable');
// 设置初始尺寸
function setDimensions() {
const headerHeight = headerContainer.offsetHeight;
const leftWidth = leftContainer.offsetWidth;
contentContainer.style.top = `${headerHeight}px`;
contentContainer.style.left = `${leftWidth}px`;
contentContainer.style.width = `${excelContainer.offsetWidth - leftWidth}px`;
contentContainer.style.height = `${excelContainer.offsetHeight - headerHeight}px`;
headerContainer.style.width = `${excelContainer.offsetWidth - leftWidth}px`;
leftContainer.style.height = `${excelContainer.offsetHeight - headerHeight}px`;
}
// 同步滚动
contentContainer.addEventListener('scroll', function() {
headerContainer.scrollLeft = contentContainer.scrollLeft;
leftContainer.scrollTop = contentContainer.scrollTop;
});
// 窗口大小变化时重新计算
window.addEventListener('resize', setDimensions);
// 初始化
setDimensions();
虚拟滚动(处理大数据量):
function renderVisibleRows() {
const rowHeight = 30; // 假设每行高度
const startRow = Math.floor(contentContainer.scrollTop / rowHeight);
const visibleRowCount = Math.ceil(contentContainer.clientHeight / rowHeight);
// 只渲染可见行
// ...
}
性能优化:
// 使用requestAnimationFrame优化滚动性能
let isScrolling = false;
contentContainer.addEventListener('scroll', function() {
if (!isScrolling) {
window.requestAnimationFrame(function() {
headerContainer.scrollLeft = contentContainer.scrollLeft;
leftContainer.scrollTop = contentContainer.scrollTop;
isScrolling = false;
});
isScrolling = true;
}
});
精确像素级滚动:
// 确保行高和列宽是整数像素
function normalizeCellSizes() {
const rows = contentTable.rows;
for (let i = 0; i < rows.length; i++) {
rows[i].style.height = `${Math.floor(rows[i].offsetHeight)}px`;
}
// 同样处理列宽...
}
这种实现方式可以创建类似Excel的精确行列滚动效果,同时保持较好的性能表现。