<template> <div class="nf-timeline flex-row"> <div class="nf-timeline-list flex-row" ref="ppp"> <div :style="{ width: 100 / Number(list.length ? list.length : 20) + '%' }" class="nf-timeline-item flex-row" :class="[`timelineItem${i}`, i == list.length - 1 ? 'w-20' : '', Math.floor(index / 100) >= i ? 'node-check' : '']" v-for="(item, i) in list" :ref="`timelineItem${i}`" @click="(index = i * 100), $emit('checkTimeLineNode', index)" :key="item.id" @mousedown="dragStart($event, i)" @mousemove="dragging($event, i)" @mouseup="dragEnd($event, i)" > <el-tooltip class="box-item" effect="dark" :content="item.name" placement="top"> <div class="nf-timeline-item-node flex-row"> <!-- <span>{{ item.name }}</span> --> </div> </el-tooltip> <div class="nf-timeline-item-line" v-if="i != list.length - 1"> <div :style="{ width: `${Math.floor(index / 100) - 1 >= i ? 100 : index % 100}%`, }" v-if="i * 100 < index" ></div> </div> </div> </div> <div class="nf-timeline-buttom flex-row" :class="{ 'nf-timeline-play': !status }" :title="!status ? '播放' : '暂停'" @click="status ? stop() : start()" > <!-- <div></div> --> <img :src="status ? getImageUrl('zanting_icon.png', 'newImgs/HaiMianScreen') : getImageUrl('kaisshi_icon.png', 'newImgs/HaiMianScreen')" alt="" /> </div> </div> </template> <script> export default { name: 'TimeLine', props: { list: { type: Array, default() { return [ { id: 1, name: '2016', detail: '' }, { id: 2, name: '2017', detail: '' }, { id: 3, name: '2018', detail: '' }, { id: 4, name: '2019', detail: '' }, { id: 5, name: '2020', detail: '' }, { id: 6, name: '2021', detail: '' }, ]; }, }, params: { type: Object, default() { return { nodeTime: 1, }; }, }, }, data() { return { interval: null, index: -1, draggingindex: 0, status: false, draggingElement: null, initialMousePosition: null, initialElementPosition: null, }; }, methods: { dragStart(event, index) { if (event.button !== 0 || !this.$refs[`timelineItem${index}`]) return; // Only handle left mouse button and ensure element ref exists const target = this.$refs[`timelineItem${index}`]; if (!target) return; this.draggingElement = target; }, dragging(event, indexs) { if (!this.draggingElement) return; this.index = indexs * 100; if (indexs == 0) { this.index = -1; } }, dragEnd(event, indexs) { if (!this.draggingElement) return; this.draggingElement = null; this.initialMousePosition = null; this.initialElementPosition = null; // Restore text selection after dragging document.body.style.userSelect = ''; }, start() { let self = this; if (self.interval) { self.destroy(); self.interval = null; } self.interval = setInterval(() => { self.index += 1; if (self.index >= (self.list.length - 1) * 100) (self.index = -1), (self.status = false), clearInterval(self.interval); // if (self.index >= (self.list.length - 1) * 100) self.index = 0; this.$emit('getTimeLineIndex', self.index); }, 10 * self.params.nodeTime); self.status = true; }, stop() { let self = this; self.destroy(); self.status = false; }, destroy() { let self = this; clearInterval(self.interval); }, }, mounted() {}, destroyed() { let self = this; self.destroy(); }, }; </script> <style scoped> div { box-sizing: border-box; } .nf-timeline { /*position: absolute;*/ z-index: 9999; bottom: 0px; left: 0; width: 100%; /*min-height: 100px;*/ /*padding:15px 20px 0 20px;*/ justify-content: flex-start !important; align-items: flex-start !important; /* background: rgba(6, 31, 64, 0.5); */ } .nf-timeline-buttom { width: 40px; height: 40px; /* border: 3px solid rgba(12, 89, 165, 1); */ margin-top: -8px; cursor: pointer; border-radius: 100%; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); } .nf-timeline-buttom > div { width: 50%; height: 50%; border: 1px solid rgba(12, 89, 165, 1); background: rgba(12, 89, 165, 1); transition: all 0.2s ease-in; } .nf-timeline-play > div { border-top: 8px solid transparent; border-bottom: 8px solid transparent; border-left: 13px solid rgba(12, 89, 165, 1); border-right: 8px solid transparent; background: transparent; /*left: 50%;*/ transform: translateX(25%); /*border: 0px solid transparent !important;*/ /*border-left: 40px solid rgba(12,89,165,1) !important;*/ } .nf-timeline-list { width: calc(100% - 40px); height: 80%; padding-left: 20px; /* border-radius: 10px; */ } .nf-timeline-list > :first-child { /* 样式应用于.container的第一个子元素 */ border-radius: 10px; .nf-timeline-item-node { border-radius: 40px 0 0 40px; } } .nf-timeline-list > :last-child { /* 样式应用于.container的最后一个子元素 */ border-radius: 10px; .nf-timeline-item-node { border-radius: 0 40px 40px 0; } } .nf-timeline-item { width: 100%; height: 100%; align-items: flex-start !important; justify-content: flex-start !important; cursor: pointer; } .nf-timeline-item-node { width: 20px; height: 10px !important; top: 9px; /* border-radius: 100%; border: 2px solid rgba(192, 196, 204, 1); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04); */ position: relative; color: rgba(192, 196, 204, 1); background: rgba(192, 196, 204, 1); cursor: pointer; } .node-check > .nf-timeline-item-node { /* border: 2px solid rgba(12, 89, 165, 1) !important; */ width: 20px; height: 10px !important; top: 9px; position: relative; color: #37d9fa !important; background: #37d9fa; } .nf-timeline-item-node > span { position: relative; top: 30px; } .nf-timeline-item-line { height: 10px !important; /* width: calc(100% - 20px); */ width: 100%; position: relative; top: 9px; background: rgba(192, 196, 204, 1); } .nf-timeline-item-line > div { height: 100%; width: 0; background: #37d9fa; } .flex-row { display: flex; justify-content: center; align-items: center; } .flex-column { display: flex; justify-content: center; align-items: center; flex-flow: column nowrap; } .w-20 { width: 20px !important; } .node-check { width: 100%; } .node-check > div { height: 100%; width: 100%; background: #37d9fa; } </style>