custom-lib / custom-vue-scrollbar

A Vue3 scrollbar component.
https://custom-lib.github.io/custom-vue-scrollbar/
29 stars 7 forks source link

how to srcoll start from bottom? #8

Open DevMojahed opened 7 months ago

DevMojahed commented 7 months ago

I'm using it for a chat box & I need that to start srcoll from bottom first how to do it?

YongKJ commented 7 months ago

I'm using it for a chat box & I need that to start srcoll from bottom first how to do it?

I want to tell you that I have made similar attempts before and have been successful, based on DOM operations. So let's get to the point, show my code, and then understand my code. Good luck to you.

export class ScrollUtil {

    private constructor() {
    }

    public static async scrollToBottom(scrollBarIndex?: number, isImg?: boolean, messages?: Array<Record<string, any>>): Promise<void> {
        if (typeof scrollNum === "undefined") {
            scrollBarIndex = 0;
        }
        if (typeof isImg === "undefined") {
            while (ScrollUtil.scrollTop(scrollBarIndex) === ScrollUtil.distance(scrollBarIndex)) {
                await ScrollUtil.sleep(10);
            }
            ScrollUtil.setInstance(scrollBarIndex);
            return;
        }
        if (typeof messages === "undefined") return;
        for (let message of messages) {
            await ScrollUtil.getImageHeight(message);
        }
        ScrollUtil.setInstance(scrollBarIndex);
    }

    private static setInstance(scrollBarIndex: number): void {
        const scroller = <HTMLDivElement>document.getElementsByClassName("scrollbar__scroller")[scrollBarIndex];
        scroller.scrollTop = scroller.scrollHeight - scroller.clientHeight;
    }

    private static distance(scrollBarIndex: number): number {
        const scroller = <HTMLDivElement>document.getElementsByClassName("scrollbar__scroller")[scrollBarIndex];
        return scroller.scrollHeight - scroller.clientHeight;
    }

    private static scrollTop(scrollBarIndex: number): number {
        const scroller = <HTMLDivElement>document.getElementsByClassName("scrollbar__scroller")[scrollBarIndex];
        return scroller.scrollTop;
    }

    private static async getImageHeight(message: Record<string, any>): Promise<string> {
        let width = 0;
        let height = 0;
        do {
            let image = new Image();
            image.src = message.messageContent;
            width = image.width > 440 ? 440 : image.width;
            height = image.height > 240 ? 240 : image.height;
            await ScrollUtil.sleep(10);
        } while (width === 0 || height === 0);
        return "width: " + width + "px; " + "height: " + height + "px;";
    }

    private static sleep(waitTimeInMs: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, waitTimeInMs));
    }

}

And how to use it? Just take a look at the following example.

import {ScrollUtil} from "./ScrollUtil";

export class OnlineChatService {

    private messages: Array<Record<string, any>>;

    public constructor() {
        this.messages = new Array<Record<string, any>>();
        this.messages.push({id: 0, messageContent: "Hello world!"});
    }

    public test(): void {
        ScrollUtil.scrollToBottom(0, false, this.messages).then();
    }

}

That's it, let's celebrate the arrival of the Chinese New Year holiday.

DevMojahed commented 7 months ago

Hi dear, thanks but I'm working with vue js framework I can't use your code.

But my solutions now is like this:

<template>
  <custom-scrollbar class="w-full" ref="scrollChat">
  </custom-scrollbar>
</template>

<script setup lang="ts">
const scrollChat = ref<{ scrollEl: HTMLDivElement; }>();
const handleClickScrollToTop = () => {
    if (!scrollChat.value?.scrollEl) return;
    scrollChat.value.scrollEl.scrollTop = scrollChat.value.scrollEl.scrollHeight
}
</script>