This commit is contained in:
tamaina 2022-02-02 21:13:19 +09:00
parent b88fc1fb4e
commit 99d8172ae5
3 changed files with 23 additions and 20 deletions

View file

@ -287,7 +287,7 @@ onDeactivated(() => {
}); });
function toBottom() { function toBottom() {
if (scrollableElement) scrollToBottom(scrollableElement); scrollToBottom(contentEl);
} }
onMounted(() => { onMounted(() => {

View file

@ -49,7 +49,7 @@ import XList from '@/components/date-separated-list.vue';
import MkPagination, { Paging } from '@/components/ui/pagination.vue'; import MkPagination, { Paging } from '@/components/ui/pagination.vue';
import XMessage from './messaging-room.message.vue'; import XMessage from './messaging-room.message.vue';
import XForm from './messaging-room.form.vue'; import XForm from './messaging-room.form.vue';
import { isBottom, onScrollBottom, scroll } from '@/scripts/scroll'; import { isBottom, onScrollBottom, scrollToBottom } from '@/scripts/scroll';
import * as os from '@/os'; import * as os from '@/os';
import { stream } from '@/stream'; import { stream } from '@/stream';
import * as sound from '@/scripts/sound'; import * as sound from '@/scripts/sound';
@ -134,7 +134,7 @@ async function fetch() {
nextTick(() => { nextTick(() => {
pagingComponent.inited.then(() => { pagingComponent.inited.then(() => {
scrollToBottom(); thisScrollToBottom();
}); });
window.setTimeout(() => { window.setTimeout(() => {
fetching = false fetching = false
@ -194,7 +194,7 @@ function onMessage(message) {
if (_isBottom) { if (_isBottom) {
// Scroll to bottom // Scroll to bottom
nextTick(() => { nextTick(() => {
scrollToBottom(); thisScrollToBottom();
}); });
} else if (message.userId != $i?.id) { } else if (message.userId != $i?.id) {
// Notify // Notify
@ -234,13 +234,13 @@ function onDeleted(id) {
} }
} }
function scrollToBottom() { function thisScrollToBottom() {
scroll(rootEl, { top: rootEl.scrollHeight || 999999, behavior: "smooth" }); scrollToBottom($$(rootEl).value, { behavior: "smooth" });
} }
function onIndicatorClick() { function onIndicatorClick() {
showIndicator = false; showIndicator = false;
scrollToBottom(); thisScrollToBottom();
} }
function notifyNewMessage() { function notifyNewMessage() {

View file

@ -1,5 +1,3 @@
type ScrollBehavior = 'auto' | 'smooth' | 'instant';
export function getScrollContainer(el: HTMLElement | null): HTMLElement | null { export function getScrollContainer(el: HTMLElement | null): HTMLElement | null {
if (el == null || el.tagName === 'HTML') return null; if (el == null || el.tagName === 'HTML') return null;
const overflow = window.getComputedStyle(el).getPropertyValue('overflow'); const overflow = window.getComputedStyle(el).getPropertyValue('overflow');
@ -19,7 +17,7 @@ export function getScrollPosition(el: HTMLElement | null): number {
return container == null ? window.scrollY : container.scrollTop; return container == null ? window.scrollY : container.scrollTop;
} }
export function isTopVisible(el: HTMLElement | null): boolean { export function isTopVisible(el: HTMLElement): boolean {
const scrollTop = getScrollPosition(el); const scrollTop = getScrollPosition(el);
const topPosition = el.offsetTop; // TODO: container内でのelの相対位置を取得できればより正確になる const topPosition = el.offsetTop; // TODO: container内でのelの相対位置を取得できればより正確になる
@ -32,10 +30,12 @@ export function onScrollTop(el: HTMLElement, cb) {
if (!document.body.contains(el)) return; if (!document.body.contains(el)) return;
if (isTopVisible(el)) { if (isTopVisible(el)) {
cb(); cb();
container.removeEventListener('scroll', onScroll); removeListener();
} }
}; };
function removeListener() { container.removeEventListener('scroll', onScroll) }
container.addEventListener('scroll', onScroll, { passive: true }); container.addEventListener('scroll', onScroll, { passive: true });
return removeListener;
} }
export function onScrollBottom(el: HTMLElement, cb) { export function onScrollBottom(el: HTMLElement, cb) {
@ -45,17 +45,15 @@ export function onScrollBottom(el: HTMLElement, cb) {
if (!document.body.contains(el)) return; if (!document.body.contains(el)) return;
if (isBottom(el, 1, container)) { if (isBottom(el, 1, container)) {
cb(); cb();
containerOrWindow.removeEventListener('scroll', onScroll); removeListener();
} }
}; };
function removeListener() { containerOrWindow.removeEventListener('scroll', onScroll) }
containerOrWindow.addEventListener('scroll', onScroll, { passive: true }); containerOrWindow.addEventListener('scroll', onScroll, { passive: true });
return removeListener;
} }
export function scroll(el: HTMLElement, options: { export function scroll(el: HTMLElement, options: ScrollToOptions | undefined) {
top?: number;
left?: number;
behavior?: ScrollBehavior;
}) {
const container = getScrollContainer(el); const container = getScrollContainer(el);
if (container == null) { if (container == null) {
window.scroll(options); window.scroll(options);
@ -75,11 +73,16 @@ export function scrollToTop(el: HTMLElement, options: { behavior?: ScrollBehavio
/** /**
* Scroll to Bottom * Scroll to Bottom
* @param el Scroll container element * @param el Content element
* @param options Scroll options * @param options Scroll options
* @param container Scroll container element
*/ */
export function scrollToBottom(el: HTMLElement, options: { behavior?: ScrollBehavior; } = {}) { export function scrollToBottom(el: HTMLElement, options: ScrollToOptions = {}, container = getScrollContainer(el)) {
scroll(el, { top: el.scrollHeight, ...options }); // TODO: ちゃんと計算する if (container) {
container.scroll({ top: el.scrollHeight - container.clientHeight || 0, ...options });
} else {
window.scroll({ top: el.scrollHeight - window.innerHeight || 0, ...options });
}
} }
export function isBottom(el: HTMLElement, asobi = 1, container = getScrollContainer(el)) { export function isBottom(el: HTMLElement, asobi = 1, container = getScrollContainer(el)) {