vue 模拟滚动条循环滚动


<template>
    <el-card class="card-duty">
        <template #header>
            <div class="card-header">
                <span>重大警情</span>
            </div>
        </template>
        <div class="card-body" v-loading="stateMajorAlert.loading" element-loading-background="rgb(0 0 0 / 34%)">
            <div class="wrapper-timeline" @mouseenter="mouseenterEvent()" @mouseleave="mouseleaveEvent()" ref="refTimeline">
                <ul class="timeline" v-if="stateMajorAlert.majorAlertList.length > 0">
                    <li class="timeline-item" v-for="(item, index) in stateMajorAlert.majorAlertList" :key="index">
                        <div class="timeline-item__wrapper">
                            <div class="timeline-itme__header">
                                <div class="timeline-item__level">{{ item.level }}</div>
                                <div class="timeline-item__type">{{ item.type }}</div>
                                <div class="timeline-item__address">{{ item.sfdz }}</div>
                                <div class="timeline-item__ajzt">{{ item.ajztmc }}</div>
                            </div>
                            <div class="timeline-item__content">
                                <div class="timeline-item__timestamp">发生时间:{{ item.time }}</div>
                                <div class="timeline-item__nr">警情内容:{{ item.nr }}</div>
                                <div class="timeline-item__nr" v-if="item.cjczqk">出警处置情况:{{ item.cjczqk }}</div>
                                <div class="timeline-item__nr" v-if="item.jqcljgsm">警情处理结果:{{ item.jqcljgsm }}</div>
                            </div>
                        </div>
                    </li>
                </ul>
                <div v-else class="empty">暂无数据</div>
            </div>
        </div>
    </el-card>
</template>

<script setup>
import { onMounted, watch, ref, nextTick, reactive } from 'vue';
import { useMajorAlertStore } from '../../../stores/majorAlert.store';
const { stateMajorAlert, getMajorAlert } = useMajorAlertStore();
let refTimeline = ref(null);

watch(
    () => stateMajorAlert.majorAlertList,
    (val, oldVal) => {
        initTimerInterval();
    }
);

const state = reactive({
    timer: null,
    intervalTime: 30,
    config: {
        height: 0,
    },
});

// 初始化定时器
function initTimerInterval() {
    nextTick(() => {
        clearTimerEvent();

        let dom = document.querySelector('.timeline');
        const outer = refTimeline.value;
        // 如果内容高度小于外部高度,不滚动
        if (outer.clientHeight > dom.offsetHeight) {
            return;
        }
        state.config.height = dom.offsetHeight;
        state.timer = setInterval(() => {
            window.requestAnimationFrame(scroll);
        }, state.intervalTime);
    });
}
// 滚动
function scroll() {
    const DOM = refTimeline.value;
    if (DOM.scrollTop >= state.config.height - DOM.clientHeight) {
        DOM.scrollTop = 0;
        setTimeout(() => {
            window.requestAnimationFrame(scroll);
        }, state.intervalTime);

        console.log(DOM.scrollTop >= state.config.height - DOM.clientHeight, 'DOM.scrollTop >= state.config.height - DOM.clientHeight');
        return;
    }

    DOM.scrollTop++;
}
// 清除定时器
function clearTimerEvent() {
    if (state.timer) {
        clearInterval(state.timer);
        state.timer = null;
    }
}
// 鼠标移入关闭定时器
function mouseenterEvent() {
    clearTimerEvent();
}
// 鼠标移出重新调用定时器
function mouseleaveEvent() {
    initTimerInterval();
}

onMounted(() => {
    getMajorAlert();
});
</script>

<style scoped lang="scss">
.card-duty {
    width: 100%;
    height: 276px;
    margin-bottom: 10px;
}
.wrapper-timeline {
    height: 200px;
    overflow: auto;
    .timeline {
        list-style-type: none;
        color: white;
        margin: 0;
        padding: 0;
        padding-right: 10px;

        .timeline-item {
            position: relative;
            display: flex;
            // animation: marqueeAnim 5s linear 0s infinite;
            .timeline-item__wrapper {
                flex: 1;

                position: relative;
                margin-left: 6px;
                margin-bottom: 8px;
                background: rgb(10 100 195 / 20%);
                padding: unset;
                border: 1px solid #23568d;
                border-radius: 5px;

                min-height: 70px;
                padding: 12px;
                box-sizing: border-box;
                color: #ffffff;

                font-size: 14px;
                .timeline-itme__header {
                    display: flex;
                    .timeline-item__level {
                        width: 20px;
                        height: 20px;
                        background-color: #1392ce;
                        border-radius: 50%;
                        border-right: 2px solid #082c64;
                        z-index: 9;
                        text-align: center;
                        line-height: 20px;
                        font-size: 12px;
                    }

                    .timeline-item__type {
                        height: 20px;
                        line-height: 20px;
                        background-color: #1392ce;
                        margin-left: -4px;
                        padding: 0 6px;
                        margin-right: 5px;
                        font-size: 12px;
                    }
                    .timeline-item__address {
                        flex: 1;
                    }

                    .timeline-item__ajzt {
                        height: 20px;
                        line-height: 20px;
                        border: 1px solid #2ad1f3;
                        background: linear-gradient(0deg, #037099 0%, #1aa4d5 100%);
                        border-radius: 2px;
                        padding: 0 3px;
                        font-size: 12px;
                    }
                }

                .timeline-item__content {
                    margin-top: 10px;
                    margin-left: 8px;
                    .timeline-item__timestamp {
                        margin-top: 5px;
                        color: #c3d2d2;
                    }

                    .timeline-item__nr {
                        margin-top: 5px;
                        color: #c3d2d2;
                    }
                }
            }
        }
        .timeline-item::after {
            content: '';
            position: absolute;
            left: 6px;
            top: 11px;

            width: 2px;
            height: 22px;
            background: #05eaff;
        }
    }
}

::-webkit-scrollbar {
    width: 6px;
    border-radius: 3px;
}

::-webkit-scrollbar-track {
    background-color: rgb(0 20 26 / 60%);
    border-radius: 3px;
}

::-webkit-scrollbar-thumb {
    background-color: #1b6cb5;
    border-radius: 3px;
}

.empty {
    font-size: 14px;
    padding: 0;
    height: 200px;
    display: flex;
    justify-content: center;
    align-items: center;
}
</style>


posted @ 2023-07-13 17:37  进阶的哈姆雷特  阅读(135)  评论(0编辑  收藏  举报