いい感じに

This commit is contained in:
syuilo 2017-11-19 00:04:40 +09:00
parent 6ed694a3f5
commit fda4003ba4
3 changed files with 88 additions and 18 deletions

View file

@ -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`;
}
}
}

View file

@ -184,6 +184,7 @@
import uuid from 'uuid'; import uuid from 'uuid';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
import dialog from '../scripts/dialog'; import dialog from '../scripts/dialog';
import ScrollFollower from '../scripts/scroll-follower';
this.mixin('i'); this.mixin('i');
this.mixin('api'); this.mixin('api');
@ -242,11 +243,8 @@
} }
if (!this.opts.customize) { if (!this.opts.customize) {
this.containerTop = this.refs.main.getBoundingClientRect().top; this.scrollFollowerLeft = new ScrollFollower(this.refs.left, this.root.getBoundingClientRect().top);
this.headerHight = this.root.getBoundingClientRect().top; this.scrollFollowerRight = new ScrollFollower(this.refs.right, this.root.getBoundingClientRect().top);
window.addEventListener('scroll', this.followWidgets);
window.addEventListener('resize', this.followWidgets);
} }
}); });
@ -256,8 +254,8 @@
}); });
if (!this.opts.customize) { if (!this.opts.customize) {
window.removeEventListener('scroll', this.followWidgets); this.scrollFollowerLeft.dispose();
window.removeEventListener('resize', this.followWidgets); this.scrollFollowerRight.dispose();
} }
}); });

View file

@ -607,20 +607,24 @@
<mk-user-home> <mk-user-home>
<div> <div>
<mk-user-profile user={ user }/> <div ref="left">
<mk-user-photos user={ user }/> <mk-user-profile user={ user }/>
<mk-user-followers-you-know if={ SIGNIN && I.id !== user.id } user={ user }/> <mk-user-photos user={ user }/>
<p>%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time time={ user.last_used_at }/></b></p> <mk-user-followers-you-know if={ SIGNIN && I.id !== user.id } user={ user }/>
<p>%i18n:desktop.tags.mk-user.last-used-at%: <b><mk-time time={ user.last_used_at }/></b></p>
</div>
</div> </div>
<main> <main>
<mk-post-detail if={ user.pinned_post } post={ user.pinned_post } compact={ true }/> <mk-post-detail if={ user.pinned_post } post={ user.pinned_post } compact={ true }/>
<mk-user-timeline ref="tl" user={ user }/> <mk-user-timeline ref="tl" user={ user }/>
</main> </main>
<div> <div>
<mk-calendar-widget warp={ warp } start={ new Date(user.created_at) }/> <div ref="right">
<mk-activity-widget user={ user }/> <mk-calendar-widget warp={ warp } start={ new Date(user.created_at) }/>
<mk-user-frequently-replied-users user={ user }/> <mk-activity-widget user={ user }/>
<div class="nav"><mk-nav-links/></div> <mk-user-frequently-replied-users user={ user }/>
<div class="nav"><mk-nav-links/></div>
</div>
</div> </div>
<style> <style>
:scope :scope
@ -629,7 +633,8 @@
margin 0 auto margin 0 auto
max-width 1200px max-width 1200px
> * > main
> div > div
> *:not(:last-child) > *:not(:last-child)
margin-bottom 16px margin-bottom 16px
@ -645,7 +650,7 @@
width 275px width 275px
margin 0 margin 0
&:first-child &:first-child > div
padding 16px 0 16px 16px padding 16px 0 16px 16px
> p > p
@ -656,7 +661,7 @@
font-size 0.8em font-size 0.8em
color #aaa color #aaa
&:last-child &:last-child > div
padding 16px 16px 16px 0 padding 16px 16px 16px 0
> .nav > .nav
@ -675,6 +680,8 @@
</style> </style>
<script> <script>
import ScrollFollower from '../scripts/scroll-follower';
this.mixin('i'); this.mixin('i');
this.user = this.opts.user; this.user = this.opts.user;
@ -683,6 +690,14 @@
this.refs.tl.on('loaded', () => { this.refs.tl.on('loaded', () => {
this.trigger('loaded'); this.trigger('loaded');
}); });
this.scrollFollowerLeft = new ScrollFollower(this.refs.left, this.parent.root.getBoundingClientRect().top);
this.scrollFollowerRight = new ScrollFollower(this.refs.right, this.parent.root.getBoundingClientRect().top);
});
this.on('unmount', () => {
this.scrollFollowerLeft.dispose();
this.scrollFollowerRight.dispose();
}); });
this.warp = date => { this.warp = date => {