Angular 组件的吸顶效果

 一些说明可以参考Angular获取DOM元素_EchoDSun的博客-CSDN博客

写法参考:js实现html页面滚动条向下拉到一定的程度时,某个div就固定在顶部,向上拉时返回原位置。_毅个混蛋的专栏-CSDN博客_页面滚动时某个div固定

组件本来是随着页面一起上划的,到了页面顶端以后,组件固定的页面顶端,示例代码:

html:

<div class="home-page">
  <mat-card class="example-card">
    <mat-card-header>
      <div mat-card-avatar class="example-header-image"></div>
      <mat-card-title>Shiba Inu</mat-card-title>
      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
    <mat-card-content>
      <p>
        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
        bred for hunting.
      </p>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button>LIKE</button>
      <button mat-button>SHARE</button>
    </mat-card-actions>
  </mat-card>
  <!-- 固定的card -->
  <mat-card #fixedCard [ngClass]="fixCard()">固定的card</mat-card>
  <!-- 固定的card -->
  <mat-card class="example-card">
    <mat-card-header>
      <div mat-card-avatar class="example-header-image"></div>
      <mat-card-title>Shiba Inu</mat-card-title>
      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
    <mat-card-content>
      <p>
        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
        bred for hunting.
      </p>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button>LIKE</button>
      <button mat-button>SHARE</button>
    </mat-card-actions>
  </mat-card>
  <mat-card class="example-card">
    <mat-card-header>
      <div mat-card-avatar class="example-header-image"></div>
      <mat-card-title>Shiba Inu</mat-card-title>
      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
    <mat-card-content>
      <p>
        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
        bred for hunting.
      </p>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button>LIKE</button>
      <button mat-button>SHARE</button>
    </mat-card-actions>
  </mat-card>
  <mat-card class="example-card">
    <mat-card-header>
      <div mat-card-avatar class="example-header-image"></div>
      <mat-card-title>Shiba Inu</mat-card-title>
      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
    <mat-card-content>
      <p>
        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
        bred for hunting.
      </p>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button>LIKE</button>
      <button mat-button>SHARE</button>
    </mat-card-actions>
  </mat-card>
  <mat-card>card 1</mat-card>
  <mat-card>card 1</mat-card>
  <mat-card>card 1</mat-card>
</div>

TS:

import { AfterViewInit, Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core';
import { fromEvent } from 'rxjs';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit, AfterViewInit {

  @ViewChild('fixedCard', { read: ElementRef })
  fixedCard!: ElementRef;

  subscribeScoll: any;
  // 当前位置距离最顶端的距离--监听的是page的移动
  pageTop: number = 0;
  elementTop: number = 0;
  originalElementTop: number = 0;

  constructor() { }

  ngOnInit(): void {

  }
  ngAfterViewInit(): void {
    // 在渲染完成以后,监听页面滚动
    this.subscribeScoll = fromEvent(window, 'scroll')
      .subscribe((event) => {
        this.onWindowScroll();//调用
      });
  }
  onWindowScroll() {
    this.pageTop = this.scollPostion().top;
    this.elementTop = this.getElementViewTop(this.fixedCard);
  }

  // 监听网页滚动
  scollPostion() {
    var top = 0;
    var left = 0;
    var width = 0;
    var height = 0;
    if (document.documentElement && document.documentElement.scrollTop) {
      top = document.documentElement.scrollTop;
      left = document.documentElement.scrollLeft;
      width = document.documentElement.scrollWidth;
      height = document.documentElement.scrollHeight;
    } else if (document.body) {
      top = document.body.scrollTop;
      left = document.body.scrollLeft;
      width = document.body.scrollWidth;
      height = document.body.scrollHeight;
    }
    return {
      top: top,
      left: left,
      width: width,
      height: height
    };
  }

  // 获取组件距离顶部的距离
  getElementViewTop(element: any) {
    var elementTop = element.nativeElement.offsetTop;
    return elementTop;
  }

  fixCard() {
    var result = '';
    if (this.elementTop != 0 && this.elementTop - this.pageTop <= 10) {
      // 当设置top的时候,会修改组件的位置
      result = 'fixed';
    } else {
      // 记录原始的位置,刚开始初始化的时候,距离为0,滚动以后改为初始位置
      // 因此记录下初始位置,以便后续复原
      if (this.elementTop != 0) {
        this.originalElementTop = this.elementTop;
      }
      result = '';
    }
    if (this.pageTop < this.originalElementTop-100) {
      result =  '';
    }
    return result;

  }


}

css样式:

.home-page {
  background-color: #e9e9e9;
}
.fixed {
  width: 100%;
  position: fixed;
  top:10px;
  left:0;
  z-index: 2;
}

.float {
  background-color: aqua;
}
.example-card {
  max-width: 400px;
  // background-color: white;
}

.example-header-image {
  background-image: url('https://material.angular.io/assets/img/examples/shiba1.jpg');
  background-size: cover;
}

还有另外一种写法,核心的内容还是比较页面上划的距离和元素上划的距离,处理方法上换成了使用Renderer2 的 addClass() 方法来设定元素的样式,写起来更加简便。

参考:

只要修改Ts文件即可:Angular2-6 实现吸顶效果指令_可乐会唱歌的博客-CSDN博客

import { AfterViewInit, Component, ElementRef, HostListener, OnInit, Renderer2, ViewChild } from '@angular/core';
import { fromEvent } from 'rxjs';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit, AfterViewInit {

  // 元素距离顶部的原始距离
  toTop: number = 0;
  // 吸顶元素
  @ViewChild('fixedCard', { read: ElementRef })
  toTopElement: any;

  constructor(private renderer2: Renderer2) {
  }

  ngAfterViewInit(): void {
    this.toTop = this.toTopElement.nativeElement.offsetTop;
    fromEvent(window, 'scroll').subscribe((event) => {
      if (document.documentElement.scrollTop >= this.toTop) {
        this.renderer2.addClass(this.toTopElement.nativeElement, 'fixed');
      } else {
        this.renderer2.removeClass(this.toTopElement.nativeElement, 'fixed');
      }
    });
  }
  ngOnInit(): void {

  }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值