diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2017-11-19 00:04:40 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2017-11-19 00:04:40 +0900 |
| commit | fda4003ba4944f2e2d3bdd8a42f2ddc510aefa5c (patch) | |
| tree | 3ae9a3e3c4e36f019aead1f79159acf15d1bdd52 /src/web/app/desktop/scripts/scroll-follower.ts | |
| parent | Merge branch 'master' of https://github.com/syuilo/misskey (diff) | |
| download | sharkey-fda4003ba4944f2e2d3bdd8a42f2ddc510aefa5c.tar.gz sharkey-fda4003ba4944f2e2d3bdd8a42f2ddc510aefa5c.tar.bz2 sharkey-fda4003ba4944f2e2d3bdd8a42f2ddc510aefa5c.zip | |
いい感じに
Diffstat (limited to 'src/web/app/desktop/scripts/scroll-follower.ts')
| -rw-r--r-- | src/web/app/desktop/scripts/scroll-follower.ts | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/web/app/desktop/scripts/scroll-follower.ts b/src/web/app/desktop/scripts/scroll-follower.ts new file mode 100644 index 0000000000..e99f125cc0 --- /dev/null +++ b/src/web/app/desktop/scripts/scroll-follower.ts @@ -0,0 +1,57 @@ +/** + * 要素をスクロールに追従させる + */ +export default class ScrollFollower { + private follower: Element; + private containerTop: number; + private topPadding: number; + + constructor(follower: Element, topPadding: number) { + //#region + this.follow = this.follow.bind(this); + //#endregion + + this.follower = follower; + this.containerTop = follower.getBoundingClientRect().top; + this.topPadding = topPadding; + + window.addEventListener('scroll', this.follow); + window.addEventListener('resize', this.follow); + } + + /** + * 追従解除 + */ + public dispose() { + window.removeEventListener('scroll', this.follow); + window.removeEventListener('resize', this.follow); + } + + private follow() { + const windowBottom = window.scrollY + window.innerHeight; + const windowTop = window.scrollY + this.topPadding; + + const rect = this.follower.getBoundingClientRect(); + //const followerHeight = rect.height + this.containerTop; + const followerBottom = (rect.top + window.scrollY) + rect.height; + + // スクロールの上部(+余白)がフォロワーコンテナの上部よりも上方にある + if (window.scrollY + this.topPadding < this.containerTop) { + // フォロワーをコンテナの最上部に合わせる + (this.follower.parentNode as any).style.marginTop = '0px'; + return; + } + + // スクロールの下部がフォロワーの下部よりも下方にある かつ 表示領域の縦幅がフォロワーの縦幅よりも狭い + if (windowBottom > followerBottom && rect.height > (window.innerHeight - this.topPadding)) { + // フォロワーの下部をスクロール下部に合わせる + const top = (windowBottom - rect.height) - this.containerTop; + (this.follower.parentNode as any).style.marginTop = `${top}px`; + // スクロールの上部(+余白)がフォロワーの上部よりも上方にある または 表示領域の縦幅がフォロワーの縦幅よりも広い + } else if ((windowTop < rect.top + window.scrollY || rect.height < (window.innerHeight - this.topPadding))) { + // フォロワーの上部をスクロール上部(+余白)に合わせる + const top = windowTop - this.containerTop; + (this.follower.parentNode as any).style.marginTop = `${top}px`; + } + } +} |