環境
TypeScriptベースのフレームワークであるAngularと、iOS/AndroidのハイブリッドモバイルアプリケーションのフレームワークであるIonicを使用しています。
- "rxjs": "~6.6.0",
- "@angular/fire": "^6.1.4"
- "firebase": "^8.3.1"
- "semver": "^7.3.5"
ionic info
コマンドの実行結果
$ ionic info Ionic: Ionic CLI : 6.11.8 (/usr/local/lib/node_modules/@ionic/cli) Ionic Framework : @ionic/angular 5.6.0 @angular-devkit/build-angular : 0.1101.4 @angular-devkit/schematics : 11.1.4 @angular/cli : 11.1.4 @ionic/angular-toolkit : 3.1.0 Cordova: Cordova CLI : 8.0.0 Cordova Platforms : none Cordova Plugins : no whitelisted plugins (1 plugins total) Utility: cordova-res : not installed native-run : not installed System: ios-deploy : 1.9.2 ios-sim : 6.1.2 NodeJS : v12.13.1 (/usr/local/bin/node) npm : 6.14.12 OS : macOS Catalina Xcode : Xcode 12.0.1 Build version 12A7300
Alert/Modal同士でz-indexを交換する
Ionicのアラート/モーダルはz-index
を交換することができるため、アラート/モーダル同士の奥行きの位置を入れ替えることができます。
/** * アラート/モーダルの奥行きの位置を交換する * * @private * @memberof VersionCheckService */ private swapPositions(): void { [this.versionUpAlert.style.zIndex, this.maintenanceAlert.style.zIndex] = [ this.maintenanceAlert.style.zIndex, this.versionUpAlert.style.zIndex, ]; }
例えば、下記の画像では、バージョンアップのアラートとメンテナンスのアラートが重なって表示されていて、あとに表示されたバージョンアップのアラートが前面に表示されています。
この状態で先ほど作成したswapPositions()
を呼び出すと、アラートの位置が交換されて、メンテナンスのアラートが前面に表示されます。(隠れて見えませんが背後にバージョンアップのアラートが表示されています)
該当コードの全体像は下記となります。
import { Injectable } from '@angular/core'; import { AngularFireDatabase } from '@angular/fire/database'; import { Observable } from 'rxjs'; import { Maintenance } from '../model/maintenance.model'; import { Version } from '../model/version.model'; import * as semver from 'semver'; import { AlertController } from '@ionic/angular'; @Injectable({ providedIn: 'root', }) export class VersionCheckService { // このアプリのバージョン private readonly appVersion = '1.0.0'; private maintenance$: Observable<Maintenance>; private version$: Observable<Version>; private maintenanceAlert: HTMLIonAlertElement; private versionUpAlert: HTMLIonAlertElement; constructor( private db: AngularFireDatabase, private alertController: AlertController ) {} /** * 初期設定 * * @memberof VersionCheckService */ public initSetting(): void { // Realtime Databaseからデータを取得 this.maintenance$ = this.db .object<Maintenance>('maintenance') .valueChanges(); this.version$ = this.db.object<Version>('version').valueChanges(); this.maintenance$.subscribe( async (maintenance: Maintenance) => await this.checkMaintenance(maintenance) ); this.version$.subscribe( async (version: Version) => await this.checkVersion(this.appVersion, version) ); } /** * メンテナンスポップアップを表示する。 * * @private * @param {Maintenance} maintenance * @returns {Promise<void>} * @memberof VersionCheckService */ private async checkMaintenance(maintenance: Maintenance): Promise<void> { if (!maintenance) { return; } if (!maintenance.maintenanceFlg) { // メンテナンスフラグがOFFだったら処理を中断する if (this.maintenanceAlert) { // メンテナンスメッセージが開かれている場合は閉じる await this.maintenanceAlert.dismiss(); this.maintenanceAlert = undefined; } return; } // メンテナンスメッセージを表示する this.maintenanceAlert = await this.alertController.create({ header: maintenance.title, message: maintenance.message, backdropDismiss: false, // 背景をクリックしても閉じない }); await this.maintenanceAlert.present(); } /** * 強制バージョンアップメッセージを表示する。 * * @private * @param {string} appVersion * @param {Version} version * @returns * @memberof VersionCheckService */ private async checkVersion(appVersion: string, version: Version) { if (!version || !version.minimumVersion) { return; } if (semver.gte(appVersion, version.minimumVersion)) { // 最低バージョンよりもアプリのバージョンが高かったら処理を中断する if (this.versionUpAlert) { // 強制バージョンアップメッセージが開かれている場合は閉じる await this.versionUpAlert.dismiss(); this.versionUpAlert = undefined; } return; } // 強制バージョンアップメッセージを表示する this.versionUpAlert = await this.alertController.create({ header: version.title, message: version.message, backdropDismiss: false, // 背景をクリックしても閉じない }); await this.versionUpAlert.present(); } /** * アラート/モーダルの奥行きの位置を交換する * * @private * @memberof VersionCheckService */ private swapPositions(): void { [this.versionUpAlert.style.zIndex, this.maintenanceAlert.style.zIndex] = [ this.maintenanceAlert.style.zIndex, this.versionUpAlert.style.zIndex, ]; } }
Alert/Modalのz-indexを参照できるのはなぜか?
そもそも、なぜIonicのアラート/モーダルで、z-index
を参照・更新できるのか?という点について説明します。
Ionicのアラートの型はHTMLIonAlertElement
、モーダルの型はHTMLIonModalElement
に設定されています。
HTMLIonAlertElement
とHTMLIonModalElement
はHTMLElement
を継承しているため、HTMLElement.style
によって、z-index
含むスタイル関連のメソッドやプロパティの情報を取得することができる、というわけです。
おわりに
IonicのコンポーネントってStencilで書かれているWeb Componentsなんですね......知らなかった。コントリビュートしやすそう
参考サイト
ElementCSSInlineStyle.style - Web API | MDN
Stencilを使ってWebComponentを作ってみる - Qiita