tencent.jquery.pix.component 1.0.61 → 1.0.63-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/waterfall/waterfall.js +296 -71
- package/package.json +1 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getEnv } from "../config.js";
|
|
2
2
|
import { remToPx } from "../../utils/utils.js";
|
|
3
3
|
|
|
4
|
+
let $ = null;
|
|
5
|
+
|
|
4
6
|
// 默认配置
|
|
5
7
|
const DEFAULTS = {
|
|
6
8
|
columns: 2, // 列数
|
|
@@ -20,12 +22,20 @@ const DEFAULTS = {
|
|
|
20
22
|
};
|
|
21
23
|
|
|
22
24
|
export function Waterfall(optionsInput = {}) {
|
|
25
|
+
$ = getEnv().$;
|
|
26
|
+
|
|
23
27
|
this.options = Object.assign({}, DEFAULTS, optionsInput);
|
|
24
28
|
const options = this.options;
|
|
25
29
|
const $container = $(options.container);
|
|
26
30
|
// 标记是否有更新元素用的回调函数
|
|
27
31
|
this.hasUpdateItem = options.updateItem && (options.updateItem.constructor === Function) ? true : false;
|
|
28
32
|
|
|
33
|
+
// 新方案:数据ID映射机制
|
|
34
|
+
this.dataIdMap = new Map(); // 数据ID -> 布局信息映射
|
|
35
|
+
this.nextDataId = 0; // 下一个数据ID
|
|
36
|
+
this.renderedDataIds = new Set(); // 已渲染的数据ID集合
|
|
37
|
+
|
|
38
|
+
|
|
29
39
|
// 间隔字符串转数字
|
|
30
40
|
if (options.columnGap.constructor === String) {
|
|
31
41
|
// 如果是rem单位,则需要计算
|
|
@@ -81,13 +91,29 @@ export function Waterfall(optionsInput = {}) {
|
|
|
81
91
|
this.columnItems.push(this.createColumn(i));
|
|
82
92
|
}
|
|
83
93
|
|
|
84
|
-
this.renderIndex = 0; //
|
|
85
|
-
this.activeNodes = new Map(); //
|
|
94
|
+
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
95
|
+
this.activeNodes = new Map(); // 当前活跃节点(数据ID -> DOM)
|
|
86
96
|
this.nodePool = []; // DOM 节点池
|
|
87
97
|
|
|
98
|
+
// 新方案:初始化数据ID映射
|
|
99
|
+
this.dataIdMap = new Map(); // 数据ID -> 布局信息映射
|
|
100
|
+
this.nextDataId = 0; // 下一个数据ID
|
|
101
|
+
this.renderedDataIds = new Set(); // 已渲染的数据ID集合
|
|
102
|
+
|
|
103
|
+
// 为初始数据分配数据ID
|
|
104
|
+
this.options.data.forEach((item, index) => {
|
|
105
|
+
const dataId = index; //this.nextDataId++;
|
|
106
|
+
this.dataIdMap.set(dataId, {
|
|
107
|
+
data: item,
|
|
108
|
+
originalIndex: index,
|
|
109
|
+
layoutInfo: null // 将在布局时填充
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
88
113
|
this.init();
|
|
89
114
|
}
|
|
90
115
|
|
|
116
|
+
|
|
91
117
|
Waterfall.prototype.init = function () {
|
|
92
118
|
const self = this;
|
|
93
119
|
const options = this.options;
|
|
@@ -95,6 +121,8 @@ Waterfall.prototype.init = function () {
|
|
|
95
121
|
|
|
96
122
|
this.nodePool = []; // DOM 节点池
|
|
97
123
|
this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
|
|
124
|
+
this.allReadyNodes = new Map(); // 所有节点(索引 -> DOM)
|
|
125
|
+
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
98
126
|
|
|
99
127
|
|
|
100
128
|
|
|
@@ -130,8 +158,9 @@ Waterfall.prototype.updateVisibleItems = function (force = false) {
|
|
|
130
158
|
const options = this.options;
|
|
131
159
|
const $container = $(options.container);
|
|
132
160
|
|
|
133
|
-
const startTop =
|
|
161
|
+
const startTop = self.scrollTop; // 当前滚动位置
|
|
134
162
|
const endTop = startTop + $container.height();
|
|
163
|
+
// console.log('startTop', startTop)
|
|
135
164
|
|
|
136
165
|
// 进行可见区域的渲染更新
|
|
137
166
|
this.updateCardsInView({
|
|
@@ -139,23 +168,41 @@ Waterfall.prototype.updateVisibleItems = function (force = false) {
|
|
|
139
168
|
end: endTop,
|
|
140
169
|
force
|
|
141
170
|
});
|
|
171
|
+
|
|
142
172
|
}
|
|
143
173
|
|
|
144
174
|
// 新增卡片
|
|
145
|
-
Waterfall.prototype.appendCard = function (data,
|
|
175
|
+
Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
|
|
146
176
|
const self = this;
|
|
147
177
|
const options = this.options;
|
|
148
178
|
const $container = $(options.container);
|
|
149
179
|
const $viewport = $container.find('.waterfall-list-viewport');
|
|
180
|
+
|
|
181
|
+
// 新方案:基于数据ID的数据验证
|
|
182
|
+
if (!this.dataIdMap.has(dataId)) {
|
|
183
|
+
console.error('Waterfall: Invalid dataId in appendCard', dataId);
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const dataInfo = this.dataIdMap.get(dataId);
|
|
188
|
+
if (!dataInfo || !dataInfo.data) {
|
|
189
|
+
console.warn('Waterfall: Empty data for dataId', dataId);
|
|
190
|
+
}
|
|
191
|
+
|
|
150
192
|
const $card = $(
|
|
151
193
|
`<div class="waterfall-item"
|
|
152
|
-
data-index="${
|
|
153
|
-
style="position: absolute;transform:translate(${left}px,${top}px);
|
|
194
|
+
data-index="${dataId}"
|
|
195
|
+
style="position: absolute;transform:translate(${left}px,${top}px);"
|
|
154
196
|
>
|
|
155
|
-
${options.renderItem(data,
|
|
197
|
+
${options.renderItem(data, dataInfo.originalIndex)}
|
|
156
198
|
</div> `
|
|
157
199
|
);
|
|
158
200
|
|
|
201
|
+
|
|
202
|
+
if (options.columns !== 1) {
|
|
203
|
+
$card.width(this.columnWidth + 'px');
|
|
204
|
+
}
|
|
205
|
+
|
|
159
206
|
$viewport.append($card);
|
|
160
207
|
return $card;
|
|
161
208
|
}
|
|
@@ -170,49 +217,100 @@ Waterfall.prototype.updateCardsInView = function ({ start, end, force = false })
|
|
|
170
217
|
this.createCards({ end: endBuffer });
|
|
171
218
|
}
|
|
172
219
|
|
|
173
|
-
|
|
174
|
-
|
|
220
|
+
const startNum = start - options.bufferHeight;
|
|
221
|
+
const endNum = end + options.bufferHeight;
|
|
222
|
+
// 新方案:基于数据ID映射机制
|
|
175
223
|
const newActiveNodes = new Map();
|
|
176
224
|
for (let i = 0; i < this.columns; i++) {
|
|
177
225
|
const column = this.columnItems[i];
|
|
178
226
|
|
|
179
227
|
for (let j = 0; j < column.children.length; j++) {
|
|
180
228
|
const row = column.children[j];
|
|
181
|
-
const
|
|
229
|
+
const dataId = row.dataId; // 使用dataId替代renderIndex
|
|
230
|
+
|
|
231
|
+
// 验证数据ID有效性
|
|
232
|
+
if (!this.dataIdMap.has(dataId)) {
|
|
233
|
+
console.warn('Waterfall: Invalid dataId detected', dataId);
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const dataInfo = this.dataIdMap.get(dataId);
|
|
238
|
+
|
|
239
|
+
if (!dataInfo) {
|
|
240
|
+
console.warn('Waterfall: Invalid data for dataId', dataId);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
const data = options.data[dataId]
|
|
245
|
+
|
|
182
246
|
// 在可视区域内 进行有关卡片的操作
|
|
183
|
-
|
|
247
|
+
const bool = row.top <= endNum && row.bottom >= startNum;
|
|
248
|
+
if (bool) {
|
|
184
249
|
// 理论上什么都不动,因为卡片的位置不会变
|
|
185
|
-
const $card = this.activeNodes.get(
|
|
250
|
+
const $card = this.activeNodes.get(dataId);
|
|
186
251
|
|
|
187
252
|
let $node = null;
|
|
188
|
-
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
// 遍历当前的节点是否被占用,如果被占用的话,就得要从nodePool中取一个
|
|
257
|
+
let bool = true;
|
|
189
258
|
if ($card) {
|
|
259
|
+
bool = hasNodeInActives(newActiveNodes, $card)
|
|
260
|
+
}
|
|
261
|
+
// 如果卡片已经在DOM中,则不用更新位置
|
|
262
|
+
if (bool === false) {
|
|
190
263
|
$node = $card;
|
|
191
|
-
this.activeNodes.delete(
|
|
264
|
+
this.activeNodes.delete(dataId);
|
|
265
|
+
// 如果是强更,这里才会采取更新
|
|
192
266
|
if (force) {
|
|
193
|
-
this.updateRenderUI($node,
|
|
267
|
+
this.updateRenderUI($node, data, dataId);
|
|
194
268
|
}
|
|
269
|
+
|
|
195
270
|
} else {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
271
|
+
const $card = this.allReadyNodes.get(dataId);
|
|
272
|
+
// 遍历当前的节点是否被占用,如果被占用的话,就得要从nodePool中取一个
|
|
273
|
+
let bool = true;
|
|
274
|
+
if ($card) {
|
|
275
|
+
bool = hasNodeInActives(newActiveNodes, $card)
|
|
276
|
+
}
|
|
277
|
+
if (bool === false) {
|
|
278
|
+
// 如果成功获取到card并没有占用 那么就复用这个card
|
|
279
|
+
$node = $card;
|
|
280
|
+
|
|
281
|
+
this.updateRenderUI($node, data, dataId);
|
|
282
|
+
|
|
205
283
|
} else {
|
|
206
|
-
|
|
207
|
-
$node.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
284
|
+
// 卡片不在DOM中,则更新位置
|
|
285
|
+
$node = getNodePoolPop(this.nodePool, newActiveNodes);
|
|
286
|
+
if ($node === null) {
|
|
287
|
+
// 这里是往上方拖动时,可能需要补建的情况
|
|
288
|
+
$node = this.appendCard(data, dataId, {
|
|
289
|
+
top: row.top, left: row.left
|
|
290
|
+
});
|
|
291
|
+
row.$node = $node;
|
|
292
|
+
} else {
|
|
293
|
+
//$node = $(this.nodePool.pop());
|
|
294
|
+
this.updateRenderUI($node, data, dataId);
|
|
295
|
+
row.$node = $node;
|
|
296
|
+
}
|
|
212
297
|
}
|
|
213
298
|
}
|
|
214
299
|
|
|
215
|
-
|
|
300
|
+
$node.css({
|
|
301
|
+
'transform': `translate(${row.left}px,${row.top}px)`,
|
|
302
|
+
}).attr('data-index', dataId);
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
newActiveNodes.set(dataId, $node);
|
|
306
|
+
|
|
307
|
+
// 清除掉在NodePool中的card
|
|
308
|
+
const index = this.nodePool.indexOf($card);
|
|
309
|
+
if (index !== -1) {
|
|
310
|
+
this.nodePool.splice(index, 1);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// console.log('302-row', row.dataId, dataInfo);
|
|
216
314
|
}
|
|
217
315
|
}
|
|
218
316
|
}
|
|
@@ -220,11 +318,16 @@ Waterfall.prototype.updateCardsInView = function ({ start, end, force = false })
|
|
|
220
318
|
// 阶段2:处理不活跃节点
|
|
221
319
|
this.activeNodes.forEach($node => {
|
|
222
320
|
$node.css('transform', `translateY(-9999px)`);// 移出可视区域
|
|
223
|
-
this.nodePool.
|
|
321
|
+
if (this.nodePool.indexOf($node) === -1) {
|
|
322
|
+
this.nodePool.push($node);
|
|
323
|
+
}
|
|
224
324
|
});
|
|
225
325
|
this.activeNodes = newActiveNodes;
|
|
326
|
+
// console.log('this.activeNodes', this.activeNodes);
|
|
327
|
+
// console.log('this.nodePool', this.nodePool);
|
|
226
328
|
}
|
|
227
329
|
|
|
330
|
+
|
|
228
331
|
Waterfall.prototype.getMaxHeight = function () {
|
|
229
332
|
let maxHeight = 0;
|
|
230
333
|
for (let i = 0; i < this.columns; i++) {
|
|
@@ -272,79 +375,99 @@ Waterfall.prototype.getMinHeightColumn = function () {
|
|
|
272
375
|
}
|
|
273
376
|
|
|
274
377
|
// 创建卡片
|
|
275
|
-
Waterfall.prototype.createCards = function ({ end }) {
|
|
378
|
+
Waterfall.prototype.createCards = function ({ end, dataId = -1 }) {
|
|
276
379
|
const self = this;
|
|
277
380
|
const options = this.options;
|
|
278
381
|
const $container = $(options.container);
|
|
279
|
-
const renderIndex = this.renderIndex;
|
|
280
382
|
|
|
281
|
-
|
|
383
|
+
// 新方案:获取下一个未渲染的数据ID
|
|
384
|
+
let nextDataId = null;
|
|
385
|
+
for (let [dataId, dataInfo] of this.dataIdMap) {
|
|
386
|
+
if (!this.renderedDataIds.has(dataId)) {
|
|
387
|
+
nextDataId = dataId;
|
|
388
|
+
break;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// 如果没有更多数据需要渲染
|
|
393
|
+
if (nextDataId === null) {
|
|
282
394
|
const maxHeight = this.getMaxHeight();
|
|
283
|
-
|
|
284
|
-
$(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom)
|
|
395
|
+
$container.find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
|
|
285
396
|
return;
|
|
286
397
|
}
|
|
287
398
|
|
|
399
|
+
const dataInfo = this.dataIdMap.get(nextDataId);
|
|
400
|
+
if (!dataInfo || !dataInfo.data) {
|
|
401
|
+
console.warn('Waterfall: Invalid data for dataId', nextDataId);
|
|
402
|
+
this.renderedDataIds.add(nextDataId);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
if (this.renderIndex >= this.options.data.length) {
|
|
407
|
+
return
|
|
408
|
+
}
|
|
409
|
+
|
|
288
410
|
let column = this.getMinHeightColumn();
|
|
289
411
|
if (column === null) {
|
|
290
|
-
// 没有可用的列,则在第一列创建,说明此时还没有数据
|
|
291
412
|
column = this.columnItems[0];
|
|
292
413
|
}
|
|
293
414
|
|
|
294
415
|
const top = column.bottom === 0 ? options.marginTop : (column.bottom + options.rowGap);
|
|
295
|
-
|
|
296
|
-
// 设置卡片位置
|
|
297
|
-
const position = {
|
|
298
|
-
top,
|
|
299
|
-
left: column.left,
|
|
300
|
-
}
|
|
301
|
-
|
|
416
|
+
const position = { top, left: column.left };
|
|
302
417
|
const row = createDefaultRow(position);
|
|
303
418
|
|
|
419
|
+
this.renderIndex += 1;
|
|
304
420
|
|
|
305
|
-
//
|
|
421
|
+
// 添加卡片,使用dataId作为唯一标识
|
|
306
422
|
let $card = null;
|
|
307
423
|
if (this.nodePool.length === 0) {
|
|
308
|
-
$card = this.appendCard(
|
|
424
|
+
$card = this.appendCard(dataInfo.data, nextDataId, position);
|
|
309
425
|
} else {
|
|
310
426
|
$card = $(this.nodePool.pop());
|
|
311
427
|
$card.css({
|
|
312
428
|
'transform': `translate(${row.left}px,${row.top}px)`,
|
|
313
|
-
}).attr('data-index',
|
|
314
|
-
this.updateRenderUI($card,
|
|
429
|
+
}).attr('data-index', nextDataId);
|
|
430
|
+
this.updateRenderUI($card, dataInfo.data, nextDataId);
|
|
315
431
|
}
|
|
316
432
|
|
|
317
|
-
|
|
318
433
|
row.$node = $card;
|
|
434
|
+
row.dataId = nextDataId; // 使用dataId替代renderIndex
|
|
435
|
+
if (dataId !== -1) {
|
|
436
|
+
row.dataId = dataId;
|
|
437
|
+
}
|
|
319
438
|
|
|
320
|
-
//
|
|
321
|
-
|
|
439
|
+
// 记录布局信息
|
|
440
|
+
dataInfo.layoutInfo = {
|
|
441
|
+
columnIndex: this.columnItems.indexOf(column),
|
|
442
|
+
position: position,
|
|
443
|
+
row: row
|
|
444
|
+
};
|
|
322
445
|
|
|
446
|
+
// 把新增的卡片放进 activeNodes
|
|
447
|
+
this.activeNodes.set(nextDataId, $card);
|
|
448
|
+
this.allReadyNodes.set(nextDataId, $card);
|
|
449
|
+
this.renderedDataIds.add(nextDataId);
|
|
323
450
|
|
|
324
451
|
// 更新列的底部距离
|
|
325
452
|
column.bottom = top + $card.height();
|
|
326
453
|
column.children.push(row);
|
|
327
|
-
|
|
328
|
-
// 计算当前卡片的位置
|
|
329
454
|
row.bottom = column.bottom;
|
|
330
|
-
row.renderIndex = renderIndex;
|
|
331
|
-
|
|
332
|
-
this.renderIndex += 1;
|
|
333
|
-
|
|
334
|
-
let hasNextData = this.renderIndex < options.data.length;
|
|
335
455
|
|
|
456
|
+
// 检查是否需要继续创建卡片
|
|
336
457
|
const minHeight = this.getMinHeight();
|
|
337
|
-
|
|
458
|
+
const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
|
|
459
|
+
|
|
460
|
+
if (hasMoreData && (minHeight < end)) {
|
|
338
461
|
window.requestAnimationFrame(() => {
|
|
339
462
|
this.createCards({ end });
|
|
340
463
|
});
|
|
341
464
|
} else {
|
|
342
465
|
const maxHeight = this.getMaxHeight();
|
|
343
|
-
|
|
344
|
-
$(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom)
|
|
466
|
+
$(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom);
|
|
345
467
|
}
|
|
346
468
|
}
|
|
347
469
|
|
|
470
|
+
|
|
348
471
|
Waterfall.prototype.createColumn = function (index) {
|
|
349
472
|
const res = {
|
|
350
473
|
left: 0,
|
|
@@ -361,33 +484,135 @@ Waterfall.prototype.createColumn = function (index) {
|
|
|
361
484
|
return res;
|
|
362
485
|
}
|
|
363
486
|
|
|
364
|
-
Waterfall.prototype.updateRenderUI = function ($node, data,
|
|
487
|
+
Waterfall.prototype.updateRenderUI = function ($node, data, dataId) {
|
|
365
488
|
const options = this.options;
|
|
489
|
+
|
|
490
|
+
// 新方案:基于数据ID的数据验证
|
|
491
|
+
if (!this.dataIdMap.has(dataId)) {
|
|
492
|
+
console.error('Waterfall: Invalid dataId in updateRenderUI', dataId);
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
const dataInfo = this.dataIdMap.get(dataId);
|
|
497
|
+
if (!dataInfo || !dataInfo.data) {
|
|
498
|
+
console.warn('Waterfall: Empty data for dataId', dataId);
|
|
499
|
+
}
|
|
500
|
+
|
|
366
501
|
if (this.hasUpdateItem === true) {
|
|
367
|
-
options.updateItem($node, data,
|
|
502
|
+
options.updateItem($node, data, dataInfo.originalIndex)
|
|
368
503
|
} else {
|
|
369
|
-
$node.html(options.renderItem(data,
|
|
504
|
+
$node.html(options.renderItem(data, dataInfo.originalIndex));
|
|
370
505
|
}
|
|
371
506
|
}
|
|
372
507
|
|
|
508
|
+
|
|
509
|
+
|
|
373
510
|
Waterfall.prototype.updateData = function (newData) {
|
|
374
|
-
|
|
511
|
+
const options = this.options;
|
|
512
|
+
options.data = newData;
|
|
513
|
+
|
|
514
|
+
// 新方案:重新建立数据ID映射
|
|
515
|
+
//this.dataIdMap.clear();
|
|
516
|
+
//this.renderedDataIds.clear();
|
|
517
|
+
//this.nextDataId = 0;
|
|
518
|
+
|
|
519
|
+
// 为每个数据项分配唯一ID
|
|
520
|
+
options.data.forEach((item, index) => {
|
|
521
|
+
const dataId = index; // this.nextDataId++;
|
|
522
|
+
if (!this.allReadyNodes.has(dataId)) {
|
|
523
|
+
this.dataIdMap.set(dataId, {
|
|
524
|
+
data: item,
|
|
525
|
+
originalIndex: index,
|
|
526
|
+
layoutInfo: null // 将在布局时填充
|
|
527
|
+
});
|
|
528
|
+
// 如果没有准备好这个数据,这里要创建一个占位节点
|
|
529
|
+
this.createCards({ end: 0, dataId });
|
|
530
|
+
}
|
|
531
|
+
});
|
|
532
|
+
|
|
375
533
|
this.updateVisibleItems(true); // 强制更新渲染
|
|
534
|
+
|
|
535
|
+
// 重新计算所有卡片位置并更新位置
|
|
536
|
+
// this.updatePointCards();
|
|
376
537
|
}
|
|
377
538
|
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
// 重新计算设置一遍所有的卡片位置
|
|
542
|
+
Waterfall.prototype.updatePointCards = function () {
|
|
543
|
+
const self = this;
|
|
544
|
+
const options = this.options;
|
|
545
|
+
const columnItems = this.columnItems;
|
|
546
|
+
let top = options.marginTop;
|
|
547
|
+
for (let i = 0; i < columnItems.length; i++) {
|
|
548
|
+
const column = columnItems[i];
|
|
549
|
+
// 这里为了简化,各列的瀑布流保持不动,只更新各列下节点的top位置,不做节点的跨列位移
|
|
550
|
+
for (let j = 0; j < column.children.length; j++) {
|
|
551
|
+
const row = column.children[j];
|
|
552
|
+
const $card = row.$node;
|
|
553
|
+
|
|
554
|
+
// 验证数据ID有效性
|
|
555
|
+
if (!this.dataIdMap.has(row.dataId)) {
|
|
556
|
+
console.warn('Waterfall: Invalid dataId in updatePointCards', row.dataId);
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// 第一个的top不需要更新
|
|
561
|
+
if (j === 0) {
|
|
562
|
+
row.bottom = top + $card.height();
|
|
563
|
+
} else {
|
|
564
|
+
row.top = column.children[j - 1].bottom + options.rowGap;
|
|
565
|
+
row.bottom = row.top + $card.height();
|
|
566
|
+
// 更新卡片位置
|
|
567
|
+
// $card.css({
|
|
568
|
+
// 'transform': `translate(${row.left}px,${row.top}px)`,
|
|
569
|
+
// })
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
}
|
|
573
|
+
// 设置一次该列的bottom
|
|
574
|
+
column.bottom = getBottomByColumn(column);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
|
|
378
579
|
function createDefaultRow({ top, left }) {
|
|
379
580
|
return {
|
|
380
581
|
top,
|
|
381
582
|
left,
|
|
382
583
|
bottom: 0,
|
|
383
584
|
$node: null,
|
|
384
|
-
|
|
585
|
+
dataId: -1 // 新方案:使用dataId替代renderIndex
|
|
385
586
|
}
|
|
386
587
|
}
|
|
387
588
|
|
|
388
|
-
|
|
389
|
-
|
|
589
|
+
|
|
590
|
+
function getBottomByColumn(column) {
|
|
591
|
+
if (column.children.length === 0) {
|
|
390
592
|
return 0;
|
|
391
593
|
}
|
|
392
|
-
|
|
594
|
+
const child = column.children;
|
|
595
|
+
return child[child.length - 1].bottom;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
function hasNodeInActives(mapObj, $node) {
|
|
599
|
+
let bool = false
|
|
600
|
+
mapObj.forEach((item) => {
|
|
601
|
+
if (item === $node) {
|
|
602
|
+
bool = true;
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
return bool;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// 从众多jq对象数组取得一个不重复的
|
|
609
|
+
function getNodePoolPop(nodePool, actives) {
|
|
610
|
+
for (let i = 0; i < nodePool.length; i++) {
|
|
611
|
+
const $node = nodePool[i];
|
|
612
|
+
if (!hasNodeInActives(actives, $node)) {
|
|
613
|
+
nodePool.splice(i, 1);
|
|
614
|
+
return $node;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
return null;
|
|
393
618
|
}
|