Angular CDK 了解叠加位置系统

问题描述 投票:0回答:4

我真的很想理解叠加位置参数,但没有任何运气。我也找不到有关此主题的任何文档。

下面的代码是什么意思?

const positions = [
  new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }),
  new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' })
];
this.positionStrategy = this._overlay.position()
.flexibleConnectedTo(this.getConnectedElement())
.withPositions(positions)
.withFlexibleDimensions(false)
.withPush(false);
angular angular-cdk
4个回答
76
投票

关于 Angular Overlay CDK 的文档仍然不多。我学到的大部分内容都来自他们的 Github 存储库。

全球定位战略

这将是一个全球定位战略。您创建的覆盖层将直接定位在屏幕上,而不是与元素相关。这对于弹出对话框或模式窗口很有用。

  overlayConfig = this.overlay.position().global()
    .centerHorizontally().centerVertically();

灵活连接策略

这就是您想要用于工具栏、菜单、从按钮弹出的内容的内容。您必须传递对您希望覆盖层连接到的按钮的引用:

<button id="toolbar-icons" cdkOverlayOrigin mat-button class="toolbar-button" (click)="this.showAppContext()">

在你的 Component.ts 中

showAppContext() {
  const appOverlayRef: AppOverlayRef = 
    this.appOverlayService.open(this.origin);
}

ConnectionPositionPair - 这是首选位置列表,从最理想到最不理想。所以它会首先尝试使用你传入的第一个位置。

originX:这将是“开始”、“结束”或“中心”。它是覆盖层的附着点。如果您已将按钮传递给 .flexibleConnectedTo 函数,则 this 指的是该元素的开始、结束和中心。

originY:这将是“顶部”、“底部”或“中心”。这是指传入元素的顶部、底部或中心。

所以

{ originX: 'start', originY: 'bottom' }
将是按钮的左下角。

overlayX和overlayY具有相同的选项,但指的是叠加层将附加到的位置。

{ overlayX: 'start', overlayY: 'top' }
将覆盖层的左上角附加到我们指定的原点。

然后,正如您在数组中看到的,我们可以传入多个位置。如果覆盖层不适合第一个位置,它将尝试数组中的下一个位置。因此,如果第一种方式覆盖层不适合屏幕,它将自动移动到第二个位置,此处定义为将底部的左上角连接到覆盖层的左下角。

const positions = [
  new ConnectionPositionPair(
   { originX: 'start', originY: 'bottom' },
   { overlayX: 'start', overlayY: 'top' }),
  new ConnectionPositionPair(
  { originX: 'start', originY: 'top' },
  { overlayX: 'start', overlayY: 'bottom' })];
];

withPush

您可以将 withPush 设置为 true,如果没有提供的位置适合,这会将覆盖层推送到屏幕上。

代码仍然是查看文档的最佳位置: https://github.com/angular/material2/blob/master/src/cdk/overlay/position/connected-position.ts


14
投票

经过日复一日的反复试验,David Rinck 对这个问题的回答对我有所帮助,所以我想我应该发布我在此基础上整理的备忘单,希望它能对将来的某人有所帮助。

这可能并不适合所有人,但它对我有帮助:

// top-left
originX: 'start', // left corner of the button
originY: 'bottom', // bottom corner of the button
overlayX: 'start', // left corner of the overlay to the origin
overlayY: 'top', // top corner of the overlay to the origin

// top-right
originX: 'end', // right corner of the button
originY: 'bottom', // bottom corner of the button
overlayX: 'end', // right corner of the overlay to the origin
overlayY: 'top', // top corner of the overlay to the origin

// bottom-left
originX: 'start', // left corner of the button
originY: 'top', // top corner of the button
overlayX: 'start', // left corner of the overlay to the origin
overlayY: 'bottom', // top corner of the overlay to the origin

// bottom-right
originX: 'end', // right corner of the button
originY: 'top', // top corner of the button
overlayX: 'end', // right corner of the overlay to the origin
overlayY: 'bottom', // top corner of the overlay to the origin

6
投票

David Rinck 的回答非常出色,最终对我有用的是直接使用模板指令,甚至没有进入打字稿覆盖引用(overlay.postition /手动附加/分离等)。

这是一个示例,我创建了一个位于按钮下方的模式。如果没有明确设置位置,它的行为很奇怪,所以我必须实现位置数组。

html:

<button cdkOverlayOrigin
        #trigger="cdkOverlayOrigin"
        (click)="isOpen = true">
  View Menu
</button>


<ng-template
    [cdkConnectedOverlayPanelClass]="'pm-responsive-text'"
    *ngIf="filterGroup?.filters?.length > numberOfVisibleFilters"
    cdkConnectedOverlay
    cdkConnectedOverlayPush ----- this pushes things on screen
    [cdkConnectedOverlayPositions]="positionPairs"
    [cdkConnectedOverlayOrigin]="filterTrigger"
    [cdkConnectedOverlayOpen]="isOpen"
    [cdkConnectedOverlayHasBackdrop]="true"
    (backdropClick)="isOpen = false">
    <div>...my modal code....</div>
</ng-template>

ts:

 // from my testing it doesn't seem to want to switch positions when 
 // resizing so I went ahead and just set it to the position I wanted and 
 // relied on cdkConnectedOverlayPush to handle the rest
positionPairs: ConnectionPositionPair[] = [
    {
      offsetX: 0,
      offsetY: 165,
      originX: 'start',
      originY: 'bottom',
      overlayX: 'start',
      overlayY: 'bottom',
      panelClass: null,
    },
  ];

0
投票

仅供记录,这就是我使用 Angular CDK 中的 OverlayModule 实现工具提示的方法

我的组件:

...
import { ConnectionPositionPair, OverlayModule } from '@angular/cdk/overlay';
...

@Component({
  selector: 'app-my-component-panel',
  standalone: true,
  imports: [
    OverlayModule
  ],
  templateUrl: './code-panel.component.html',
  ...
})
export class MyComponent {


  isCopied = false;

  topIsOpen = false;

  bottomIsOpen = false;

  leftOpen = false;

  rightIsOpen = false;

  // Tooltip Positions:

  topCenter: ConnectionPositionPair = {
    offsetY: -8,
    originX: 'center',
    originY: 'top',
    overlayX: 'center',
    overlayY: 'bottom',
  };

  bottomCenter: ConnectionPositionPair = {
    offsetY: 8,
    originX: 'center',
    originY: 'bottom',
    overlayX: 'center',
    overlayY: 'top',
  };

  leftCenter: ConnectionPositionPair = {
    offsetX: 8,
    originX: 'end',
    originY: 'center',
    overlayX: 'start',
    overlayY: 'center',
  };

  rightCenter: ConnectionPositionPair = {
    offsetX: -8,
    originX: 'start',
    originY: 'center',
    overlayX: 'end',
    overlayY: 'center',
  };
}

我的模板:

<div class="container">
  <button type="button"
          cdkOverlayOrigin
          #top="cdkOverlayOrigin"
          (mouseenter)="topIsOpen = true"
          (mouseleave)="topIsOpen = false">Tooltip on top</button>

  <button type="button"
          cdkOverlayOrigin
          (mouseenter)="bottomIsOpen = true"
          (mouseleave)="bottomIsOpen = false"
          #bottom="cdkOverlayOrigin">Tooltip on the bottom</button>

  <button type="button"
          (mouseenter)="leftOpen = true"
          (mouseleave)="leftOpen = false"
          cdkOverlayOrigin
          #left="cdkOverlayOrigin">Tooltip on the left</button>

  <button type="button"
          cdkOverlayOrigin
          (mouseenter)="rightIsOpen = true"
          (mouseleave)="rightIsOpen = false"
          #right="cdkOverlayOrigin">Tooltip on the right</button>
</div>


<!-- TOOLTIP TEMPLATES -->

<ng-template cdkConnectedOverlay
     [cdkConnectedOverlayOrigin]="top"
     [cdkConnectedOverlayOpen]="topIsOpen"
     [cdkConnectedOverlayPositions]="[topCenter, bottomCenter]" // FYI: if the isn't any available buffer on the top then display tooltip on the bottom
     >
  <div role="tooltip" class="tooltip">
    On top
  </div>
</ng-template>

<ng-template cdkConnectedOverlay
             [cdkConnectedOverlayOrigin]="bottom"
             [cdkConnectedOverlayOpen]="bottomIsOpen"
             [cdkConnectedOverlayPositions]="[bottomCenter, topCenter]" // FYI: if the isn't any available buffer on the bottom then display tooltip on the top
>
  <div role="tooltip" class="tooltip">
    On the bottom
  </div>
</ng-template>

<ng-template cdkConnectedOverlay
             [cdkConnectedOverlayOrigin]="left"
             [cdkConnectedOverlayOpen]="leftOpen"
             cdkConnectedOverlayGrowAfterOpen="true"
             [cdkConnectedOverlayPositions]="[leftCenter, rightCenter]" // FYI: if the isn't any available buffer on the left then display tooltip on the right
>
  <div role="tooltip" class="tooltip">
    On the left
  </div>
</ng-template>

<ng-template cdkConnectedOverlay
             [cdkConnectedOverlayOrigin]="right"
             [cdkConnectedOverlayOpen]="rightIsOpen"
             [cdkConnectedOverlayPositions]="[rightCenter, leftCenter]"> // FYI: if the isn't any available buffer on the right then display tooltip on the left
  <div role="tooltip" class="tooltip">
    On the right
  </div>
</ng-template>
© www.soinside.com 2019 - 2024. All rights reserved.