Skip to content

Commit

Permalink
feat: ✨add slider move
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyjone committed Apr 18, 2023
1 parent 8eac017 commit 36c32c8
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 42 deletions.
4 changes: 2 additions & 2 deletions demo/demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ function onAdd() {
ganttData.push({
id: ++id,
name: 't' + id,
startDate: new Date(2020, 0, 1),
endDate: new Date(2020, 0, 5)
startDate: new Date(2020, 0, id),
endDate: new Date(2020, 0, id + 5)
});
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
},
"dependencies": {
"@types/lodash": "^4.14.192",
"@vueuse/core": "^9.13.0",
"@vueuse/core": "^10.0.0",
"dayjs": "^1.11.7",
"lodash": "^4.17.21",
"vue": "^3.2.47"
Expand Down
6 changes: 3 additions & 3 deletions src/components/common/GanttHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<table class="xg-gantt-header" cellpadding="0" cellspacing="0" border="0">
<colgroup>
<template v-for="i in dateList[1].length" :key="i">
<col width="30px" />
<col :width="`${ganttColumnWidth}px`" />
</template>
</colgroup>
<thead>
Expand All @@ -24,12 +24,12 @@

<script lang="ts" setup>
import useData from '@/composables/useData';
import useGanttWidth from '@/composables/useGanttWidth';
import useStyle from '@/composables/useStyle';
const { $styleBox } = useStyle();
const { dateList } = useData();
console.log('getDateList', dateList.value);
const { ganttColumnWidth } = useGanttWidth();
</script>

<style lang="scss" scoped>
Expand Down
3 changes: 2 additions & 1 deletion src/components/root/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import useData from '@/composables/useData';
import useStyle from '@/composables/useStyle';
import { useResizeObserver } from '@vueuse/core';
import useParam from '@/composables/useParam';
import useGanttHeader from '@/composables/useGanttHeader';
const containerId = uuid(10);
const props = defineProps(rootProps);
Expand Down Expand Up @@ -111,7 +112,7 @@ initData(data);
// #endregion
// #region 监听 gantt 尺寸变化,表头和宽度需要重新渲染
const { setGanttHeaders } = useData();
const { setGanttHeaders } = useGanttHeader();
onMounted(() => useResizeObserver(ganttRef.value?.$el, setGanttHeaders));
// #endregion
Expand Down
70 changes: 66 additions & 4 deletions src/components/slider/index.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
<template>
<div class="xg-slider">
<div
ref="sliderRef"
:class="['xg-slider', 'xg-slider-drag']"
:style="{ left: `${sliderLeft}px`, width: `${sliderWidth}px` }"
>
<slot v-if="slots.default" v-bind="props.data?.data" />
<span v-else-if="props.prop">{{ props.data?.data?.[props.prop] }}</span>
</div>
</template>
<script lang="ts">
import { defineComponent, useSlots } from 'vue';
import { defineComponent, useSlots, ref, computed } from 'vue';
import Variables from '@/constants/vars';
import sliderProps from './props';
import { useDraggable } from '@vueuse/core';
import useData from '@/composables/useData';
import useGanttHeader from '@/composables/useGanttHeader';
import useGanttWidth from '@/composables/useGanttWidth';
export default defineComponent({
name: Variables.name.slider
Expand All @@ -18,15 +26,65 @@ export default defineComponent({
<script setup lang="ts">
const props = defineProps(sliderProps);
const slots = useSlots();
// left 取决于 data 的 start 日期值
// 滑块的初始偏移量
const { $data } = useData();
const { ganttHeader } = useGanttHeader();
const { ganttColumnWidth } = useGanttWidth();
const sliderLeft = computed(
() =>
((props.data?.start.intervalTo($data.start) ?? 0) /
Variables.time.millisecondOf[ganttHeader.unit]) *
ganttColumnWidth.value
);
const sliderWidth = computed(
() =>
(props.data!.start.intervalTo(props.data?.end) /
Variables.time.millisecondOf[ganttHeader.unit]) *
ganttColumnWidth.value
);
const left = ref(0);
const sliderRef = ref<HTMLElement | null>(null);
const delta = ref(0);
const startDate = props.data?.start.clone();
const endDate = props.data?.end.clone();
useDraggable(sliderRef, {
onStart: (pos, e) => {
const rect = sliderRef.value!.getBoundingClientRect();
delta.value = Math.abs(left.value - rect.left) + e.offsetX;
},
onMove: (pos, e) => {
left.value = e.clientX - delta.value;
props.data?.setStart(
startDate!.getOffset(
(left.value / ganttColumnWidth.value) *
Variables.time.millisecondOf[ganttHeader.unit]
),
ganttHeader.unit
);
props.data?.setEnd(
endDate!.getOffset(
(left.value / ganttColumnWidth.value) *
Variables.time.millisecondOf[ganttHeader.unit]
),
ganttHeader.unit
);
}
});
</script>
<style lang="scss" scoped>
@use 'sass:math';
.xg-slider {
width: 100px;
background-color: darkgoldenrod;
position: absolute;
$h: 70%;
Expand All @@ -35,4 +93,8 @@ const slots = useSlots();
font-size: 12px;
top: math.div(100% - $h, 2);
}
.xg-slider.xg-slider-drag {
cursor: move;
}
</style>
18 changes: 2 additions & 16 deletions src/composables/useData.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import type RowItem from '@/models/data/row';
import { useStore } from '@/store';
import { computed, watch, type Ref } from 'vue';
import useGanttWidth from './useGanttWidth';
import useTableWidth from './useTableWidth';
import useGanttHeader from './useGanttHeader';

export default () => {
const store = useStore();
const { ganttColumnWidth } = useGanttWidth();
const { tableWidth } = useTableWidth();

// 设置甘特日期头
function setGanttHeaders() {
store.ganttHeader.setDate(
// 使用 window 的宽度减去 table 的宽度,就是最小需要的列数,再加一个阈值即可
(window.innerWidth - tableWidth.value) / ganttColumnWidth.value + 5,
store.$data.start,
store.$data.end,
store.$styleBox.unit
);
}
const { setGanttHeaders } = useGanttHeader();

function initData(data: Ref<any[]>) {
store.$data.init(data.value);
Expand Down Expand Up @@ -48,7 +35,6 @@ export default () => {
$data: store.$data,
initData,
dateList: computed(() => store.ganttHeader.headers),
setGanttHeaders,
toRowData
};
};
25 changes: 25 additions & 0 deletions src/composables/useGanttHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useStore } from '@/store';
import useGanttWidth from './useGanttWidth';
import useTableWidth from './useTableWidth';

export default () => {
const store = useStore();
const { ganttColumnWidth } = useGanttWidth();
const { tableWidth } = useTableWidth();

// 设置甘特日期头
function setGanttHeaders() {
store.ganttHeader.setDate(
// 使用 window 的宽度减去 table 的宽度,就是最小需要的列数,再加一个阈值即可
(window.innerWidth - tableWidth.value) / ganttColumnWidth.value + 5,
store.$data.start,
store.$data.end,
store.$styleBox.unit
);
}

return {
setGanttHeaders,
ganttHeader: store.ganttHeader
};
};
3 changes: 1 addition & 2 deletions src/constants/vars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ export const Variables = {
week: 'year',
day: 'month',
hour: 'day',
minute: 'hour',
second: 'minute'
minute: 'hour'
}
}
};
Expand Down
19 changes: 10 additions & 9 deletions src/models/data/row.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* @Author: JeremyJone
* @Date: 2021-09-09 15:50:52
* @LastEditors: JeremyJone
* @LastEditTime: 2023-04-18 10:35:13
* @LastEditTime: 2023-04-18 19:30:08
* @Description: 一条数据类
*/

Expand Down Expand Up @@ -175,11 +175,11 @@ export default class RowItem {

// 首先判断起始日期不能大于结束日期
if (
date.compareTo(this.end.getOffset(Variables.time.millisecondOf.day)) ===
date.compareTo(this.end.getOffset(Variables.time.millisecondOf[unit])) ===
'r'
)
this.data[this.options.endLabel] = date.getOffset(
Variables.time.millisecondOf.day
this.__data[this.options.endLabel] = date.getOffset(
Variables.time.millisecondOf[unit]
).date;

// if (!linkage) return;
Expand Down Expand Up @@ -207,16 +207,17 @@ export default class RowItem {
linkage = false,
modifyArr: RowItem[] = []
) {
this.data[this.options.endLabel] = date.date;
this.__data[this.options.endLabel] = date.date;

// 首先判断起始日期不能大于结束日期

if (
date.compareTo(this.start.getOffset(Variables.time.millisecondOf.day)) ===
'l'
date.compareTo(
this.start.getOffset(Variables.time.millisecondOf[unit])
) === 'l'
)
this.data[this.options.startLabel] = date.getOffset(
Variables.time.millisecondOf.day
this.__data[this.options.startLabel] = date.getOffset(
Variables.time.millisecondOf[unit]
).date;

// if (!linkage) return;
Expand Down
11 changes: 9 additions & 2 deletions src/models/param/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export class XDate {
/**
* 获取两个时间的间隔时间戳
*/
intervalTo(date: XDate) {
return this.date.getTime() - date.date.getTime();
intervalTo(date?: XDate) {
return this.date.getTime() - (date?.date.getTime() ?? 0);
}

/**
Expand Down Expand Up @@ -107,4 +107,11 @@ export class XDate {
toString(format: string = 'YYYY-MM-DD') {
return day(this.date).format(format);
}

/**
* 返回一个全新的日期对象
*/
clone() {
return new XDate(this.date);
}
}
9 changes: 7 additions & 2 deletions src/typings/date.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
declare type HeaderDateUnit = 'week' | 'day' | 'hour' | 'minute' | 'second';
declare type HeaderDateUnit = 'week' | 'day' | 'hour' | 'minute';

declare type DateUnit = 'year' | 'month' | HeaderDateUnit | 'millisecond';
declare type DateUnit =
| 'year'
| 'month'
| HeaderDateUnit
| 'millisecond'
| 'second';

0 comments on commit 36c32c8

Please sign in to comment.