tencent.jquery.pix.component 1.0.62 → 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 +292 -71
- package/package.json +1 -1
|
@@ -22,7 +22,7 @@ const DEFAULTS = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
export function Waterfall(optionsInput = {}) {
|
|
25
|
-
$ = getEnv()
|
|
25
|
+
$ = getEnv().$;
|
|
26
26
|
|
|
27
27
|
this.options = Object.assign({}, DEFAULTS, optionsInput);
|
|
28
28
|
const options = this.options;
|
|
@@ -30,6 +30,12 @@ export function Waterfall(optionsInput = {}) {
|
|
|
30
30
|
// 标记是否有更新元素用的回调函数
|
|
31
31
|
this.hasUpdateItem = options.updateItem && (options.updateItem.constructor === Function) ? true : false;
|
|
32
32
|
|
|
33
|
+
// 新方案:数据ID映射机制
|
|
34
|
+
this.dataIdMap = new Map(); // 数据ID -> 布局信息映射
|
|
35
|
+
this.nextDataId = 0; // 下一个数据ID
|
|
36
|
+
this.renderedDataIds = new Set(); // 已渲染的数据ID集合
|
|
37
|
+
|
|
38
|
+
|
|
33
39
|
// 间隔字符串转数字
|
|
34
40
|
if (options.columnGap.constructor === String) {
|
|
35
41
|
// 如果是rem单位,则需要计算
|
|
@@ -85,13 +91,29 @@ export function Waterfall(optionsInput = {}) {
|
|
|
85
91
|
this.columnItems.push(this.createColumn(i));
|
|
86
92
|
}
|
|
87
93
|
|
|
88
|
-
this.renderIndex = 0; //
|
|
89
|
-
this.activeNodes = new Map(); //
|
|
94
|
+
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
95
|
+
this.activeNodes = new Map(); // 当前活跃节点(数据ID -> DOM)
|
|
90
96
|
this.nodePool = []; // DOM 节点池
|
|
91
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
|
+
|
|
92
113
|
this.init();
|
|
93
114
|
}
|
|
94
115
|
|
|
116
|
+
|
|
95
117
|
Waterfall.prototype.init = function () {
|
|
96
118
|
const self = this;
|
|
97
119
|
const options = this.options;
|
|
@@ -99,6 +121,8 @@ Waterfall.prototype.init = function () {
|
|
|
99
121
|
|
|
100
122
|
this.nodePool = []; // DOM 节点池
|
|
101
123
|
this.activeNodes = new Map(); // 当前活跃节点(索引 -> DOM)
|
|
124
|
+
this.allReadyNodes = new Map(); // 所有节点(索引 -> DOM)
|
|
125
|
+
this.renderIndex = 0; // 渲染索引(保留兼容性)
|
|
102
126
|
|
|
103
127
|
|
|
104
128
|
|
|
@@ -134,8 +158,9 @@ Waterfall.prototype.updateVisibleItems = function (force = false) {
|
|
|
134
158
|
const options = this.options;
|
|
135
159
|
const $container = $(options.container);
|
|
136
160
|
|
|
137
|
-
const startTop =
|
|
161
|
+
const startTop = self.scrollTop; // 当前滚动位置
|
|
138
162
|
const endTop = startTop + $container.height();
|
|
163
|
+
// console.log('startTop', startTop)
|
|
139
164
|
|
|
140
165
|
// 进行可见区域的渲染更新
|
|
141
166
|
this.updateCardsInView({
|
|
@@ -143,23 +168,41 @@ Waterfall.prototype.updateVisibleItems = function (force = false) {
|
|
|
143
168
|
end: endTop,
|
|
144
169
|
force
|
|
145
170
|
});
|
|
171
|
+
|
|
146
172
|
}
|
|
147
173
|
|
|
148
174
|
// 新增卡片
|
|
149
|
-
Waterfall.prototype.appendCard = function (data,
|
|
175
|
+
Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
|
|
150
176
|
const self = this;
|
|
151
177
|
const options = this.options;
|
|
152
178
|
const $container = $(options.container);
|
|
153
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
|
+
|
|
154
192
|
const $card = $(
|
|
155
193
|
`<div class="waterfall-item"
|
|
156
|
-
data-index="${
|
|
157
|
-
style="position: absolute;transform:translate(${left}px,${top}px);
|
|
194
|
+
data-index="${dataId}"
|
|
195
|
+
style="position: absolute;transform:translate(${left}px,${top}px);"
|
|
158
196
|
>
|
|
159
|
-
${options.renderItem(data,
|
|
197
|
+
${options.renderItem(data, dataInfo.originalIndex)}
|
|
160
198
|
</div> `
|
|
161
199
|
);
|
|
162
200
|
|
|
201
|
+
|
|
202
|
+
if (options.columns !== 1) {
|
|
203
|
+
$card.width(this.columnWidth + 'px');
|
|
204
|
+
}
|
|
205
|
+
|
|
163
206
|
$viewport.append($card);
|
|
164
207
|
return $card;
|
|
165
208
|
}
|
|
@@ -174,49 +217,100 @@ Waterfall.prototype.updateCardsInView = function ({ start, end, force = false })
|
|
|
174
217
|
this.createCards({ end: endBuffer });
|
|
175
218
|
}
|
|
176
219
|
|
|
177
|
-
|
|
178
|
-
|
|
220
|
+
const startNum = start - options.bufferHeight;
|
|
221
|
+
const endNum = end + options.bufferHeight;
|
|
222
|
+
// 新方案:基于数据ID映射机制
|
|
179
223
|
const newActiveNodes = new Map();
|
|
180
224
|
for (let i = 0; i < this.columns; i++) {
|
|
181
225
|
const column = this.columnItems[i];
|
|
182
226
|
|
|
183
227
|
for (let j = 0; j < column.children.length; j++) {
|
|
184
228
|
const row = column.children[j];
|
|
185
|
-
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
|
+
|
|
186
246
|
// 在可视区域内 进行有关卡片的操作
|
|
187
|
-
|
|
247
|
+
const bool = row.top <= endNum && row.bottom >= startNum;
|
|
248
|
+
if (bool) {
|
|
188
249
|
// 理论上什么都不动,因为卡片的位置不会变
|
|
189
|
-
const $card = this.activeNodes.get(
|
|
250
|
+
const $card = this.activeNodes.get(dataId);
|
|
190
251
|
|
|
191
252
|
let $node = null;
|
|
192
|
-
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
// 遍历当前的节点是否被占用,如果被占用的话,就得要从nodePool中取一个
|
|
257
|
+
let bool = true;
|
|
193
258
|
if ($card) {
|
|
259
|
+
bool = hasNodeInActives(newActiveNodes, $card)
|
|
260
|
+
}
|
|
261
|
+
// 如果卡片已经在DOM中,则不用更新位置
|
|
262
|
+
if (bool === false) {
|
|
194
263
|
$node = $card;
|
|
195
|
-
this.activeNodes.delete(
|
|
264
|
+
this.activeNodes.delete(dataId);
|
|
265
|
+
// 如果是强更,这里才会采取更新
|
|
196
266
|
if (force) {
|
|
197
|
-
this.updateRenderUI($node,
|
|
267
|
+
this.updateRenderUI($node, data, dataId);
|
|
198
268
|
}
|
|
269
|
+
|
|
199
270
|
} else {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
+
|
|
209
283
|
} else {
|
|
210
|
-
|
|
211
|
-
$node.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
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
|
+
}
|
|
216
297
|
}
|
|
217
298
|
}
|
|
218
299
|
|
|
219
|
-
|
|
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);
|
|
220
314
|
}
|
|
221
315
|
}
|
|
222
316
|
}
|
|
@@ -224,11 +318,16 @@ Waterfall.prototype.updateCardsInView = function ({ start, end, force = false })
|
|
|
224
318
|
// 阶段2:处理不活跃节点
|
|
225
319
|
this.activeNodes.forEach($node => {
|
|
226
320
|
$node.css('transform', `translateY(-9999px)`);// 移出可视区域
|
|
227
|
-
this.nodePool.
|
|
321
|
+
if (this.nodePool.indexOf($node) === -1) {
|
|
322
|
+
this.nodePool.push($node);
|
|
323
|
+
}
|
|
228
324
|
});
|
|
229
325
|
this.activeNodes = newActiveNodes;
|
|
326
|
+
// console.log('this.activeNodes', this.activeNodes);
|
|
327
|
+
// console.log('this.nodePool', this.nodePool);
|
|
230
328
|
}
|
|
231
329
|
|
|
330
|
+
|
|
232
331
|
Waterfall.prototype.getMaxHeight = function () {
|
|
233
332
|
let maxHeight = 0;
|
|
234
333
|
for (let i = 0; i < this.columns; i++) {
|
|
@@ -276,79 +375,99 @@ Waterfall.prototype.getMinHeightColumn = function () {
|
|
|
276
375
|
}
|
|
277
376
|
|
|
278
377
|
// 创建卡片
|
|
279
|
-
Waterfall.prototype.createCards = function ({ end }) {
|
|
378
|
+
Waterfall.prototype.createCards = function ({ end, dataId = -1 }) {
|
|
280
379
|
const self = this;
|
|
281
380
|
const options = this.options;
|
|
282
381
|
const $container = $(options.container);
|
|
283
|
-
const renderIndex = this.renderIndex;
|
|
284
382
|
|
|
285
|
-
|
|
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) {
|
|
286
394
|
const maxHeight = this.getMaxHeight();
|
|
287
|
-
|
|
288
|
-
|
|
395
|
+
$container.find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom + 'px');
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
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);
|
|
289
403
|
return;
|
|
290
404
|
}
|
|
291
405
|
|
|
406
|
+
if (this.renderIndex >= this.options.data.length) {
|
|
407
|
+
return
|
|
408
|
+
}
|
|
409
|
+
|
|
292
410
|
let column = this.getMinHeightColumn();
|
|
293
411
|
if (column === null) {
|
|
294
|
-
// 没有可用的列,则在第一列创建,说明此时还没有数据
|
|
295
412
|
column = this.columnItems[0];
|
|
296
413
|
}
|
|
297
414
|
|
|
298
415
|
const top = column.bottom === 0 ? options.marginTop : (column.bottom + options.rowGap);
|
|
299
|
-
|
|
300
|
-
// 设置卡片位置
|
|
301
|
-
const position = {
|
|
302
|
-
top,
|
|
303
|
-
left: column.left,
|
|
304
|
-
}
|
|
305
|
-
|
|
416
|
+
const position = { top, left: column.left };
|
|
306
417
|
const row = createDefaultRow(position);
|
|
307
418
|
|
|
419
|
+
this.renderIndex += 1;
|
|
308
420
|
|
|
309
|
-
//
|
|
421
|
+
// 添加卡片,使用dataId作为唯一标识
|
|
310
422
|
let $card = null;
|
|
311
423
|
if (this.nodePool.length === 0) {
|
|
312
|
-
$card = this.appendCard(
|
|
424
|
+
$card = this.appendCard(dataInfo.data, nextDataId, position);
|
|
313
425
|
} else {
|
|
314
426
|
$card = $(this.nodePool.pop());
|
|
315
427
|
$card.css({
|
|
316
428
|
'transform': `translate(${row.left}px,${row.top}px)`,
|
|
317
|
-
}).attr('data-index',
|
|
318
|
-
this.updateRenderUI($card,
|
|
429
|
+
}).attr('data-index', nextDataId);
|
|
430
|
+
this.updateRenderUI($card, dataInfo.data, nextDataId);
|
|
319
431
|
}
|
|
320
432
|
|
|
321
|
-
|
|
322
433
|
row.$node = $card;
|
|
434
|
+
row.dataId = nextDataId; // 使用dataId替代renderIndex
|
|
435
|
+
if (dataId !== -1) {
|
|
436
|
+
row.dataId = dataId;
|
|
437
|
+
}
|
|
323
438
|
|
|
324
|
-
//
|
|
325
|
-
|
|
439
|
+
// 记录布局信息
|
|
440
|
+
dataInfo.layoutInfo = {
|
|
441
|
+
columnIndex: this.columnItems.indexOf(column),
|
|
442
|
+
position: position,
|
|
443
|
+
row: row
|
|
444
|
+
};
|
|
326
445
|
|
|
446
|
+
// 把新增的卡片放进 activeNodes
|
|
447
|
+
this.activeNodes.set(nextDataId, $card);
|
|
448
|
+
this.allReadyNodes.set(nextDataId, $card);
|
|
449
|
+
this.renderedDataIds.add(nextDataId);
|
|
327
450
|
|
|
328
451
|
// 更新列的底部距离
|
|
329
452
|
column.bottom = top + $card.height();
|
|
330
453
|
column.children.push(row);
|
|
331
|
-
|
|
332
|
-
// 计算当前卡片的位置
|
|
333
454
|
row.bottom = column.bottom;
|
|
334
|
-
row.renderIndex = renderIndex;
|
|
335
|
-
|
|
336
|
-
this.renderIndex += 1;
|
|
337
|
-
|
|
338
|
-
let hasNextData = this.renderIndex < options.data.length;
|
|
339
455
|
|
|
456
|
+
// 检查是否需要继续创建卡片
|
|
340
457
|
const minHeight = this.getMinHeight();
|
|
341
|
-
|
|
458
|
+
const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
|
|
459
|
+
|
|
460
|
+
if (hasMoreData && (minHeight < end)) {
|
|
342
461
|
window.requestAnimationFrame(() => {
|
|
343
462
|
this.createCards({ end });
|
|
344
463
|
});
|
|
345
464
|
} else {
|
|
346
465
|
const maxHeight = this.getMaxHeight();
|
|
347
|
-
|
|
348
|
-
$(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom)
|
|
466
|
+
$(options.container).find('.waterfall-list-scroll').css('height', maxHeight + options.marginBottom);
|
|
349
467
|
}
|
|
350
468
|
}
|
|
351
469
|
|
|
470
|
+
|
|
352
471
|
Waterfall.prototype.createColumn = function (index) {
|
|
353
472
|
const res = {
|
|
354
473
|
left: 0,
|
|
@@ -365,33 +484,135 @@ Waterfall.prototype.createColumn = function (index) {
|
|
|
365
484
|
return res;
|
|
366
485
|
}
|
|
367
486
|
|
|
368
|
-
Waterfall.prototype.updateRenderUI = function ($node, data,
|
|
487
|
+
Waterfall.prototype.updateRenderUI = function ($node, data, dataId) {
|
|
369
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
|
+
|
|
370
501
|
if (this.hasUpdateItem === true) {
|
|
371
|
-
options.updateItem($node, data,
|
|
502
|
+
options.updateItem($node, data, dataInfo.originalIndex)
|
|
372
503
|
} else {
|
|
373
|
-
$node.html(options.renderItem(data,
|
|
504
|
+
$node.html(options.renderItem(data, dataInfo.originalIndex));
|
|
374
505
|
}
|
|
375
506
|
}
|
|
376
507
|
|
|
508
|
+
|
|
509
|
+
|
|
377
510
|
Waterfall.prototype.updateData = function (newData) {
|
|
378
|
-
|
|
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
|
+
|
|
379
533
|
this.updateVisibleItems(true); // 强制更新渲染
|
|
534
|
+
|
|
535
|
+
// 重新计算所有卡片位置并更新位置
|
|
536
|
+
// this.updatePointCards();
|
|
380
537
|
}
|
|
381
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
|
+
|
|
382
579
|
function createDefaultRow({ top, left }) {
|
|
383
580
|
return {
|
|
384
581
|
top,
|
|
385
582
|
left,
|
|
386
583
|
bottom: 0,
|
|
387
584
|
$node: null,
|
|
388
|
-
|
|
585
|
+
dataId: -1 // 新方案:使用dataId替代renderIndex
|
|
389
586
|
}
|
|
390
587
|
}
|
|
391
588
|
|
|
392
|
-
|
|
393
|
-
|
|
589
|
+
|
|
590
|
+
function getBottomByColumn(column) {
|
|
591
|
+
if (column.children.length === 0) {
|
|
394
592
|
return 0;
|
|
395
593
|
}
|
|
396
|
-
|
|
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;
|
|
397
618
|
}
|