Skip to content

Commit

Permalink
[docs] 优化 move 工具方法文档演示动画
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhang-Wei-666 committed Aug 9, 2023
1 parent d4a95ce commit cc45ec0
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 26 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"eslint": "^8.46.0",
"fast-glob": "^3.3.1",
"fs-extra": "^11.1.1",
"gsap": "^3.12.2",
"jsdom": "^22.1.0",
"lint-staged": "^13.2.3",
"magic-string": "^0.30.2",
Expand Down
97 changes: 72 additions & 25 deletions packages/mixte/src/move/demo/move.vue
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
<template>
<TransitionGroup ref="containerRef" tag="div" move-class="move-item" text-sm flex="~ gap-2 wrap" mt-5>
<template v-for="(num, index) in array" :key="num">
<div
ref="itemsRef"
:class="{ 'jump': index === to, 'will-move': [from, to].includes(index) }" :data-index="index"
size-8 flex="~ items-center justify-center" transition="all duration-360" bg-teal-3 el-2
>
{{ num }}
</div>
</template>
</TransitionGroup>
<div ref="containerRef" text-sm flex="~ gap-2 wrap" mt-5>
<div
v-for="(num, index) in array" :key="index"
ref="itemsRef"
:class="{ 'will-move': [from, to].includes(index) }" :data-index="index"
size-8 flex="~ items-center justify-center" bg-teal-3 el-2
>
{{ num }}
</div>
</div>

<div flex="~ items-center gap-3" mt-10>
<div text-sm grid="~ cols-[auto_1fr] items-center gap-(x2 y1)">
from: <el-input-number v-model="from" class="w-32!" controls-position="right" :min="0" :max="array.length - 1" />
to: <el-input-number v-model="to" class="w-32!" controls-position="right" :min="0" :max="array.length - 1" />
from: <el-input-number v-model="from" class="w-32!" :disabled="isMove" controls-position="right" :min="0" :max="array.length - 1" />
to: <el-input-number v-model="to" class="w-32!" :disabled="isMove" controls-position="right" :min="0" :max="array.length - 1" />
</div>
<button m-btn @click="move(array, from, to)">移动</button>
<el-button class="c-white!" color="#14b8a6" :disabled="isMove" @click="toMove">移动</el-button>
</div>

<div ref="fromFloatingRef" m-popover :style="fromFloatingStyles">from</div>
<div ref="toFloatingRef" m-popover :style="toFloatingStyles">to</div>
</template>

<script lang="ts" setup>
import { move } from 'mixte';
import { delay, move } from 'mixte';
import { gsap } from 'gsap';
import { offset, useFloating } from '@floating-ui/vue';
const containerRef = ref<HTMLElement>();
const itemsRef = ref<HTMLElement[]>([]);
const fromFloatingRef = ref<HTMLElement>();
const toFloatingRef = ref<HTMLElement>();
const itemsRef = ref<HTMLElement[]>([]);
const itemsSortRef = computed(() => itemsRef.value.sort((a, b) => Number(a.dataset.index) - Number(b.dataset.index)));
const array = reactive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
const from = ref(0);
const to = ref(5);
const from = ref(10);
const to = ref(2);
const fromRef = computed(() => itemsRef.value.find(item => item.dataset.index === `${from.value}`));
const toRef = computed(() => itemsRef.value.find(item => item.dataset.index === `${to.value}`));
Expand All @@ -48,18 +49,64 @@
middleware: [offset(6)],
});
const isMove = ref(false);
function toMove() {
isMove.value = true;
const fromEl = fromRef.value!;
const [fromV, toV] = [from.value, to.value];
const [max, min] = [fromV, toV].sort((a, b) => b - a);
const itemsBounding = itemsSortRef.value.map(item => item.getBoundingClientRect());
const range = itemsSortRef.value
.map((el, index) => [el, itemsBounding[index]!, itemsBounding[index + (index > fromV ? -1 : 1)]!])
.filter(([el], index) => el !== fromEl && index >= min && index <= max) as [HTMLElement, DOMRect, DOMRect][];
const rangeTl = gsap.timeline();
let rangeIndex = 0;
if (fromV > toV) range.reverse();
// 移动到目标位置上方
gsap.to(fromEl, {
x: itemsBounding[toV]!.x - itemsBounding[fromV]!.x,
y: itemsBounding[toV]!.y - itemsBounding[fromV]!.y - 50,
zIndex: 6,
duration: Math.max(range.length / 10, 0.5),
ease: 'circ.out',
});
// 移动范围内的元素
range.forEach(([el, fromBounding, toBounding]) => {
rangeTl.to(el, {
x: toBounding.x - fromBounding.x,
y: toBounding.y - fromBounding.y,
duration: 0.07,
delay: (rangeIndex++) ? 0 : 0.3,
});
});
// 移动到目标位置
rangeTl.to(fromEl, {
y: itemsBounding[toV]!.y - itemsBounding[fromV]!.y,
ease: 'circ.in',
duration: 0.3,
delay: 0.1,
onComplete() {
delay(300).then(() => {
itemsSortRef.value.filter((_, i) => i >= min && i <= max).forEach(el => gsap.set(el, { x: 0, y: 0, zIndex: 'auto' }));
move(array, fromV, toV);
isMove.value = false;
});
},
});
}
watch(useElementSize(containerRef).width, () => {
fromFloatingUpdate();
toFloatingUpdate();
});
</script>

<style lang="sass" scoped>
.move-item.jump
@apply -translate-y-8 z-1
.will-move
@apply relative
&::before
@apply content-[''] size-10 absolute b-(1 dashed gray rounded) z-666
.will-move::before
@apply content-[''] size-10 absolute b-(1 dashed gray rounded) z-1
</style>
2 changes: 1 addition & 1 deletion packages/unocss.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineConfig({
'm-box-b': 'flex-(~ items-center justify-center) rounded b-(1 solid neutral-3)',

// 按钮
'm-btn': 'm-box flex-none bg-teal-5 c-white rounded-1 p-(1.5 x-3) active:bg-teal-6/90 disabled:cursor-not-allowed',
'm-btn': 'm-box flex-none bg-teal-5 c-white rounded-1 p-(1.5 x-3) hover:bg-teal-5/80 active:bg-teal-6/90 disabled:cursor-not-allowed',

// 输入框
'm-input': 'lh-none b-(1 solid neutral-3 rounded-1) p-(2 x-3)',
Expand Down
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit cc45ec0

Please sign in to comment.