Skip to content

Commit 8101681

Browse files
committed
chore: 独立了卡片定位时间和飞入时间,添加了定位完成后的事件
1 parent 609c47b commit 8101681

File tree

8 files changed

+79
-51
lines changed

8 files changed

+79
-51
lines changed

‎README.md‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,23 @@ data: {
6161
| `breakpoints` | `Object` | {<br>1200:{rowPerView:3},<br>800:{rowPerView:2},<br>500:{rowPerView:1}<br>} | 类似css的@media, ���义不同容器宽度下每行卡片个数,主要用于对移动端的适配 |
6262
| `gutter` | `Number` | `10` | 卡片之间的间隙 |
6363
| `hasAroundGutter` | `Boolean` | `true` | 容器四周是否有 `gutter` 边距 |
64+
| `posDuration` | `Number` | `300` | 卡片移动到正确位置的动画时间 |
6465
| `animationPrefix` | `String` | `animate__animated` | 详情见下文《动画样式》 |
6566
| `animationEffect` | `String` | `fadeIn` | 卡片入场动画,默认只有 `fadeIn`,引入 `animation.css` 后可使用其他动画 |
66-
| `animationDuration` | `Number` | `1000` | 动画执行时间(单位毫秒),该动画时间只影响卡片重拍的时间,一般情况都不用修改,如果想要修改飞入动画的执行时间,见下文|
67-
| `animationDelay` | `Number` | `300` | 动画延迟(单位毫秒)|
67+
| `animationDuration` | `Number` | `1000` | 卡片入场动画执行时间(单位毫秒),该动画时间只影响卡片重拍的时间,一般情况都不用修改,如果想要修改飞入动画的执行时间,见下文|
68+
| `animationDelay` | `Number` | `300` | 卡片入场动画延迟(单位毫秒)|
6869
| `backgroundColor` | `String` | `#ffffff` | 背景颜色 |
6970
| `loadProps` | `Object` | `loadProps` | 懒加载图片组件的属性设置,详情见下文《懒加载属性》 |
7071
| `lazyload` | `Boolean` | `true` | 是否开启懒加载 |
7172
| `crossOrigin` | `Boolean` | `true` | 图片加载是否开启跨域 |
7273
| `delay` | `Number` | `300` | 布局刷新的防抖时间,默认 `300ms` 内没有再次触发才刷新布局。(图片加载���成;容器大小、`list``width``gutter``hasAroundGutter`变化时均会触发刷新) |
7374
| `align` | `String` | `center` | 卡片的对齐方式,可选值为:`left`,`center`,`right` |
7475

76+
## `WaterfallList` 方法
77+
| 方法名字 | 返回值类型 | 描述 |
78+
| --------- | --------- | -------------- |
79+
| `afterRender` | | 本次卡片坐标计算完成并且移动到了对应位置(列表渲染的过程可能会多次触发,比如有一张图片加载完成就会重新计算位置) |
80+
7581
## `LazyImg` 方法
7682
| 方法名字 | 返回值类型 | 描述 |
7783
| --------- | --------- | -------------- |
@@ -89,6 +95,7 @@ waterfall.value.renderer()
8995
`WaterFall`组件向外暴露了一个`renderer`函数,可以直接调用,该方法可以主动重绘列表,使用其他懒加载图片组件的回调函数里可以调用这个renderer来重绘。
9096

9197
## 动画样式
98+
首先需要明白,这里的动画指的是数据插入时的动画,比如第一次加载数据已经加载更多的时候的一个插入动画。
9299
想要使用动画必须引入`animate.css`或者定义一个动画`className`
93100
1. 如果引入了`animate.css`,并且版本是`4.x.x`及以上,可以不作任何处理
94101
2. 如果引入了`animate.css`,并且是老版���则需要将`animationPrefix`设置为`animated`

‎example/components/WaterfallApp.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ const options = reactive({
112112
},
113113
// 是否懒加载
114114
lazyload: true,
115-
align: 'right',
115+
align: 'center',
116116
})
117117
118118
const dialogVisible = ref(false)

‎example/components/WaterfallList.vue‎

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @FilePath: /vue3-waterfall/example/components/WaterfallList.vue
66
-->
77
<template>
8-
<div style="width:100%">
8+
<div v-loading="loading" style="min-height: 100%; width:100%">
99
<Waterfall
1010
:list="list"
1111
:row-key="options.rowKey"
@@ -22,6 +22,7 @@
2222
:load-props="options.loadProps"
2323
:cross-origin="options.crossOrigin"
2424
:align="options.align"
25+
@afterRender="afterRender"
2526
>
2627
<template #item="{ item, url, index }">
2728
<div class="bg-gray-900 rounded-lg shadow-md overflow-hidden transition-all duration-300 ease-linear hover:shadow-lg hover:shadow-gray-600 group" @click="handleClick(item)">
@@ -47,7 +48,7 @@
4748
</template>
4849
</Waterfall>
4950

50-
<div class="flex justify-center py-10 bg-gray-900">
51+
<div v-show="!loading" class="flex justify-center py-10 bg-gray-900">
5152
<button class="px-5 py-2 rounded-full bg-gray-700 text-md text-white cursor-pointer hover:bg-gray-800 transition-all duration-300" @click="handleLoadMore">
5253
加载更多
5354
</button>
@@ -84,6 +85,7 @@ const emits = defineEmits({
8485
// 列表
8586
const list = ref<ViewCard[]>([])
8687
const page = ref(1)
88+
const loading = ref(true)
8789
8890
onMounted(() => {
8991
handleLoadMore()
@@ -118,7 +120,12 @@ function imageError(url: string) {
118120
}
119121
120122
function imageSuccess(url: string) {
121-
// console.log(`${url}: 加载成功`)
123+
console.log(`${url}: 加载成功`)
124+
}
125+
126+
function afterRender() {
127+
loading.value = false
128+
console.log('计算完成')
122129
}
123130
</script>
124131

‎lib/components/Waterfall.vue‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ export default defineComponent({
7373
type: Boolean,
7474
default: true,
7575
},
76+
posDuration: {
77+
type: Number,
78+
default: 300,
79+
},
7680
animationPrefix: {
7781
type: String,
7882
default: 'animate__animated',
@@ -115,7 +119,7 @@ export default defineComponent({
115119
},
116120
},
117121
118-
setup(props) {
122+
setup(props, ctx) {
119123
const lazy: LazyType = new Lazy(props.lazyload, props.loadProps, props.crossOrigin)
120124
provide('lazy', lazy)
121125
@@ -139,7 +143,9 @@ export default defineComponent({
139143
140144
// 1s内最多执行一次排版,减少性能开销
141145
const renderer = useDebounceFn(() => {
142-
layoutHandle()
146+
layoutHandle().then(() => {
147+
ctx.emit('afterRender')
148+
})
143149
}, props.delay)
144150
145151
// 列表发生变化直接触发排版

‎lib/types/waterfall.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export type Breakpoints = Record<number, Point>
2222
export interface WaterfallProps {
2323
breakpoints: Breakpoints
2424
width: number
25+
posDuration: number
2526
animationDuration: number
2627
animationDelay: number
2728
animationEffect: string

‎lib/use/useLayout.ts‎

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -35,52 +35,60 @@ export function useLayout(props: WaterfallProps, colWidth: Ref<number>, cols: Re
3535
const animation = addAnimation(props)
3636

3737
// 排版
38-
const layoutHandle = async() => {
38+
const layoutHandle = async(): Promise<boolean> => {
39+
return new Promise((resolve) => {
3940
// 初始化y集合
40-
initY()
41-
42-
// 构造列表
43-
const items: HTMLElement[] = []
44-
if (waterfallWrapper && waterfallWrapper.value) {
45-
waterfallWrapper.value.childNodes.forEach((el: any) => {
46-
if (el!.className === 'waterfall-item')
47-
items.push(el)
48-
})
49-
}
41+
initY()
42+
43+
// 构造列表
44+
const items: HTMLElement[] = []
45+
if (waterfallWrapper && waterfallWrapper.value) {
46+
waterfallWrapper.value.childNodes.forEach((el: any) => {
47+
if (el!.className === 'waterfall-item')
48+
items.push(el)
49+
})
50+
}
51+
52+
// 获取节点
53+
if (items.length === 0) return false
5054

51-
// 获取节点
52-
if (items.length === 0) return false
55+
// 遍历节点
56+
for (let i = 0; i < items.length; i++) {
57+
const curItem = items[i] as HTMLElement
58+
// 最小的y值
59+
const minY = Math.min.apply(null, posY.value)
60+
// 最小y的下标
61+
const minYIndex = posY.value.indexOf(minY)
62+
// 当前下标对应的x
63+
const curX = getX(minYIndex)
5364

54-
// 遍历节点
55-
for (let i = 0; i < items.length; i++) {
56-
const curItem = items[i] as HTMLElement
57-
// 最小的y值
58-
const minY = Math.min.apply(null, posY.value)
59-
// 最小y的下标
60-
const minYIndex = posY.value.indexOf(minY)
61-
// 当前下标对应的x
62-
const curX = getX(minYIndex)
65+
// 设置x,y,width
66+
const style = curItem.style as CssStyleObject
6367

64-
// 设置x,y,width
65-
const style = curItem.style as CssStyleObject
68+
// 设置偏移
69+
if (transform) style[transform] = `translate3d(${curX}px,${minY}px, 0)`
70+
style.width = `${colWidth.value}px`
6671

67-
// 设置偏移
68-
if (transform) style[transform] = `translate3d(${curX}px,${minY}px, 0)`
69-
style.width = `${colWidth.value}px`
72+
style.visibility = 'visible'
7073

71-
// 更新当前index的y值
72-
const { height } = curItem.getBoundingClientRect()
73-
posY.value[minYIndex] += height + props.gutter
74+
// 更新当前index的y值
75+
const { height } = curItem.getBoundingClientRect()
76+
posY.value[minYIndex] += height + props.gutter
7477

75-
// 添加入场动画
76-
animation(curItem, () => {
78+
// 添加入场动画
79+
animation(curItem, () => {
7780
// 添加动画时间
78-
const time = props.animationDuration / 1000
79-
if (transition) style[transition] = `transform ${time}s`
80-
})
81-
}
81+
const time = props.posDuration / 1000
82+
if (transition) style[transition] = `transform ${time}s`
83+
})
84+
}
85+
86+
wrapperHeight.value = Math.max.apply(null, posY.value)
8287

83-
wrapperHeight.value = Math.max.apply(null, posY.value)
88+
setTimeout(() => {
89+
resolve(true)
90+
}, props.posDuration)
91+
})
8492
}
8593

8694
return {
@@ -97,7 +105,9 @@ function addAnimation(props: WaterfallProps) {
97105
const durationSec = `${props.animationDuration / 1000}s`
98106
const delaySec = `${props.animationDelay / 1000}s`
99107
const style = content.style as CssStyleObject
100-
style.visibility = 'visible'
108+
addClass(content, props.animationPrefix)
109+
addClass(content, props.animationEffect)
110+
101111
if (duration)
102112
style[duration] = durationSec
103113

@@ -107,9 +117,6 @@ function addAnimation(props: WaterfallProps) {
107117
if (fillMode)
108118
style[fillMode] = 'both'
109119

110-
addClass(content, props.animationPrefix)
111-
addClass(content, props.animationEffect)
112-
113120
if (callback) {
114121
setTimeout(() => {
115122
callback()

‎lib/utils/dom.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,11 @@ const elementStyle = document.createElement('div').style as CssStyleObject
3131

3232
const vendor = (() => {
3333
const transformNames: Record<string, string> = {
34+
standard: 'transform',
3435
webkit: 'webkitTransform',
3536
Moz: 'MozTransform',
3637
O: 'OTransform',
3738
ms: 'msTransform',
38-
standard: 'transform',
3939
}
4040

4141
for (const key in transformNames) {

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-waterfall-plugin-next",
3-
"version": "2.3.1",
3+
"version": "2.4.1",
44
"license": "UNLICENSED",
55
"author": "Yaowen Liu <576079353@qq.com>",
66
"main": "dist/my-lib.umd.js",

0 commit comments

Comments
 (0)