vue实现横向时间轴组件方式
HELLO_小仙女~ 人气:0前言
项目中有需要用到横向时间轴,网上大部分组件不满足 功能需要,于是自己写了一个。先上简单的demo。
功能
- 默认获取初始数据显示对应的时间轴和时间点。
- 当超出屏幕后,滑动滚动条加载更多页,类似分页加载。
- 某个大的时间轴节点鼠标放入需要显示相关信息。
- 某两个大节点之间会有子节点出现。
- 每个子节点会有对应的子节点详情内容展示,无详情内容介绍的只展示子节点。
效果图
vue时间轴视频效果
代码
Timeline组件封装
<template> <ul class="timeline-wrapper" @scroll="scrollEvent"> <li class="timeline-item" v-for="item in timelineList" :key="item.id"> <div class="timeline-box"> <div class="out-circle"> <div class="in-circle"></div> <div class="timeline-date"> <el-popover placement="bottom" title="标题" width="200" trigger="hover" :content="item.content" > <el-button type="text" slot="reference" class="father-text">{{ item.date }}</el-button> </el-popover> </div> </div> <div class="long-line" v-show="item.isShow" :style="`width:${ item.children ? (item.children.length + 1) * 100 : 1 * 100 }px`" > <div v-for="(subItem, index) in item.children" :key="subItem.id" class="sub-item-box" > <span>{{ subItem.name + ":" + subItem.num }}人</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>
<script type="text/babel"> import Vue from "vue"; export default Vue.component("Timeline", { name: "Timeline", props: { timelineList: { type: Array, default: () => { return []; }, }, }, mounted() {}, methods: { scrollEvent(e) { this.$emit("scrollEvent", e); }, handleBottomClick() { this.$emit("handleBottomClick"); }, }, }); </script>
<style scoped lang="scss"> ul.timeline-wrapper { list-style: none; margin: 0; padding: 0; padding: 200px 20px; white-space: nowrap; overflow-x: scroll; } /* 时间线 */ .timeline-item { position: relative; display: inline-block; .timeline-box { text-align: center; // position: absolute; display: flex; align-items: center; .out-circle { width: 16px; height: 16px; background: rgba(14, 116, 218, 0.3); box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.4); /*opacity: 0.1;*/ border-radius: 50%; display: flex; align-items: center; cursor: pointer; .in-circle { width: 8px; height: 8px; margin: 0 auto; background: rgba(14, 116, 218, 1); border-radius: 50%; box-shadow: 0px 4px 12px 0px rgba(0, 0, 0, 0.1); } .timeline-date { color: #333; margin-top: 40px; .father-text { font-weight: 900; font-size: 16px; margin-left: -15px; } } } .long-line { // width: 300px; 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; .sub-item-box { margin-top: -20px; position: relative; .sub-line-box { // cursor: pointer; display: flex; flex-direction: column; justify-content: center; align-items: center; .children-line-box { width: 0px; border-left: 1px solid rgba(14, 116, 218, 0.3); } .children-box { 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; } } .top-line-box { margin-top: -100px; height: 60px; } .bottom-line-box { margin-top: 5px; height: 150px; } .top-line { height: 65px; } .bottom-line { height: 120px; } .top-children-box { margin-top: -90px; // height: 30px; width: 100px; } .bottom-children-box { // height: 120px; 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-title { font-size: 14px; word-break: break-all; margin-bottom: 16px; color: #333; font-weight: 500; /*display: inline;*/ } .timeline-desc { font-size: 14px; color: #999999; } } } .timeline-item:last-of-type .timeline-content { margin-bottom: 0; } </style>
父组件引用:
<template> <Timeline :timelineList="timeLineArr" @scrollEvent="scrollEvent" /> </template> <script> import Timeline from "@/components/Timeline"; export default { components: { Timeline, }, computed: {}, data() { return { nomore: false, // 初始话模拟数据,数据较多时即可,形成滚动条。 timeLineArr: [ { id: 1, date: "2015", title: "2015", content: "2015年初,团队在北京注册公司", isShow: true, children: [], }, { id: 2, date: "2016", title: "2016", content: "2016年,公司成立销售团队", isShow: true, children: [ { name: "创始团队", num: 5, content: "前期公司规划", }, ], }, { id: 3, date: "2017", title: "2017", content: "2017年,公司决定创建自有品牌,进行规模扩招团队", isShow: true, children: [ { name: "销售部", num: 10, content: "负责市场开发", }, { name: "技术部", num: 20, content: "前端:5人,后端10人,测试5人", }, ], }, { id: 4, date: "2018", title: "2018", content: "2018年,新增两个部门", isShow: true, children: [ { name: "人力资源部", num: 3, content: "负责人才招聘", }, { name: "财务部", num: 2, content: "财务结算", }, { name: "总裁办", num: 2, content: "", }, ], }, { id: 5, date: "2019", title: "2019", content: "2019年", isShow: true, children: [ { name: "商务企划部", num: 2, content: "对外合作", }, ], }, ], }; }, methods: { // 滚动监听 scrollEvent(e) { if ( e.srcElement.scrollLeft + e.srcElement.clientWidth >= e.srcElement.scrollWidth ) { console.log("嘿嘿我在底部触发了"); // 这里正常请求数据即可 let data = [ { id: 12, date: "2020", title: "2020", content: "2020年,受全球疫情影响,公司暂未扩招人员", isShow: true, children: [], }, { id: 22, date: "2021", title: "2021", content: "公司被xxx投资公司注入资本1000万,公司天使轮融资成功", isShow: true, children: [ { name: "仓储部", num: 30, content: "负责货物存储", }, { name: "物流部", num: 40, content: "负责自有配送", }, ], }, { id: 23, date: "2022", title: "2022", content: "公司进入A轮融资,公司被xx投资公司注入资本8000万。", isShow: false, children: [], }, ]; if (!this.nomore) { this.timeLineArr[this.timeLineArr.length - 1].isShow = true; this.timeLineArr.push(...data); this.nomore = true; } } }, }, }; </script>
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
加载全部内容