1. 程式人生 > >Angular 實現Bootstrap ScrollSpy控制元件

Angular 實現Bootstrap ScrollSpy控制元件

  Bootstap是基於JQuery開發,Angular中不支援Bootstrap相關事件邏輯。本文基於Typecript開發了一個Angular可用的ScrollSpy控制元件。Scrollspy控制元件主要實現了左側導航以及右側正文之間的聯動和切換。所以,

  此元件主要解決兩個問題:

  (1)點選左側導航列表,右側正文能夠跟隨切換的焦點定位到具體的段落,即新增導航點選事件

  (2)右側正文滾動時,左側導航列表可以根據正文滾動的位置自動定位到,該段落所屬的目錄索引上。即新增正文滾動事件。

  1. 程式碼結構

 

1.元件程式碼

滾動監聽指令:

  監聽滾動事件,並且獲取當前滾動焦點的元素值(element)然後切換當前導航樹位置(postion),觸發positionchange事件函式。

//scrollspy.direct.ts
import { Directive, Injectable, Input, EventEmitter, Output, ElementRef, HostListener } from '@angular/core';

@Directive({
    selector: '[NgScrollSpy]'
})
export class NgScrollSpyDirective {
   
    @Output() public positonChange = new EventEmitter<string>();
    private currentposition: string;
    private Tags 
= ['DIV']; constructor(private _el: ElementRef) {} @HostListener('scroll', ['$event']) //監聽正文滾動事件 onScroll(event: any) { let position: string; const children = this._el.nativeElement.children; const scrollTop = event.target.scrollTop; const parentOffset = event.target.offsetTop;
for (let i = 0; i < children.length; i++) { const element = children[i]; if (this.Tags.some(tag => tag === element.tagName)) { if ((element.offsetTop - parentOffset) <= scrollTop) { position = element.id; } } } if (position !== this.currentposition) { this.currentposition = position; this.positonChange.emit(this.currentposition); } } }

  通過scrollTo(position :string)函式獲取左側導航樹點選位置,並操作DOM定位到對應位置。

  通過onPositionChange(position: string)函式獲取右側正文的滾動位置。

//ngscrollspy.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-ngscrollspy',
  templateUrl: './ngscrollspy.component.html',
  styleUrls: ['./ngscrollspy.component.css']
})
export class NgscrollspyComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  currentPostion = 'Phase1';

  // 正文滾動事件 設定當前滾動位置,供NgScrollSpyDirective使用
  onPositionChange(position: string) {
    this.currentPostion = position;
  }

  // 導航點選事件  查詢目錄節點別切換到節點
  scrollTo(position :string) {
    document.querySelector('#' + position)
    .scrollIntoView();
  }
}

html

//ngscrollspy.component.html
<div class="container">
  <div class="row">
      <div class="col-xl-6 col-lg-6 col-md-6 col-sm-6">
        <h2>導航</h2>
        <div (click)="scrollTo('phase1')">段落1
          <ng-container *ngIf="currentPostion==='phase1'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase2')">段落2
          <ng-container *ngIf="currentPostion==='phase2'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase3')">段落3
          <ng-container *ngIf="currentPostion==='phase3'">++</ng-container>
        </div>
        <div (click)="scrollTo('phase4')">段落4
          <ng-container *ngIf="currentPostion==='phase4'">++</ng-container>
        </div>
      </div>
      <div class="col-xl-6 col-lg-6 col-md-6 col-sm-6">
        <div id="phases" NgScrollSpy (positonChange)="onPositionChange($event)" style="height:150px;overflow-y: scroll;">
          <div id="phase1">
            <h2 style="margin:0">段落 1</h2>
            <PhaseText></PhaseText>
          </div>
          <div id="phase2">
            <h1>段落 2</h1>
            <PhaseText></PhaseText>
          </div>
          <div id="phase3">
            <h1>段落 3</h1>
            <PhaseText></PhaseText>
          </div>
          <div id="phase4">
            <h1>段落 4</h1>
            <PhaseText></PhaseText>
          </div>
        </div>
      </div>
  </div>
</div>

詳細程式碼可以訪問github倉庫

https://github.com/OshimaYong/AngularDemo