vue3使用vis绘制甘特图制作timeline可拖动时间轴及时间轴中文化(推荐)
导读:收集整理的这篇文章主要介绍了vue3使用vis绘制甘特图制作timeline可拖动时间轴及时间轴中文化(推荐 ,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录前言:参考文档文章一...
收集整理的这篇文章主要介绍了vue3使用vis绘制甘特图制作timeline可拖动时间轴及时间轴中文化(推荐),觉得挺不错的,现在分享给大家,也给大家做个参考。 目录
- 前言:参考文档文章
- 一、实现效果:
- 二、安装插件及依赖:
- 三、封装组件:
- 1.html部分:
- 2.引入依赖:
- 3.父组件传入数据:
- 4.js部分全部配置
- 四、父组件调用
- 1.引入子组件
- 2.初始数据
- 3.父组件按钮及事件
前言:参考文档文章
vis官方配置文档:文档地址
参考使用文章:文章地址
一、实现效果:
二、安装插件及依赖:
cnpm install -s vis-linetimecnpm install -S vis-datacnpm install -S moment
三、封装组件:
下端时间轴单独封装成组件
1.htML部分:
template> div class="visGantt" ref="visGanttDom"> /div> /template>
2.引入依赖:
import { DataSet } From 'vis-data/PEer'import { dateFormat } from '@/util' //封装的时间格式化函数,如下所示import { Timeline } from 'vis-timeline/peer'import 'vis-timeline/styles/vis-timeline-graph2d.css'const moment = require('moment')
时间格式化函数:
export function dateFormat(date, fmt) { //date是日期,fmt是格式 let o = { 'M+': date.getMonth() + 1, // 月份 'd+': date.getDate(), // 日 'H+': date.getHours(), // 小时 'h+': date.getHours(), // 小时 'm+': date.getMinutes(), // 分 's+': date.getSeconds(), // 秒 'q+': Math.floor((date.getMonth() + 3) / 3), // 季度 S: date.getMilliseconds() // 毫秒 } if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)) } for (VAR k in o) { if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))) } } return fmt}
3.父组件传入数据:
let PRops = defineProps({ ganntData: { // 初始传入数据 type: Object, default: () => { } } , ganntHistoryData: { // 全部的历史数据,为了实现撤销上一步 type: Object, default: () => { } } } )
4.js部分全部配置
配置项参考官方文档,仅注释解释个别方法。
script SETUP> import { ref, defineProps, watch, nextTick, defineEmITs } from 'vue'import { DataSet } from 'vis-data/peer'import { dateFormat } from '@/util'import { Timeline } from 'vis-timeline/peer'import 'vis-timeline/styles/vis-timeline-graph2d.css'const moment = require('moment')let props = defineProps({ ganntData: { type: Object, default: () => { } } , ganntHistoryData: { type: Object, default: () => { } } } )let timeline = ref(null)watch( props.ganntData, (newVal) => { if (newVal & & newVal[0].trackTimeWindows & & newVal[0].trackTimeWindows.length > 0) { nextTick(() => { initChart() checkTimeConflict() } ) } } , { immediate: true, deep: true } )const computedData = () => { const trackTimeWindows = [] const timeWindows = [] props.ganntData[0].trackTimeWindows.foreach( (trackTimeWindow, trackTimeWindowIndex) => { // 项目类别数组 trackTimeWindows.push({ content: trackTimeWindow.deviceid, id: `${ trackTimeWindow.deviceId} -${ trackTimeWindowIndex} -trackTimeWindows`, value: trackTimeWindowIndex + 1, classname: `visGantt-item${ trackTimeWindowIndex % 10} ` } ) // 项目时间数组 trackTimeWindow.timeWindows.forEach((timeWindow, timeWindowIndex) => { timeWindows.push({ start: new Date(timeWindow.startTime), startTime: timeWindow.startTime, end: new Date(timeWindow.stopTime), stopTime: timeWindow.stopTime, topTime: timeWindow.topTime, group: `${ trackTimeWindow.deviceId} -${ trackTimeWindowIndex} -trackTimeWindows`, className: `visGantt-item${ trackTimeWindowIndex % 10} `, id: `${ trackTimeWindow.deviceId} `, deviceId: trackTimeWindow.deviceId } ) } ) } ) return { trackTimeWindows, timeWindows } } const visGanttDom = ref(null)let historyDataArray = ref([])const emit = defineEmits()// 选择某个itemlet onSelect = (properties) => { emit('selectItem', properties.items[0])} const initChart = ()=> { const { timeWindows, trackTimeWindows } = computedData() const groups = new DataSet(trackTimeWindows) const items = new DataSet(timeWindows) let container = visGanttDom.value if (container.FirstChild) { container.removeChild(container.firstChild) } // 甘特图配置 const options = { groupOrder: function(a, b) { return a.value - b.value } , groupOrderSwap: function(a, b, groups) { var v = a.value a.value = b.value b.value = v } , height: '23.8vh', // 高度 verticalScroll: false, // 竖向滚动 orientation: 'top', // 时间轴位置 margin: { axis: 1, item: { horizontal: 0, vertical: 20 } } , editable: { updateTime: true, updateGroup: false } , multiselect: true, moment: function(date) { return moment(date).utc('+08:00') } , groupHeightMode: 'fixed', // min: new Date(startTime.value), // 最小可见范围 tooltip: { followMouse: true, overflowMethod: 'cap', template: (originalItemData, parsedItemData) => { // 鼠标hover时显示样式 return `div> p> span> 项目名称:/span> span> ${ originalItemData.deviceId} /span> /p> br/> p> span> 开始时间:/span> span> ${ dateFormat(parsedItemData.start, 'yyyy-MM-dd')} /span> /p> br/> span> 结束时间:/span> span> ${ dateFormat(parsedItemData.end, 'yyyy-MM-dd')} /span> /p> /div> ` } } , tooltIPOnItemUpdateTime: { template: (item) => { // 鼠标拖动时显示样式 return `div> span> 开始时间:${ dateFormat(item.start, 'yyyy-MM-dd')} /span> span> \n/span> span> 结束时间:${ dateFormat(item.end, 'yyyy-MM-dd')} /span> /div> ` } } , locale: moment.locale('zh-cn'), // 时间轴国际化 showcurrentTime: false, selectable: true, zoomMin: 1728000000, zoomMax: 315360000000, // showTooltips: false, // autoReSize: false, snap: function(date, scale, step) { var day = 60 * 60 * 1000 * 24 return Math.round(date / day) * day } , // 移动时返回函数 onMove: function(item, callback) { // 深拷贝一下,不能直接修改父组件数据 historyDataArray.value = JSON.parse(JSON.stringify(props.ganntHistoryData)) let historyData = [] // props.ganntHistoryData是全部的历史数据,historyData 是取上一步的数据 historyData = JSON.parse(JSON.stringify(props.ganntHistoryData[props.ganntHistoryData.length - 1])) // 更改一下格式 historyData[0].trackTimeWindows.forEach((eachItem)=> { if (eachItem.deviceId === item.deviceId) { if (!item.start || !item.end) { return } eachItem.timeWindows[0].startTime = item.start eachItem.timeWindows[0].stopTime = item.end } } ) historyDataArray.value.push(historyData) // 更新一下ganntHistoryData历史数据 emit('update:ganntHistoryData', historyDataArray.value) callback(item) } , onMoving: function(item, callback) { // 移动时间轴时不显示tooltip提示框 let tooltipDom = document.getElementsByClassName('vis-tooltip') tooltipDom[0].style.visibility = 'hidden' callback(item) } } timeline.value = new Timeline(container) timeline.value.redraw() timeline.value.setOptions(options) timeline.value.setGroups(groups) timeline.value.setItems(items) timeline.value.on('select', onSelect)} /script>
四、父组件调用
1.引入子组件
div v-loading="loading"> // loading是为了有个加载效果,为了美观 time-line :ganntData="ganntData" // 原始数据 v-model:ganntHistoryData="ganntHistoryData" // 历史数据 @selectItem="timelineSelected" //选择事件 > /time-line> /div>
import TimeLine from '@/components/modules/planControl/TimeLine'
2.初始数据
let props = defineProps({ // 因为这个父组件是通过点击进来的,所以有传入的数据,也可以直接赋值ganntData 数据,可以省略watch里面的转格式 conflictList: { type: Array, default: null } } )const ganntData = reactive([ { name: 'confilct', trackTimeWindows: [ ] } ])const ganntHistoryData = ref([])// 传入数据变化时为ganntData和ganntHistoryData赋值。watch( () => props.conflictList, (newValue) => { ganntData[0].trackTimeWindows.length = 0 newValue.forEach(element => { ganntData[0].trackTimeWindows.push({ deviceId: element.content, timeWindows: [ { startTime: element.startTime, stopTime: element.stopTime } ] } ) } ) // 记录操作历史 ganntHistoryData.value.length = 0 ganntHistoryData.value.push(ganntData) } , { deep: true, immediate: true } )
原数据(省略部分未使用参数):
[ { "id": 1, "content": "xxxxxxxxxxxxxx计划1", "time": "2023.08~10", "startTime": "2023-08-09", "stopTime": "2023-10-20" } , { "id": 2, "content": "xxxxxxxxxxxxxx计划2", "time": "2023.09~11", "startTime": "2023-09-09", "stopTime": "2023-11-1" } , { "id": 3, "content": "xxxxxxxxxxxxxx计划3", "time": "2023.08~10", "startTime": "2023-08-20", "stopTime": "2023-10-1" } ]
3.父组件按钮及事件
仅展示原始图、撤销事件。
div> div> el-button @click="reset()"> 原始图/el-button> el-button @click="preNode()"> 撤销/el-button> el-button> 一键调整/el-button> /div> div> el-button> 取消/el-button> el-button> 保存并退出/el-button> /div> /div>
回归原始图事件:
大致思路:先把ganntData清空,将拿到的props.conflictList里的数据赋值给ganntData,再把ganntData的数据push进ganntHistoryData中
// showResetTip 是显示一个“已回到初始状态”的提示框,可以自己封装或者使用组件,此处不展示const showResetTip = ref(false)const loading = ref(false)const reset = () => { // loading是加载效果 loading.value = true ganntData[0].trackTimeWindows.length = 0 props.conflictList.forEach(element => { ganntData[0].trackTimeWindows.push({ deviceId: element.content, timeWindows: [ { startTime: element.startTime, stopTime: element.stopTime } ] } ) } ) showResetTip.value = true ganntHistoryData.value.splice(0) ganntHistoryData.value.push(ganntData) setTimeout(() => { showResetTip.value = false loading.value = false } , 1000)}
撤销事件:
大致思路:拿到子组件返回的ganntHistoryData历史数据数组,删掉最后一组数据后:
如果历史数据数组的长度= 1,代表再撤销就回到原始状态了,那就直接调用reset()回到原始图;
否则,将ganntHistoryData删掉最后一组数据后的ganntHistoryDataClone最后一组值赋给ganntData,
const preNode = () => { // loading是加载效果 loading.value = true let ganntHistoryDataClone = [] ganntHistoryDataClone = JSON.parse(JSON.stringify(ganntHistoryData.value)) ganntHistoryDataClone.splice(ganntHistoryDataClone.length - 1, 1) if (ganntHistoryDataClone.length = 1) { reset() } else { ganntData[0] = ganntHistoryDataClone[ganntHistoryDataClone.length - 1][0] ganntHistoryData.value = JSON.parse(JSON.stringify(ganntHistoryDataClone)) } setTimeout(() => { loading.value = false } , 1000)}
到此这篇关于vue3使用vis绘制甘特图制作timeline可拖动时间轴,时间轴中文化的文章就介绍到这了,更多相关vue3用vis绘制甘特图内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
您可能感兴趣的文章:- 微信小程序实现Timeline时间线效果
- Element Timeline时间线的实现
- 微信小程序onShareTimeline()实现分享朋友圈
- Vue时间轴 vue-light-timeline的用法说明
- 使用vis-timeline绘制甘特图并实现时间轴的中文化(案例代码)
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: vue3使用vis绘制甘特图制作timeline可拖动时间轴及时间轴中文化(推荐)
本文地址: https://pptw.com/jishu/609299.html