Closed wzhudev closed 3 years ago
上一篇文章介绍了 GlobalPositionStrategy,由于它相对简单,我们没有讲解具体实现。这篇文章我们来分析更加复杂的 ConnectedOverlayPositionStrategy,该策略要求指定一个 origin 元素(可通过 setOrigin 方法指定)或称原点,在浮层元素显示或者窗口滚动的时候,浮层元素就会以原点为锚点,在页面的可视区域中显示。这种策略在组件库中是非常常用的,ng-zorro-antd 的 select cascader date-picker 等组件都用到了它。
GlobalPositionStrategy
ConnectedOverlayPositionStrategy
setOrigin
这个策略的难点就在于确定浮层的位置:浮层相对于原点一共有 12 种位置,不同的位置可能导致浮层元素的可视面积不一致,该策略需要从 12 种当中选取符合用户设置的优先级,且能够尽可能多地展示浮层元素内容的那一个。
我们还是从 apply 方法说起,如上篇文章所述,当需要调整浮层元素位置时,这个方法就会被调用。
我们省略掉一些分支情形,描述一下这个方法的主要流程
function apply(): void { // 重置浮层元素的样式 this._clearPanelClasses(); this._resetOverlayElementStyles(); this._resetBoundingBoxStyles(); // 获取视窗、原点元素和浮层元素的位置和大小 this._viewportRect = this._getNarrowedViewportRect(); this._originRect = this._getOriginRect(); this._overlayRect = this._pane.getBoundingClientRect(); // 为每一个可选的位置计算可视区域大小,每个位置按照优先级有序地排列 for (let pos of this._preferredPositions) { // 计算该位置下,浮层元素相对原点元素的定位点 let originPoint = this._getOriginPoint(originRect, pos); // 计算浮层元素的定位点 let overlayPoint = this._getOverlayPoint(originPoint, overlayRect, pos); // 计算这种情况下浮层元素能够在可视窗口内如何进行展示 let overlayFit = this._getOverlayFit(overlayPoint, overlayRect, viewportRect, pos); if (overlayFit.isCompletelyWithinViewport) { // 1. 如果能够完全展示在可视区域当中,直接应用这个定位 } if (this._canFitWithFlexibleDimensions(overlayFit, overlayPoint, viewportRect)) { // 2. 如果能够通过调整浮层元素的宽高来让浮层元素可视,那么就记录一下这种定位 } // 3. 最后,如果这个定位的可视区域大于其他的定位方法,则将它作为 fallback } // 处理分支 2 情形中的定位 // 如果没有分支情形 2 的定位,那么就应用 fallback 定位 if (this._canPush) { // 如果用户允许偏移,那么就把浮层元素推到可视区域当中 } // 否则直接应用定位 this._applyPosition(fallback!.position, fallback!.originPoint); }
在了解了算法主要内容的基础下,我们来深入探究一下一些细节问题:
如何对元素进行定位
上一篇文章介绍了
GlobalPositionStrategy
,由于它相对简单,我们没有讲解具体实现。这篇文章我们来分析更加复杂的ConnectedOverlayPositionStrategy
,该策略要求指定一个 origin 元素(可通过setOrigin
方法指定)或称原点,在浮层元素显示或者窗口滚动的时候,浮层元素就会以原点为锚点,在页面的可视区域中显示。这种策略在组件库中是非常常用的,ng-zorro-antd 的 select cascader date-picker 等组件都用到了它。这个策略的难点就在于确定浮层的位置:浮层相对于原点一共有 12 种位置,不同的位置可能导致浮层元素的可视面积不一致,该策略需要从 12 种当中选取符合用户设置的优先级,且能够尽可能多地展示浮层元素内容的那一个。
我们还是从 apply 方法说起,如上篇文章所述,当需要调整浮层元素位置时,这个方法就会被调用。
我们省略掉一些分支情形,描述一下这个方法的主要流程
在了解了算法主要内容的基础下,我们来深入探究一下一些细节问题:
如何对元素进行定位