いい感じに
This commit is contained in:
		
							
								
								
									
										57
									
								
								src/web/app/desktop/scripts/scroll-follower.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/web/app/desktop/scripts/scroll-follower.ts
									
									
									
									
									
										Normal 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`; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -184,6 +184,7 @@ | ||||
| 		import uuid from 'uuid'; | ||||
| 		import Sortable from 'sortablejs'; | ||||
| 		import dialog from '../scripts/dialog'; | ||||
| 		import ScrollFollower from '../scripts/scroll-follower'; | ||||
|  | ||||
| 		this.mixin('i'); | ||||
| 		this.mixin('api'); | ||||
| @@ -242,11 +243,8 @@ | ||||
| 			} | ||||
|  | ||||
| 			if (!this.opts.customize) { | ||||
| 				this.containerTop = this.refs.main.getBoundingClientRect().top; | ||||
| 				this.headerHight = this.root.getBoundingClientRect().top; | ||||
|  | ||||
| 				window.addEventListener('scroll', this.followWidgets); | ||||
| 				window.addEventListener('resize', this.followWidgets); | ||||
| 				this.scrollFollowerLeft = new ScrollFollower(this.refs.left, this.root.getBoundingClientRect().top); | ||||
| 				this.scrollFollowerRight = new ScrollFollower(this.refs.right, this.root.getBoundingClientRect().top); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| @@ -256,8 +254,8 @@ | ||||
| 			}); | ||||
|  | ||||
| 			if (!this.opts.customize) { | ||||
| 				window.removeEventListener('scroll', this.followWidgets); | ||||
| 				window.removeEventListener('resize', this.followWidgets); | ||||
| 				this.scrollFollowerLeft.dispose(); | ||||
| 				this.scrollFollowerRight.dispose(); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
|   | ||||
| @@ -607,20 +607,24 @@ | ||||
|  | ||||
| <mk-user-home> | ||||
| 	<div> | ||||
| 		<mk-user-profile user={ user }/> | ||||
| 		<mk-user-photos user={ user }/> | ||||
| 		<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 ref="left"> | ||||
| 			<mk-user-profile user={ user }/> | ||||
| 			<mk-user-photos user={ user }/> | ||||
| 			<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> | ||||
| 	<main> | ||||
| 		<mk-post-detail if={ user.pinned_post } post={ user.pinned_post } compact={ true }/> | ||||
| 		<mk-user-timeline ref="tl" user={ user }/> | ||||
| 	</main> | ||||
| 	<div> | ||||
| 		<mk-calendar-widget warp={ warp } start={ new Date(user.created_at) }/> | ||||
| 		<mk-activity-widget user={ user }/> | ||||
| 		<mk-user-frequently-replied-users user={ user }/> | ||||
| 		<div class="nav"><mk-nav-links/></div> | ||||
| 		<div ref="right"> | ||||
| 			<mk-calendar-widget warp={ warp } start={ new Date(user.created_at) }/> | ||||
| 			<mk-activity-widget user={ user }/> | ||||
| 			<mk-user-frequently-replied-users user={ user }/> | ||||
| 			<div class="nav"><mk-nav-links/></div> | ||||
| 		</div> | ||||
| 	</div> | ||||
| 	<style> | ||||
| 		:scope | ||||
| @@ -629,7 +633,8 @@ | ||||
| 			margin 0 auto | ||||
| 			max-width 1200px | ||||
|  | ||||
| 			> * | ||||
| 			> main | ||||
| 			> div > div | ||||
| 				> *:not(:last-child) | ||||
| 					margin-bottom 16px | ||||
|  | ||||
| @@ -645,7 +650,7 @@ | ||||
| 				width 275px | ||||
| 				margin 0 | ||||
|  | ||||
| 				&:first-child | ||||
| 				&:first-child > div | ||||
| 					padding 16px 0 16px 16px | ||||
|  | ||||
| 					> p | ||||
| @@ -656,7 +661,7 @@ | ||||
| 						font-size 0.8em | ||||
| 						color #aaa | ||||
|  | ||||
| 				&:last-child | ||||
| 				&:last-child > div | ||||
| 					padding 16px 16px 16px 0 | ||||
|  | ||||
| 					> .nav | ||||
| @@ -675,6 +680,8 @@ | ||||
|  | ||||
| 	</style> | ||||
| 	<script> | ||||
| 		import ScrollFollower from '../scripts/scroll-follower'; | ||||
|  | ||||
| 		this.mixin('i'); | ||||
|  | ||||
| 		this.user = this.opts.user; | ||||
| @@ -683,6 +690,14 @@ | ||||
| 			this.refs.tl.on('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 => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo