分页导航器
先看看各平台的分页导航器
CSDN:
Iconfont:
经分析比对,上述两种都是 通过实时计算页码的展示形态,动态insert DOM。
本质是: 强算法
我自身实现的有点像,但是较低难度。嘿嘿。
直接看效果吧。
后期会将 “共31页”的31改成input 点击即跳转即可。
动画:
1、 overflow 配合 inline-block transition动画移动即可
2、.active 配置 index和当前pagination相同即可
css代码
.bar-group {
float: right;
max-width: 418px;
overflow-x: hidden;
.bar-group-container {
display: inline-block;
white-space: nowrap;
transition: transform 0.3s;
.bar-item {
display: inline-block;
text-align: center;
color: #333;
height: 32px;
width: 32px;
line-height: 32px;
margin-right: 6px;
font-size: 14px;
border-radius: 99px;
&:hover {
cursor: pointer;
background-color: #ffd6d6;
}
&.active {
color: white;
background-color: red;
}
}
}
}
算法逻辑:
需求:保证用户体验感,比如:最大限制11格子,高亮的数字左边必定包含6格,右边包含4格。
当点击指定页码时,当前索引为基准(index)。以及已经偏移的步长(step)根据6-4规则,绞尽脑汁思考。计算。得出:
比如当前点击数字的索引为 24 ,当前步长 14
shouldMoveStep:当前需要移动的距离 ( 24 - 20 = 4 )
maxMoveStep:理论上最大能移动的距离 ( 24 + 14(step) - 6(左侧格子占位6) ) 得出 32
两者取最小的。
其实maxMoveStep仅在step===0 时才有意义,它的设立是防止数字的过分偏移。
最后,需要step> 0时,需要进行边界限制,Math.max或min 0以及totalPage-maxPage (可以移动的极限步长),防止越边界)
总结:
step === 0 需要判断 shouldMoveStep 和 maxMoveStep
step > 0 需要判断shouldMoveStep 和 边界上下限
核心代码如下:
/**
* handlePageNumberClick: 内部逻辑主要计算步长
* step->calcMove:
* step情况有三种:
* 1.中间移动时:前后相减 得出 相距步长 直接跳 (step > 0)
* 2.靠起始位置移动:需要计算出当前限制步长 与 相距步长 相较取小(左开始step === 0)
* 3.靠终点位置移动:需要计算出当前限制步长 与 相距步长 相较取小(右开始step === 0)
*/
const handlePageNumberClick = (index) => {
const oldIndex = activePageIndex;
let shouldMoveStep, limitMoveStep;// 相距步长 限制步长
shouldMoveStep = Math.abs(index - oldIndex); // 兼容左右情况
if (
index > MIDDLE_PAGE &&
index > oldIndex
) {
// 朝右:
// 限制步长:(左侧步长为0时需要限制,保证数字居中)
limitMoveStep = index - MIDDLE_PAGE;
if (shouldMoveStep < limitMoveStep) {
// 注:右移可能越界,若越界则取极值totalPage - MAX_PAGE
const calcMove = Math.min(totalPage - MAX_PAGE, step + shouldMoveStep);
setStep(calcMove);
} else {
setStep(step + limitMoveStep);
}
} else if (
totalPage - index > MAX_PAGE - MIDDLE_PAGE &&
index < oldIndex
) {
// 朝左:
// 限制步长:(右侧步长为0时需要限制,保证数字居中)
limitMoveStep = totalPage - index - (MAX_PAGE - MIDDLE_PAGE);
if (shouldMoveStep < limitMoveStep) {
// 注:左移可能越界,若越界则取极值totalPage - MAX_PAGE
const calcMove = Math.max(0, step - shouldMoveStep);
setStep(calcMove);
} else {
setStep(step - limitMoveStep);
}
}
// 2、回调
setNumIndex(index);
onHandlePaginationClick(index);
}