Angular CDK Overlayで要素の相対位置でオーバーレイを表示する
Angular CDK Overlay の2本目の記事です。前回は画面に対する絶対位置で表示する方法についてでした。
今回は特定の要素に対して相対位置でオーバーレイを表示する方法です。
環境
Angular CLI: 9.1.3 Node: 12.16.2 OS: win32 x64 Angular: 9.1.3 ... animations, cli, common, compiler, compiler-cli, core, forms ... language-service, platform-browser, platform-browser-dynamic ... router Ivy Workspace: Yes Package Version ----------------------------------------------------------- @angular-devkit/architect 0.901.3 @angular-devkit/build-angular 0.901.3 @angular-devkit/build-optimizer 0.901.3 @angular-devkit/build-webpack 0.901.3 @angular-devkit/core 9.1.3 @angular-devkit/schematics 9.1.3 @angular/cdk 9.2.1 @angular/material 9.2.1 @ngtools/webpack 9.1.3 @schematics/angular 9.1.3 @schematics/update 0.901.3 rxjs 6.5.5 typescript 3.8.3 webpack 4.42.0
今回のコードは こちら に Push しています。
オーバーレイで Component を表示する
ConnectedOverlay で要素の相対位置にオーバーレイを表示する
FlexibleConnectedPositionStrategy
は指定した要素に対して相対位置でオーバーレイを表示する PositionStrategy
です。起点となる要素は FlexibleConnectedPositionStrategyOrigin
に定義されている HTMLElement
、 ElementRef
、そして { x: number, y: number, width: number, height: number }
を指定します。要素と言いつつ自分で作った任意の箱も指定できるみたいですね。
まずは適当に表示してみます。起点となる要素の ElementRef は CdkOverlayOrigin
で簡単に取得する事ができます。
<button #origin="cdkOverlayOrigin" cdk-overlay-origin (click)="showOverlay(origin.elementRef)">Show overlay</button>
showOverlay(origin: ElementRef) { let positionStrategy: FlexibleConnectedPositionStrategy = this._overlay.position().flexibleConnectedTo(origin); const config: OverlayConfig = { positionStrategy, width: 'auto', height: 'auto', }; const overlayRef: OverlayRef = this._overlay.create(config); const componentPortal: ComponentPortal<OverlayContentComponent> = new ComponentPortal(OverlayContentComponent); const componentRef: ComponentRef<OverlayContentComponent> = overlayRef.attach(componentPortal); }
これでオーバーレイを表示するために設定しているボタンに対して相対位置で表示できるようになりました。次に相対位置を指定します。
相対位置を指定するには FlexibleConnectedPositionStrategy#withPositions(ConnectedPosition[])
を利用します。引数の ConnectedPosition
は相対位置を記したオブジェクトの配列です。 ConnectedPosition を複数渡すと、要素の画面位置とオーバーレイ表示がイイカンジになるように実際に表示に使用される ConnectedPosition が変化します。
ConnectedPosition がもつプロパティです。 originX
orignY
overlayX
overlayX
の4つを指定します。
プロパティ名 | 必須 | |
---|---|---|
originX | x | 相対位置の起点となる要素の X 座標の位置。 start center end |
originY | x | 相対位置の起点となる要素の Y 座標の位置。 top center bottom |
overlayX | x | オーバーレイの起点 X 座標の位置。 start center end |
overlayY | x | オーバーレイの起点 Y 座標の位置。 top center bottom |
weight | - | |
offsetX | - | |
offsetY | - | |
panelClass | - |
まずは起点となるボタンに対して中央下に表示してみます。 ConnectedPosition には { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top' }
を使用します。
showOverlay(origin: ElementRef) { let positionStrategy: FlexibleConnectedPositionStrategy = this._overlay.position().flexibleConnectedTo(origin); positionStrategy = positionStrategy .withPositions([{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top' }]); const config: OverlayConfig = { positionStrategy, width: 'auto', height: 'auto', }; const overlayRef: OverlayRef = this._overlay.create(config); const componentPortal: ComponentPortal<OverlayContentComponent> = new ComponentPortal(OverlayContentComponent); const componentRef: ComponentRef<OverlayContentComponent> = overlayRef.attach(componentPortal); }
続いてボタンの横に表示してみます。ボタンの左側に表示するには ConnectedPosition に { originX: 'start', originY: 'center', overlayX: 'end', overlayY: 'center' }
を指定します。
最後に、複数の ConnectedPosition を指定してみます。 CDK のソースコード中にはこんなコメントがありますので、複数を指定した際はきっとイイカンジに表示してくれるでしょう。
Go through each of the preferred positions looking for a good fit.
If a good fit is found, it will be applied immediately.
ではボタンの下またはボタンの上に表示される ConnectedPosition を指定し、実際の挙動を確認します。指定順はボタン下が1番目、ボタン上が2番目です。
showOverlay(origin: ElementRef) { let positionStrategy: FlexibleConnectedPositionStrategy = this._overlay.position().flexibleConnectedTo(origin); positionStrategy = positionStrategy.withPositions([ { originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top' }, { originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom' }, ]); const config: OverlayConfig = { positionStrategy, width: 'auto', height: 'auto', }; const overlayRef: OverlayRef = this._overlay.create(config); const componentPortal: ComponentPortal<OverlayContentComponent> = new ComponentPortal(OverlayContentComponent); const componentRef: ComponentRef<OverlayContentComponent> = overlayRef.attach(componentPortal); }
画面の複数の位置にボタンを設置してオーバーレイを表示した結果です。画面上、および中央に設置したボタンからは下に、画面下に設置したボタンからは上にオーバーレイが表示されています。表示されるオーバーレイと余白の大きさから、指定した ConnectedPosition のうち丁度良い物を使用してくれているようです。