Skip to content

Commit

Permalink
feat: ✨添加连线以及动态增加连线
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremyjone committed May 15, 2023
1 parent baaedba commit 567eedd
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 38 deletions.
22 changes: 20 additions & 2 deletions demo/demo.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div style="top: 20vh; width: 100%; height: 500px">
<div style="top: 20vh; width: 100%; height: 500px; padding-left: 5vw">
<x-gantt
data-id="index"
:data="ganttData"
Expand All @@ -12,6 +12,7 @@
:show-weekend="true"
@row-click="onClickRow"
@move-slider="onMoveSlider"
@add-link="onAddLink"
>
<x-gantt-column label="group1">
<x-gantt-column prop="index" width="120px"></x-gantt-column>
Expand Down Expand Up @@ -133,12 +134,25 @@ const ganttLinks = [
{
index: 1,
from: 1,
to: 2
to: 2,
color: 'green'
},
{
index: 2,
from: 2,
to: 5
},
{
index: 3,
from: 4,
to: 2,
color: 'red'
},
{
index: 4,
from: 4,
to: 3,
color: '#abc'
}
];
Expand Down Expand Up @@ -179,6 +193,10 @@ const onMoveSlider = (data: any) => {
console.log('move slider', data);
};
const onAddLink = (data: any) => {
console.log('add link', data);
};
function onMove(data: any) {
return true;
}
Expand Down
10 changes: 8 additions & 2 deletions src/components/common/GanttBody.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div
ref="ganttBodyRef"
class="xg-gantt-body"
:style="{ height: bodyHeight, width: `${ganttWidth}px` }"
>
Expand All @@ -14,6 +15,8 @@
<svg class="xg-gantt-body-line-wrap" :style="{ width: `${ganttWidth}px` }">
<!-- <path stroke="red" fill="transparent" d="M 200 2 H 400 V 102"></path> -->
<LinkPath v-for="link in $links.links" :key="link.uuid" :link="link" />

<Linking />
</svg>

<!-- 行样式 -->
Expand Down Expand Up @@ -55,9 +58,11 @@ import useInView from '@/composables/useInView';
import useSlotsBox from '@/composables/useSlotsBox';
import useStyle from '@/composables/useStyle';
import useToday from '@/composables/useToday';
import RowVue from './Row.vue';
import LinkPath from './LinkPath.vue';
import useLinks from '@/composables/useLinks';
import RowVue from './Row.vue';
import LinkPath from '@/components/links/LinkPath.vue';
import Linking from '@/components/links/Linking.vue';
import useElement from '@/composables/useElement';
const { $slotsBox } = useSlotsBox();
const { bodyHeight, $styleBox } = useStyle();
Expand All @@ -66,6 +71,7 @@ const { inView } = useInView();
const { todayLeft, showToday } = useToday();
const { ganttHeader } = useGanttHeader();
const { $links } = useLinks();
const { ganttBodyRef } = useElement();
</script>

<style lang="scss" scoped>
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/Row.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
backgroundColor: props.renderStyle ? ($styleBox.levelColor[props.data!.level] ?? undefined) : undefined,
...$styleBox.getBorderColor()
}"
@mouseenter="onEnter"
@mouseleave="onLeave"
@pointerenter="onEnter"
@pointerleave="onLeave"
@click="onClick"
@dblclick="onDblClick"
>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
<template>
<path stroke="#eca710" fill="transparent" :d="path"></path>
<g>
<path
:d="path"
fill="transparent"
:stroke="link.color"
stroke-width="2"
stroke-dasharray="4,4"
:marker-end="`url(#triangle_${link.color})`"
:marker-start="`url(#circle_${link.color})`"
/>

<defs>
<marker
:id="`triangle_${link.color}`"
markerWidth="5"
markerHeight="4"
refX="0"
refY="2"
orient="auto"
markerUnits="strokeWidth"
>
<path d="M0,0 L0,4 L5,2 z" :fill="link.color" />
</marker>

<marker
:id="`circle_${link.color}`"
markerWidth="5"
markerHeight="4"
refX="3"
refY="2"
orient="auto"
markerUnits="strokeWidth"
>
<circle cx="2" cy="2" r="2" :fill="link.color" />
</marker>
</defs>
</g>
</template>

<script lang="ts" setup>
Expand Down Expand Up @@ -42,10 +78,14 @@ const y2 = computed(
() => props.link.toRow.flatIndex * rowHeight.value + rowHeight.value / 2
);
const down = computed(() => (y2.value > y.value ? 1 : -1));
const path = computed(
() =>
`M ${x.value + 10} ${y.value} H ${x.value + 20} V ${
x2.value - 20 >= x.value + 20 ? y.value : y.value + rowHeight.value / 2
`M ${x.value + 10} ${y.value} H ${x.value + 20} V${
x2.value - 20 >= x.value + 20
? y.value
: y.value + (rowHeight.value / 2) * down.value
} H ${x2.value - 20} V ${y2.value} H ${x2.value - 10}`
);
</script>
Expand Down
43 changes: 43 additions & 0 deletions src/components/links/Linking.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<g v-show="linking.isLinking">
<path
:d="path"
fill="transparent"
stroke="red"
stroke-width="2"
stroke-dasharray="5,5"
:marker-end="`url(#${id})`"
/>

<defs>
<marker
:id="id"
markerWidth="5"
markerHeight="4"
refX="5"
refY="2"
orient="auto"
markerUnits="strokeWidth"
>
<path d="M0,0 L0,4 L5,2 z" fill="red" />
</marker>
</defs>
</g>
</template>

<script lang="ts" setup>
import useLinks from '@/composables/useLinks';
import { uuid } from '@/utils/common';
import { computed } from 'vue';
const { linking } = useLinks();
const id = uuid();
const path = computed(
() =>
`M ${linking.startPos.x} ${linking.startPos.y} L ${linking.endPos.x} ${linking.endPos.y}`
);
</script>

<style scoped lang="scss"></style>
3 changes: 3 additions & 0 deletions src/components/root/RootWrap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { initStore } from '@/store';
import useRoot from '@/composables/useRoot';
import Root from './index.vue';
import useEvent from '@/composables/useEvent';
import { MoveSliderData } from '@/typings/data';
import { LinkProps } from '@/typings/link';
export default defineComponent({
name: 'RootWrap',
Expand All @@ -25,6 +27,7 @@ const emit = defineEmits<{
(e: 'row-checked', state: boolean, data: any): void;
(e: 'move-slider', data: MoveSliderData[]): void;
(e: 'move-progress', data: any, old: number): void;
(e: 'add-link', data: LinkProps): void;
(e: 'no-date-error'): void;
}>();
Expand Down
67 changes: 57 additions & 10 deletions src/components/slider/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@
: `calc(calc(100% - ${height}) / 2)`
}"
@click.stop
@pointerup="onPointerUp"
>
<div
<!-- <div
:class="[
'xg-slider-anchor',
'in-anchor',
Expand All @@ -25,7 +26,7 @@
}
]"
@pointerdown="onInAnchorDown"
></div>
></div> -->

<div class="xg-slider-block">
<!-- 滑块主体 -->
Expand Down Expand Up @@ -74,6 +75,7 @@
</div>

<div
ref="outAnchorRef"
:class="[
'xg-slider-anchor',
'out-anchor',
Expand All @@ -100,6 +102,8 @@ import { formatDate } from '@/utils/date';
import { flow, isBoolean, isFunction } from 'lodash';
import useEvent from '@/composables/useEvent';
import { MoveSliderInternalData, RowData } from '@/typings/data';
import useLinks from '@/composables/useLinks';
import useElement from '@/composables/useElement';
export default defineComponent({
name: Variables.name.slider
Expand Down Expand Up @@ -267,16 +271,59 @@ onDrag(resizeRightRef, {
// #endregion
// #region inAnchor
function onInAnchorDown() {
handleDisableMove();
}
// function onInAnchorDown() {
// handleDisableMove();
// }
// #endregion
// #region outAnchor
function onOutAnchorDown() {
function onOutAnchorDown(e: PointerEvent) {
handleDisableMove();
}
const { setLinking, linking, $links } = useLinks();
const { ganttBodyRef } = useElement();
const { rowHeight } = useStyle();
const outAnchorRef = ref(null) as Ref<HTMLElement | null>;
const startPos = { x: 0, y: 0 };
onDrag(outAnchorRef, {
reset: true,
onStart: pos => {
startPos.x = (ganttBodyRef.value?.getBoundingClientRect().x ?? 0) - pos.x;
startPos.y = (ganttBodyRef.value?.getBoundingClientRect().y ?? 0) - pos.y;
const _sp = {
x: sliderLeft.value + sliderWidth.value + 10,
y: ((props.data?.flatIndex ?? 0) + 0.5) * rowHeight.value
};
setLinking({
isLinking: true,
startRow: props.data,
startPos: _sp,
endPos: _sp
});
},
console.log('outAnchorDown', props.data);
onMove: (x, pos) => {
setLinking({ endPos: { x: pos.x - startPos.x, y: pos.y - startPos.y } });
},
onFinally: () => {
setLinking({ isLinking: false });
}
});
const { EmitAddLink } = useEvent();
function onPointerUp() {
if (linking.startRow) {
if (linking.startRow?.uuid !== props.data?.uuid) {
const link = $links.addLink(linking.startRow, props.data!);
EmitAddLink(link);
}
setLinking({ startRow: null, endRow: null });
}
}
// #endregion
</script>
Expand Down Expand Up @@ -382,9 +429,9 @@ function onOutAnchorDown() {
opacity: 1;
}
.in-anchor {
left: -12px;
}
// .in-anchor {
// left: -12px;
// }
.out-anchor {
right: -12px;
Expand Down
1 change: 1 addition & 0 deletions src/composables/useData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type rootProps from '@/components/root/rootProps';
import Variables from '@/constants/vars';
import type RowItem from '@/models/data/row';
import { useStore } from '@/store';
import { type RowData } from '@/typings/data';
import { isString } from 'lodash';
import { computed, type ExtractPropTypes, toRaw, watch, type Ref } from 'vue';
import useGanttHeader from './useGanttHeader';
Expand Down
14 changes: 7 additions & 7 deletions src/composables/useDrag.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useDraggable } from '@vueuse/core';
import { type Position, useDraggable } from '@vueuse/core';
import { type Ref, ref, computed, onMounted, nextTick } from 'vue';
import useElement from './useElement';
import useParam from './useParam';
Expand All @@ -8,9 +8,9 @@ const lineLeft = ref(0);
const mousedown = ref(false);

interface DragOptions {
onStart?: (pos: { x: number; y: number }, e: MouseEvent) => void;
onMove?: (x: number, e: MouseEvent) => void;
onEnd?: (x: number, e: MouseEvent) => Promise<void> | void;
onStart?: (pos: Position, e: PointerEvent) => void;
onMove?: (x: number, pos: Position, e: PointerEvent) => void;
onEnd?: (x: number, pos: Position, e: PointerEvent) => Promise<void> | void;
onFinally?: () => void;
target?: El;
reset?: boolean;
Expand Down Expand Up @@ -51,14 +51,14 @@ export default () => {
isMove.value = true;

left.value = e.clientX - delta.value;
options?.onMove?.(left.value, e);
options?.onMove?.(left.value, pos, e);
},

onEnd: (pos, e) => {
if (options.disabled?.()) return;

mousedown.value = false;
if (isMove.value) void options?.onEnd?.(left.value, e);
if (isMove.value) void options?.onEnd?.(left.value, pos, e);

options?.onFinally?.();
}
Expand Down Expand Up @@ -88,7 +88,7 @@ export default () => {
onDrag(el, {
reset: true,

onMove: (x, e) => {
onMove: (x, pos, e) => {
const clientX = e.clientX - (rootRect?.left ?? 0);
if (options?.preMove && !options?.preMove(x, clientX)) return;

Expand Down
Loading

0 comments on commit 567eedd

Please sign in to comment.