Cara membuat panduan langkah demi langkah dari aplikasi Anda (jika proyek Anda ada di Angular)

Halo semuanya.

Belum lama ini, sprint lain berakhir, dan saya punya waktu untuk membuat bagi pengguna saya bukan yang paling diperlukan, tetapi pada saat yang sama fitur menarik - panduan interaktif untuk bekerja dengan aplikasi kita.

Ada banyak solusi siap pakai di Internet - semuanya tentu cocok untuk tugas ini, tetapi kita akan melihat bagaimana melakukannya sendiri.

Arsitektur


Arsitektur komponen ini cukup sederhana.

Kami memiliki elemen penting di pohon DOM yang ingin kami beri tahu pengguna sesuatu, misalnya tombol.

Kita perlu menggambar lapisan yang gelap di sekitar elemen ini, mengalihkan perhatian padanya.
Anda perlu menggambar kartu di sebelah elemen ini dengan pesan penting.

gambar

Untuk mengatasi masalah ini, @ angular / cdk akan membantu kami . Dalam artikel terakhir saya , saya sudah memuji @ angular / material, yang tergantung pada CDK, bagi saya itu masih menjadi contoh komponen berkualitas tinggi yang dibuat menggunakan semua fitur dari kerangka kerja.

Komponen seperti menu, kotak dialog, bilah alat dari pustaka @ angular / materialdibuat menggunakan komponen dari CDK - Overlay.

Antarmuka sederhana dari komponen ini memungkinkan Anda untuk dengan cepat membuat layer di atas aplikasi kami, yang secara mandiri akan beradaptasi dengan perubahan ukuran layar dan pengguliran. Seperti yang sudah Anda pahami, menggunakan komponen ini untuk menyelesaikan masalah kami menjadi sangat sederhana.

Pertama, instal perpustakaan

npm i @angular/cdk @angular/material -S

Setelah instalasi, jangan lupa untuk menambahkan gaya ke style.css

@import '~@angular/cdk/overlay-prebuilt.css';
@import '~@angular/material/prebuilt-themes/deeppurple-amber.css';

Sekarang buat modul baru di proyek kami:

ng generate library intro-lib

Dan segera buat templat untuk arahan:

ng generate directive intro-trigger

Arahan ini akan bertindak sebagai pemicu untuk panduan kami di masa mendatang, akan mendengarkan klik pada suatu elemen dan menyorotnya pada halaman.

@Directive({
  selector: '[libIntroTrigger]'
})
export class IntroTriggerDirective {
  @Input() libIntroTrigger: string;

  constructor(private introLibService: IntroLibService, private elementRef: ElementRef) {}

  @HostListener('click') showGuideMessage(): void {
    this.introLibService.show$.emit([this.libIntroTrigger, this.elementRef]);
  }
}

Di sini kita beralih ke layanan yang juga dihasilkan ketika perpustakaan dibuat, semua pekerjaan utama akan dilakukan olehnya.

Pertama, nyatakan properti baru dalam layanan

show$ = new EventEmitter<[string, ElementRef]>();

Seperti yang telah kita lihat nilai-nilai ini, arahan akan mengirimkan kepada kita, dalam array elemen pertama adalah deskripsi, dan yang kedua adalah elemen DOM yang kami jelaskan (saya memilih solusi ini untuk kesederhanaan misalnya).

@Injectable({
  providedIn: 'root'
})
export class IntroLibService {
  private overlayRef: OverlayRef;
  show$ = new EventEmitter<[string, ElementRef]>();

  constructor(private readonly overlay: Overlay, private readonly ngZone: NgZone, private readonly injector: Injector) {
    this.show$.subscribe(([description, elementRef]: [string, ElementRef]) => {
      this.attach(elementRef, description);
    });
  }
}

Perbarui perancang layanan dengan menambahkan langganan ke pembaruan dari EventEmitter, fungsi lampiran akan menerima pembaruan dan membuat lapisan.

Untuk membuat layer kita perlu Overlay, Injector dan NgZone.

Tindakan berikut dapat dibagi menjadi beberapa tahap:

  • Tutup hamparan saat ini (jika ada)
  • Buat PositionStrategy
  • Buat OverlayRef
  • Buat PortalInjector
  • Pasang komponen ke lapisan

Dengan poin pertama jelas, untuk ini kami telah mendeklarasikan properti dalam layanan. PositionStrategy - bertanggung jawab atas bagaimana layer kita akan diposisikan di pohon DOM.

Ada beberapa strategi yang sudah jadi:

  1. Strategi Posisi FleksibelKoneksi
  2. Strategi GlobalPosisi

Dengan kata-kata sederhana, kemudian

FlexibleConnectedPositionStrategy - akan mengikuti elemen tertentu dan, tergantung pada konfigurasi, itu akan menempel ketika mengubah ukuran browser atau gulir, contoh yang jelas dari penggunaan daftar drop-down, menu.

GlobalPositionStrategy - seperti namanya, itu dibuat secara global, tidak memerlukan elemen untuk bekerja, contoh penggunaan yang jelas adalah modal windows.

Tambahkan metode untuk membuat strategi jendela mengambang di sekitar elemen yang sedang diselidiki.

{
 ...
private getPositionStrategy(elementRef: ElementRef): PositionStrategy {
    return this.overlay
      .position()
      .flexibleConnectedTo(elementRef)
      .withViewportMargin(8) //     
      .withGrowAfterOpen(true) //           (, exspansion panel  )
      .withPositions([ //   ,            
        {
          originX: 'start',
          originY: 'bottom',
          overlayX: 'start',
          overlayY: 'top'
        },
        {
          originX: 'start',
          originY: 'top',
          overlayX: 'start',
          overlayY: 'bottom'
        },
        {
          originX: 'end',
          originY: 'bottom',
          overlayX: 'end',
          overlayY: 'top'
        },
        {
          originX: 'end',
          originY: 'top',
          overlayX: 'end',
          overlayY: 'bottom'
        }
      ]);
  }
...
}

Tambahkan metode untuk membuat OverlayRef

createOverlay(elementRef: ElementRef): OverlayRef {
    const config = new OverlayConfig({
      positionStrategy: this.getPositionStrategy(elementRef),
      scrollStrategy: this.overlay.scrollStrategies.reposition()
    });

    return this.overlay.create(config);
  }

Dan tambahkan metode untuk mengikat komponen kita ke layer:

  attach(elementRef: ElementRef, description: string): void {
    if (this.overlayRef && this.overlayRef.hasAttached()) {
      this.overlayRef.dispose();
    }

    this.overlayRef = this.createOverlay(elementRef);

    const dataRef = this.ngZone.run(
      () => new DataRef(this.overlay, this.injector, this.overlayRef, elementRef, description)
    ); //   ,      ,    ,  CD    -  

    const injector = new PortalInjector(this.injector, new WeakMap([[DATA_TOKEN, dataRef]]));

    dataRef.overlayRef.attach(new ComponentPortal(IntroLibComponent, null, injector));
  }

Beginilah tampilan komponen yang menampilkan pesan

@Component({
  selector: 'lib-intro-lib',
  template: `
    <mat-card>
      <mat-card-content> {{ data.description }}</mat-card-content>
    </mat-card>
  `,
  styles: ['mat-card {width: 300px; margin: 32px;}']
})
export class IntroLibComponent {
  constructor(@Inject(DATA_TOKEN) public data: DataRef) {}
}

Sudah diberitahu tentang semua yang dihasilkan dalam daftar, kecuali DataRef.

DataRef adalah kelas sederhana yang kami tambahkan ke injector untuk komponen, pada kenyataannya, untuk mentransfer data untuk rendering - misalnya, deskripsi.

Juga, di dalamnya saya memutuskan untuk menggambar layer lain untuk menggelapkan dan menyoroti elemen. Dalam hal ini, kita sudah akan menggunakan strategi pembuatan layer global.

export class DataRef {
  shadowOverlayRef: OverlayRef;

  constructor(
    private overlay: Overlay,
    private injector: Injector,
    public overlayRef: OverlayRef,
    public elementRef: ElementRef,
    public description: string
  ) {
    const config = new OverlayConfig({
      positionStrategy: this.overlay.position().global(),
      scrollStrategy: this.overlay.scrollStrategies.block()
    });

    this.shadowOverlayRef = this.overlay.create(config);

    this.shadowOverlayRef.attach(
      new ComponentPortal(
        ShadowOverlayComponent,
        null,
        new PortalInjector(this.injector, new WeakMap([[DATA_TOKEN, this.elementRef]]))
      )
    );
  }
}


ShadowOverlayComponent - menggambar komponen, dan dalam injektor menerima token yang sama, hanya dengan elemen di sekitar yang perlu Anda tekankan.

Bagaimana saya menerapkan ini, Anda dapat melihat di sumber di github , saya tidak ingin fokus pada ini secara terpisah.

Saya hanya akan mengatakan bahwa di sana saya menggambar layar penuh kanvas, menggambar bentuk di sekitar elemen, dan mengisi konteks dengan metode fill ('evenodd');

Total


Yang paling keren adalah bahwa @ angular / cdk / overlay memungkinkan kita untuk menggambar sebanyak yang kita mau. Mereka akan adaptif dan fleksibel. Kita tidak perlu khawatir tentang mengubah ukuran layar, atau elemen akan bergeser karena beberapa alasan alami, overlay akan memikirkannya untuk kita.

Kami memahami cara bekerja dengan lapisan, kami menyadari bahwa tugas membuat panduan langkah demi langkah tidaklah begitu sulit.

Anda dapat memodifikasi perpustakaan dengan menambahkan kemampuan untuk beralih antar elemen, keluar dari mode tampilan dan sejumlah kasus sudut lainnya.

Terimakasih atas perhatiannya.

Source: https://habr.com/ru/post/undefined/


All Articles