通過Directive實(shí)現(xiàn)入場動(dòng)畫
創(chuàng)建指令并引入所需
import { Directive, ElementRef, HostListener, HostBinding } from '@angular/core';
@Directive({
selector: '[VisualIn]'
})
export class VisualInDirective {
finished: boolean;
constructor(
private el: ElementRef,
) {
this.finished = false;
}
使用HostListener為宿主元素添加window監(jiān)聽
// scroll 監(jiān)聽
@HostListener('window: scroll') elementShowIn() {}
// load 監(jiān)聽
@HostListener('window: load') elementLoadIn() {}
使用HostBinding為宿主元素綁定動(dòng)畫類名
@HostBinding('class.bounceInRight') isAnimate: boolean;
@keyframes bounceInRight {
from, 60%, 75%, 90%, to {
animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
from {
opacity: 0;
transform: translate3d(3000px, 0, 0);
}
60% {
opacity: 1;
transform: translate3d(-25px, 0, 0);
}
75% {
transform: translate3d(10px, 0, 0);
}
90% {
transform: translate3d(-5px, 0, 0);
}
to {
transform: none;
}
}
.bounceInRight {
animation-duration: .5s;
animation-fill-mode: both;
animation-name: bounceInRight;
}
獲取元素相對于body標(biāo)簽的高度
documentElement.offsetTop會(huì)獲取標(biāo)簽到offsetParent的相對偏移高度
默認(rèn)的offsetParent返回一個(gè)指向最近的包含該元素的定位元素
如果沒有定位元素則返回最近的table, table sell或根元素
因此我們需要遍歷父級元素,從基元素獲取所有父級定位元素,并累加相對偏移高度
private getOffsetBodyTop(el) {
let offsetBodyTop = 0;
function _getOffsetBodyTop(el) {
offsetBodyTop += el.offsetTop;
if (el.offsetParent.tagName != 'BODY') {
return _getOffsetBodyTop(el.offsetParent);
} else if (el.offsetParent.tagName == 'BODY') {
return false;
}
}
_getOffsetBodyTop(el);
return offsetBodyTop;
}
定位元素進(jìn)入窗口的高度,并執(zhí)行動(dòng)畫
當(dāng) 元素相對根元素的偏移高度 - 當(dāng)前滾動(dòng)高度 - 窗口高度 < 0 時(shí),元素開始進(jìn)入頁面
此時(shí)執(zhí)行動(dòng)畫
private showAnimate(): Promise<any> {
return new Promise((resolve, reject) => {
const offsetBodyTop = this.getOffsetBodyTop(this.el.nativeElement); // 元素距離頂部高度
let _dst: number; // 滾動(dòng)高度
if (this.myPhone() === 'iPhone') {
_dst = document.body.scrollTop;
} else {
_dst = document.documentElement.scrollTop;
}
const _wsh = window.innerHeight; // 屏幕高度
if (offsetBodyTop - _dst - _wsh < -30) {
if (this.finished) {
resolve('isFinished');
} else {
this.isAnimate = true;
this.finished = true;
resolve('show');
}
} else {
resolve('noShow');
}
});
}
private myPhone() {
const userAgent = navigator.userAgent;
if (userAgent.indexOf('iPhone') > -1) {
return 'iPhone';
}
修改HostListener
@HostListener('window:scroll') elementShowIn() {
this.showAnimate().then(res => {});
}
@HostListener('window:load') elementLoadIn() {
this.showAnimate().then(res => {});
}
添加指令
在你需要的元素標(biāo)簽上添加
<div VisualIn></div>