Dom-Align
2021/8/14 23:09:02
本文主要是介绍Dom-Align,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
聊聊 Dom-Align 这个包
最近在写一个弹框的 service,用到了 Dom-Align,来挨着某个元素来弹框,遇到了些坑,记录一下,以免下次再掉进去。
先聊聊 Dom-Align 怎么干活的。这个有个约定, target 指的是参考系,source(目标元素)指的是需要被定位的元素。
- 我们一般直接调用
alignElement(el,refNode,align)
这个方法。第一个参数是目标元素,第二个是参考系元素,第三个是 AlignType. 这个方法里面先调用const refNodeRegion = getRegion(target);
来获取参考系的可视区域。它是向对于 document 而言的,所以如果 document 有 scrollbar, 这个距离也是计算再内的,数据结构如下:
{ left:number, top:number, width:number, height:number, }
- 在这个函数里面,会调用
doAlign(el, refNodeRegion, align, isTargetNotOutOfVisible);
doAlign
这个方法,跳过一些不重要的,就关注主要的,它会先计算 source的可视区域。const visibleRect = getVisibleRectForElement(source, alwaysByViewport);
- 然后计算出source将要被放置的区域。
// 当前节点将要被放置的位置 // 这个函数主要是计算出最终的left,top的值。 let elFuturePos = getElFuturePos( elRegion, tgtRegion, points, offset, targetOffset ); // 当前节点将要所处的区域 let newElRegion = utils.merge(elRegion, elFuturePos);
- 下面就是微调,在adjustX,adjustY打开的情况下,如果source溢出,则会考虑在左右,上下进行颠倒来进行调整。
// 如果可视区域不能完全放置当前节点时允许调整 if ( visibleRect && (overflow.adjustX || overflow.adjustY) && isTgtRegionVisible ) { if (overflow.adjustX) { // 如果横向不能放下 if (isFailX(elFuturePos, elRegion, visibleRect)) { // 对齐位置反下 const newPoints = flip(points, /[lr]/gi, { l: "r", r: "l", }); // 偏移量也反下 const newOffset = flipOffset(offset, 0); const newTargetOffset = flipOffset(targetOffset, 0); const newElFuturePos = getElFuturePos( elRegion, tgtRegion, newPoints, newOffset, newTargetOffset ); if (!isCompleteFailX(newElFuturePos, elRegion, visibleRect)) { fail = 1; points = newPoints; offset = newOffset; targetOffset = newTargetOffset; } } } if (overflow.adjustY) { // 如果纵向不能放下 if (isFailY(elFuturePos, elRegion, visibleRect)) { // 对齐位置反下 const newPoints = flip(points, /[tb]/gi, { t: "b", b: "t", }); // 偏移量也反下 const newOffset = flipOffset(offset, 1); const newTargetOffset = flipOffset(targetOffset, 1); const newElFuturePos = getElFuturePos( elRegion, tgtRegion, newPoints, newOffset, newTargetOffset ); if (!isCompleteFailY(newElFuturePos, elRegion, visibleRect)) { fail = 1; points = newPoints; offset = newOffset; targetOffset = newTargetOffset; } } } // 如果失败,重新计算当前节点将要被放置的位置 if (fail) { elFuturePos = getElFuturePos( elRegion, tgtRegion, points, offset, targetOffset ); utils.mix(newElRegion, elFuturePos); } const isStillFailX = isFailX(elFuturePos, elRegion, visibleRect); const isStillFailY = isFailY(elFuturePos, elRegion, visibleRect); // 检查反下后的位置是否可以放下了,如果仍然放不下: // 1. 复原修改过的定位参数 if (isStillFailX || isStillFailY) { let newPoints = points; // 重置对应部分的翻转逻辑 if (isStillFailX) { newPoints = flip(points, /[lr]/gi, { l: "r", r: "l", }); } if (isStillFailY) { newPoints = flip(points, /[tb]/gi, { t: "b", b: "t", }); } points = newPoints; offset = align.offset || [0, 0]; targetOffset = align.targetOffset || [0, 0]; } // 2. 只有指定了可以调整当前方向才调整 newOverflowCfg.adjustX = overflow.adjustX && isStillFailX; newOverflowCfg.adjustY = overflow.adjustY && isStillFailY; // 确实要调整,甚至可能会调整高度宽度 if (newOverflowCfg.adjustX || newOverflowCfg.adjustY) { newElRegion = adjustForViewport( elFuturePos, elRegion, visibleRect, newOverflowCfg ); } }
- 然后就是更新宽高,如果有变化,source的位置信息被更新。同时返回位置信息。
这个里面用到了很多 Dom 的方法,例如计算可视区域,getVisibleRectForElement
,它会递归的找 offsetParent,对于 overflow 不是 visible 的,都会叠加那个可视区域。可视区域是采用{left,top,bottom,right}来描述的,跟 css 里面的 clip 计算是一样的,都是相对于 viewport 的 left,top 来计算的,这样就有了一个矩形区域。在刚才提到的递归的过程,这个矩形区域是越来越小的,其实找的是他们的交集。
这篇关于Dom-Align的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现
- 2024-06-03为什么以及如何要进行架构设计权衡?
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)