首页 > 其他分享 >vue3横向时间轴展示

vue3横向时间轴展示

时间:2023-12-27 10:45:41浏览次数:23  
标签:box -- timeline 横向 item 时间轴 vue3 line children

架子是用的vue3+element Plus, 要用到时间轴展示,但element组件只有竖着的,想要横着的,找了一圈没有合适的,终于找到个合适的,文章原址 https://blog.csdn.net/m0_62949703/article/details/127800712

数据结构:

{
    date: '2023-09-27’,
    isShow: true,
    children: [
        {
            lineTitle: `公司地址`,
            content: `变更前:${item.changeFront}\n变更后:${item.changeBack}`
        }
    ]
}

 HTML:

<template>
<!--    横向时间轴组件-->
    <ul class="timeline-wrapper">
        <li class="timeline-item" v-for="(item,index) in timelineList" :key="index">
            <div class="timeline-box">
                <div class="out-circle">
<!--                    小圆点-->
                    <div class="in-circle" />
<!--                    时间-->
                    <div class="time">{{ item.date }}</div>
<!--                    悬浮气泡-->
<!--                    <div class="timeline-date">-->
<!--                        <el-popover placement="bottom" trigger="hover" width="200" title="变更明细">-->
<!--                            <template >-->
<!--                                <p>{{666}}</p>-->
<!--                            </template>-->
<!--                            <div>777777777777</div>-->
<!--                            <div>888888888888</div>-->
<!--                        </el-popover>-->
<!--                    </div>-->
                </div>
<!--                常驻气泡框-->
                <div
                    class="long-line"
                    v-show="item.isShow"
                    :style="`width:${item.children ? (item.children.length + 1) * 400 : 1 * 100}px`">
                    <div
                        v-for="(subItem, index) in item.children"
                        :key="index"
                        class="sub-item-box"
                    >
                        <span>{{ subItem.lineTitle }}</span>
                        <!-- 根据奇数偶数来判断向上展示还是向下展示 -->
                        <div :class="`sub-line-box ${index % 2 === 0 ? 'top-line-box' : 'bottom-line-box'}`" v-show="subItem.content">
                            <!--  线-->
                            <div :class="`children-line-box ${index % 2 === 0 ? 'top-line' : 'bottom-line' }`"></div>
                            <!--     气泡框-->
                            <div :class="`children-box ${index % 2 === 0 ? 'top-children-box' : 'bottom-children-box'}`">
                                {{ subItem.content }}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </li>
    </ul>
</template>

JS: 

<script setup lang="ts">
// 接收接口返回的数据
const Props = defineProps(['timelineList'])
// 时间轴数据
const timelineList = ref<any>([])

// 新增新日期
const newArrayPush = (item: any) => {
    let childrenData = [
        {
            lineTitle: item.changeItem,
            content: `变更前:${item.changeFront}\n变更后:${item.changeBack}`
        }
    ]
    let list = {
        date: item.changeTime,
        isShow: true,
        children: childrenData
    }
    timelineList.value.push(list)
}

watch(()=>Props.timelineList, (newV) => {
    console.log(newV)
    if (newV && newV.length > 0){
        newV.forEach((item: any) => {
            if (timelineList.value.length > 0){
                const index = timelineList.value.findIndex((newItem: any) => newItem.date === item.changeTime)
                if (index !== -1){
                    // 该日期已存在,直接往该对象的children里塞
                    timelineList.value[index].children.push({
                        lineTitle: item.changeItem,
                        content: `变更前:${item.changeFront}\n变更后:${item.changeBack}`
                    },
                       )
                }else {
                    // 该日期不存在, 创建新对象塞进newArray
                    newArrayPush(item)
                }
            }else {
                newArrayPush(item)
            }
        })
        console.log(timelineList.value)
    }else {
        timelineList.value = []
    }
})
</script>

CSS:

原点颜色用的element的颜色 

background: var(--el-menu-active-color);
<style scoped>
.timeline-wrapper{
    padding: 200px 20px;
    width: 100%;
    min-width: 0;
    display: flex;
    overflow-x: auto;
}
/*展示时间样式*/
.time{
    position: absolute;
    top: 15px;
    width: 80px;
}
.timeline-wrapper::-webkit-scrollbar {
    width: 4px;
    height: 12px;
}
.timeline-wrapper::-webkit-scrollbar-thumb {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3);
    opacity: 0.2;
    background-color: #dadada;

}
.timeline-wrapper::-webkit-scrollbar-track {
    border-radius: 10px;
    -webkit-box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.3);
}

/* 时间线 */
.timeline-item {
    position: relative;
    display: inline-block;
}

.timeline-item .timeline-box {
    text-align: center;
    display: flex;
    align-items: center;
}
/*原点样式*/
.timeline-item .timeline-box .out-circle {
    width: 12px;
    height:12px;
    background: var(--el-menu-active-color);
    box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.4);
    border-radius: 50%;
    display: flex;
    align-items: center;
    cursor: pointer;
    position: relative;
}

.timeline-item .timeline-box .out-circle .in-circle {
    width: 8px;
    height: 8px;
    margin: 0 auto;
    background: var(--el-menu-active-color);
    border-radius: 50%;
    box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1);
}

.timeline-item .timeline-box .out-circle .timeline-date {
    color: #333;
    margin-top: 55px;
}

.timeline-item .timeline-box .out-circle .timeline-date .father-text {
    font-weight: 900;
    font-size: 16px;
    margin-left: -15px;
}

.long-line {
    height: 2px;
    background: rgba(14, 116, 218, 0.2);
    box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.3);
    display: flex;
    flex-direction: revert;
    justify-content: space-around;
}

.long-line .sub-item-box {
    margin-top: -20px;
    position: relative;
}

.long-line .sub-item-box .sub-line-box {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.long-line .sub-item-box .sub-line-box .children-line-box {
    width: 0px;
    border-left: 1px solid rgba(14, 116, 218, 0.3);
}

.long-line .sub-item-box .sub-line-box .children-box {
    width: 100%;
    min-width: 250px;
    flex-wrap: wrap;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid rgba(14, 116, 218, 0.3);
    white-space: break-spaces;
    text-align: center;
    padding: 5px;
}

.long-line .top-line-box {
    margin-top: -100px;
    height: 60px;
}

.long-line .bottom-line-box {
    margin-top: 5px;
    height: 150px;
}

.long-line .top-line {
    height: 65px;
}

.long-line .bottom-line {
    height: 120px;
}

.long-line .top-children-box {
    margin-top: -90px;
    background-color: #e2e2e2;
    border-radius: 5px;
    width: 100px;
}

.long-line .bottom-children-box {
    background-color: #e2e2e2;
    border-radius: 5px;
    width: 150px;
}

.timeline-content {
    box-sizing: border-box;
    margin-left: 20px;
    height: 106px;
    padding: 0 0 0 20px;
    text-align: left;
    margin-bottom: 30px;
}

.timeline-content .timeline-title {
    font-size: 14px;
    word-break: break-all;
    margin-bottom: 16px;
    color: #333;
    font-weight: 500;
    /*display: inline;*/
}

.timeline-content .timeline-desc {
    font-size: 14px;
    color: #999999;
}

.timeline-item:last-of-type .timeline-content {
    margin-bottom: 0;
}

</style>

接口返回数据样式:

逻辑就是根据相同的时间来判断,时间相同就把数据往改时间的对象的children里塞。没有该时间就新push个含有该时间的对象, 然后往这个时间的对象children里塞数据。children里就是轴上下展示的气泡框信息

标签:box,--,timeline,横向,item,时间轴,vue3,line,children
From: https://www.cnblogs.com/alannero/p/17930013.html

相关文章

  • Vue3+TS+Vite中 vConsole 插件的使用
    vConsole一个轻量、可拓展、针对手机网页的前端开发者调试面板。vConsole是框架无关的,可以在Vue、React或其他任何框架中使用。现在vConsole是微信小程序的官方调试工具。https://gitee.com/Tencent/vConsole/ 平时在web应用开发过程中,我们可以console.log去输出一些......
  • vue3 elementplus 表格表头过长 三个点显示
    vue3:constrenderHeaderMethods=({column})=>{returncreateVNode(resolveComponent('el-tooltip'),{effect:'dark',content:column.label,placement:'top'......
  • vue3学习之Pinia状态管理
    状态管理 src/views/Pinia.vue<scriptsetup>import{ref}from"vue";import{storeToRefs}from"pinia";import{useCounterStore}from"../stores/counter";import{useTodos}from"../stores/todos";//可......
  • vue3学习之逻辑复用
    逻辑复用-组合式函数 src/views/ad/User.vue<scriptsetup>import{useMouse}from"../../js/mouse.js";import{useFetch}from"../../js/fetch.js";import{ref,computed}from"vue";//组合式函数const{x,y}=useMouse();/......
  • vue3学习基础之组件
    组件Comp.vue<scriptsetup>import{ref,provide,readonly,defineAsyncComponent}from"vue";importDemoCompfrom"../../components/simple/DemoComp.vue";importErrorComponentfrom"../../components/simple/ErrorComp.vue&......
  • vue3学习基础之响应式状态
    响应式状态<scriptsetup>import{ref,reactive,computed,watch,watchEffect}from"vue";//reactive响应式对象只能用于对象、数组和集合类型constauthor=reactive({name:"JohnDoe",books:["Vue2-AdvancedGuide","Vue3-......
  • vue3学习基础之事件绑定
    事件绑定<scriptsetup>import{nextTick,ref}from"vue";functionclickA(){console.log("点击了a标签,点击事件传递到了外层p标签");}functionclickStop(){console.log("点击了a标签,点击事件停止向外层传递");}functionclickOnce(){console.log......
  • vue3学习基础之表单相关
    表单相关<scriptsetup>import{ref}from"vue";constmessage=ref("hello");constchecked=ref();constcheckedNames=ref([]);constpicked=ref();constselected=ref();constmulSelected=ref([]);constnum=ref(5);......
  • vue3学习基础之vue-router
    我的vue3学习之路总是学学停停,最开始在18年开发微信小程序,就发现小程序和vue的语法有些相似,然后就去看了vue2的文档,随后忙其它的事情就丢下了。直到22年又开始捡起来vue3,有了组合式api,语法简明很多,然后又不知道忙什么丢下。。。前段有些空时间,就把vue3的学习整理下,使用vite构建......
  • 【源码系列#04】Vue3侦听器原理(Watch)
    专栏分享:vue2源码专栏,vue3源码专栏,vuerouter源码专栏,玩具项目专栏,硬核......