tencent.jquery.pix.component 1.0.76 → 1.0.78

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.
@@ -1,6 +1,9 @@
1
1
  $jqpix-video-progress-bold-scale: 2 !default;
2
+ $jqpix-video-progress-handle-bold-scale: 0.5 !default;
2
3
  $jqpix-video-primary-color: #ff6429 !default;
3
4
 
5
+ @use "sass:math";
6
+
4
7
  .myplayer-shrink1 {
5
8
  flex-shrink: 1;
6
9
  }
@@ -270,16 +273,20 @@ $jqpix-video-primary-color: #ff6429 !default;
270
273
  max-width: 100%;
271
274
  }
272
275
 
273
- .myplayer-container .myplayer-subprogress div {
276
+ .myplayer-container .myplayer-subprogress .myplayer-progress-handle {
274
277
  content: "";
275
278
  position: absolute;
276
- width: 0.14rem;
277
- height: 0.14rem;
279
+ width: 0.5rem;
280
+ height: 0.5rem;
278
281
  top: 50%;
279
- right: -0.07rem;
280
- margin-top: -0.07rem;
281
- transform: rotate(45deg);
282
- background-color: #e5fd0e;
282
+ right: -0.25rem;
283
+ margin-top: -0.25rem;
284
+ border-radius: 0.25rem;
285
+ background-color: $jqpix-video-primary-color;
286
+ }
287
+
288
+ .myplayer-container .myplayer-progress-bold .myplayer-subprogress .myplayer-progress-handle {
289
+ transform: scaleY($jqpix-video-progress-handle-bold-scale);
283
290
  }
284
291
 
285
292
  .myplayer-container .myplayer-resolution {
@@ -18,7 +18,7 @@ const html = `
18
18
  <div class="myplayer-progress" draggable="true">
19
19
  <div class="myplayer-progress-bg"></div>
20
20
  <div class="myplayer-subprogress">
21
- <!-- <div></div> -->
21
+ <div class="myplayer-progress-handle"></div>
22
22
  </div>
23
23
  </div>
24
24
  </div>
@@ -20,6 +20,7 @@ import VideoHTML from "./videohtml";
20
20
  * @param {number} [options.autoHideControlsDelayMs=5000] 自动隐藏控制条延迟时间,单位ms
21
21
  * @param {boolean} [options.showProgressBar=true] 是否显示进度条
22
22
  * @param {boolean} [options.showVolumeControl=false] 是否显示音量控制
23
+ * @param {boolean} [options.showProgressHandle=true] 是否显示进度条滑块
23
24
  * @param {boolean} [options.clickToPause=false] 点击播放区域是否直接暂停,true: 直接暂停,false: 先展示控制条
24
25
  * @param {(this: VideoPlayer, type: VideoPlayerState) => any} [options.stateChanged] 状态变化回调
25
26
  */
@@ -59,6 +60,7 @@ VideoPlayer.prototype.init = async function () {
59
60
  autoHideControlsDelayMs: 5000,
60
61
  showProgressBar: true,
61
62
  showVolumeControl: false,
63
+ showProgressHandle: true,
62
64
  clickToPause: false,
63
65
  ...this.options
64
66
  }
@@ -88,6 +90,11 @@ VideoPlayer.prototype.init = async function () {
88
90
  $container.find('.myplayer-progress').hide();
89
91
  }
90
92
 
93
+ // 根据showProgressHandle选项控制进度条滑块显示
94
+ if (!this.options.showProgressHandle) {
95
+ $container.find('.myplayer-progress-handle').hide();
96
+ }
97
+
91
98
  // 根据showVolumeControl选项控制音量控件显示
92
99
  if (this.options.showVolumeControl) {
93
100
  $container.find('.myplayer-volume').show();
@@ -496,11 +503,13 @@ VideoPlayer.prototype.progressDragStart = function (e) {
496
503
  if (!this.options.showProgressBar) {
497
504
  return;
498
505
  }
499
-
500
- this.state.updatingProgress = false;
501
506
  if (this.state.playing === true) {
502
507
  this.pause();
503
508
  }
509
+
510
+ // 更新进度条时,不更新播放时间
511
+ // 这个赋值必须放在最后,因为pause会设置this.state.updatingProgress为true
512
+ this.state.updatingProgress = false;
504
513
  }
505
514
 
506
515
  /**
@@ -1,6 +1,6 @@
1
- import "./waterfall.scss"
2
- import { getEnv } from "../config.js";
3
1
  import { remToPx } from "../../utils/utils.js";
2
+ import { getEnv } from "../config.js";
3
+ import "./waterfall.scss";
4
4
 
5
5
  let $ = null;
6
6
 
@@ -15,7 +15,7 @@ const DEFAULTS = {
15
15
  startPoints: [], // 起始点距离
16
16
  data: [], // 数据源
17
17
  container: '', // 容器元素
18
- renderItem(data, index) { // 元素首次渲染时的回调函数, 如果把updateItem设置为空,那么更新时则会兜底触发renderItem
18
+ renderItem(data, index, $card) { // 元素首次渲染时的回调函数, 如果把updateItem设置为空,那么更新时则会兜底触发renderItem
19
19
  return '<div class="waterfall-item"></div>';
20
20
  },
21
21
  scrollDom: null, // 滚动元素,如果传入了滚动元素,那么用来计算的窗口高度就以滚动元素的高度为准
@@ -236,10 +236,17 @@ Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
236
236
  data-index="${dataId}"
237
237
  style="position: absolute;transform:translate(${left}px,${top}px);"
238
238
  >
239
- ${options.renderItem(data, dataInfo.originalIndex)}
240
239
  </div> `
241
240
  );
242
241
 
242
+ $viewport.append($card);
243
+
244
+ const str = options.renderItem(data, dataInfo.originalIndex, $card);
245
+
246
+ if (str) {
247
+ $card.html(str);
248
+ }
249
+
243
250
  this.renderedDataIds.add(dataId);
244
251
 
245
252
  if (options.columns !== 1) {
@@ -247,7 +254,6 @@ Waterfall.prototype.appendCard = function (data, dataId, { top, left }) {
247
254
  }
248
255
 
249
256
 
250
- $viewport.append($card);
251
257
  return $card;
252
258
  }
253
259
 
@@ -287,14 +293,28 @@ Waterfall.prototype.updateCardsInView = async function ({ start, end, force = fa
287
293
 
288
294
  const data = options.data[dataId]
289
295
 
290
- // 如果当前这个节点是特殊节点 不用做处理
296
+ // 如果当前这个节点是特殊节点,只更新位置,不参与节点复用
291
297
  // 如果是特殊的静态占用元素卡片,需要指定节点不变更的数据,那么该数据的节点不能被其他数据使用
292
298
  let specialNode = false;
293
299
  if (options.shouldOccupySpace) {
294
300
  specialNode = options.shouldOccupySpace(data) || false;
295
301
  }
296
302
  if (specialNode) {
297
- continue;
303
+ // 特殊节点:只更新位置,不参与复用逻辑
304
+ if (row.$node && row.$node.length) {
305
+ // 直接更新特殊节点的位置
306
+ row.$node.css({
307
+ 'transform': `translate(${row.left}px,${row.top}px)`,
308
+ }).attr('data-index', dataId);
309
+
310
+ // 如果是强制更新,也重新渲染内容
311
+ if (force) {
312
+ this.updateRenderUI(row.$node, data, dataId);
313
+ }
314
+ } else {
315
+ console.warn('Waterfall: Special node DOM not found for dataId', dataId);
316
+ }
317
+ continue; // 跳过普通节点的复用逻辑
298
318
  }
299
319
 
300
320
  // 在可视区域内 进行有关卡片的操作
@@ -531,6 +551,9 @@ Waterfall.prototype.createCards = function ({ end, dataId = -1 }, callback) {
531
551
  column.children.push(row);
532
552
  row.bottom = column.bottom;
533
553
 
554
+ // 建立 dataIdMap -> row 的引用,用于快速访问布局信息
555
+ dataInfo.layoutInfo = row;
556
+
534
557
  // 检查是否需要继续创建卡片
535
558
  const minHeight = this.getMinHeight();
536
559
  const hasMoreData = this.renderedDataIds.size < this.dataIdMap.size;
@@ -590,7 +613,32 @@ Waterfall.prototype.updateRenderUI = function ($node, data, dataId) {
590
613
  if (this.hasUpdateItem === true) {
591
614
  options.updateItem($node, data, dataInfo.originalIndex)
592
615
  } else {
593
- $node.html(options.renderItem(data, dataInfo.originalIndex));
616
+ const str = options.renderItem(data, dataInfo.originalIndex, $node);
617
+ if (str) {
618
+ $node.html(str);
619
+ }
620
+ }
621
+ }
622
+
623
+ // 辅助方法:使用 renderItem 渲染节点(用于全新节点)
624
+ Waterfall.prototype.renderUI = function ($node, data, dataId) {
625
+ const options = this.options;
626
+
627
+ // 新方案:基于数据ID的数据验证
628
+ if (!this.dataIdMap.has(dataId)) {
629
+ console.error('Waterfall: Invalid dataId in renderUI', dataId);
630
+ return;
631
+ }
632
+
633
+ const dataInfo = this.dataIdMap.get(dataId);
634
+ if (!dataInfo || !dataInfo.data) {
635
+ console.warn('Waterfall: Empty data for dataId', dataId);
636
+ }
637
+
638
+ // 始终使用 renderItem,因为这是全新节点
639
+ const str = options.renderItem(data, dataInfo.originalIndex, $node);
640
+ if (str) {
641
+ $node.html(str);
594
642
  }
595
643
  }
596
644
 
@@ -600,55 +648,367 @@ Waterfall.prototype.updateData = async function (newData) {
600
648
  const options = this.options;
601
649
  options.data = newData;
602
650
 
603
- // 新方案:重新建立数据ID映射
604
- //this.dataIdMap.clear();
605
- //this.renderedDataIds.clear();
606
- //this.nextDataId = 0;
651
+ // 步骤1: 批量获取所有卡片的新高度(只需一次 requestAnimationFrame)
652
+ const dataIds = this.renderedDataIds;
653
+ const newHeightsMap = await this.getBatchCardNewHeights(dataIds, newData);
607
654
 
608
- // 为每个数据项分配唯一ID
609
- let bool = true
610
- let count = options.data.length - 1;
611
- let index = 0;
655
+ // 步骤2: 收集高度变化
656
+ const heightChanges = new Map(); // dataId -> {oldHeight, newHeight, heightDiff}
612
657
 
613
- while (bool) {
614
- if (index > count) {
615
- bool = false
616
- this.updateVisibleItems(true); // 强制更新渲染
617
- break;
658
+ for (let dataId of dataIds) {
659
+ const oldHeight = this.getCardOldHeight(dataId);
660
+ const newHeight = newHeightsMap.get(dataId);
661
+
662
+ if (oldHeight !== newHeight) {
663
+ heightChanges.set(dataId, {
664
+ oldHeight,
665
+ newHeight,
666
+ heightDiff: newHeight - oldHeight
667
+ });
618
668
  }
669
+ }
619
670
 
620
- const dataId = index;
621
- this.dataIdMap.set(dataId, {
622
- data: true,
623
- originalIndex: dataId,
624
- layoutInfo: null
671
+ // 步骤3: 使用累积差分算法更新每一列的布局
672
+ for (let i = 0; i < this.columnItems.length; i++) {
673
+ const column = this.columnItems[i];
674
+ let accumulatedDiff = 0; // 累积的高度变化
675
+
676
+ for (let j = 0; j < column.children.length; j++) {
677
+ const row = column.children[j];
678
+ const dataId = row.dataId;
679
+
680
+ // 先应用之前累积的差分
681
+ if (accumulatedDiff !== 0) {
682
+ row.top += accumulatedDiff;
683
+ row.bottom += accumulatedDiff;
684
+ }
685
+
686
+ // 如果当前卡片有高度变化,累积到差分中
687
+ if (heightChanges.has(dataId)) {
688
+ const change = heightChanges.get(dataId);
689
+ accumulatedDiff += change.heightDiff;
690
+ // 更新当前卡片的 bottom
691
+ row.bottom += change.heightDiff;
692
+ }
693
+ }
694
+
695
+ // 更新列的总高度
696
+ if (accumulatedDiff !== 0) {
697
+ column.bottom += accumulatedDiff;
698
+ }
699
+ }
700
+
701
+ // 步骤4: 同步视图
702
+ this.setScrollHeight();
703
+ this.updateVisibleItems(true); // 这里会处理内容更新和DOM位置同步
704
+ }
705
+
706
+ // 辅助方法:获取卡片的旧高度(从布局信息)
707
+ Waterfall.prototype.getCardOldHeight = function(dataId) {
708
+ const dataInfo = this.dataIdMap.get(dataId);
709
+
710
+ if (!dataInfo) {
711
+ // dataId 不存在
712
+ return 0;
713
+ }
714
+
715
+ if (!dataInfo.layoutInfo) {
716
+ // 布局信息未初始化(卡片还未创建)
717
+ return 0;
718
+ }
719
+
720
+ const row = dataInfo.layoutInfo;
721
+ return row.bottom - row.top;
722
+ }
723
+
724
+ // 辅助方法:获取特殊节点的 DOM 引用
725
+ Waterfall.prototype.getSpecialNodeDOM = function(dataId) {
726
+ const dataInfo = this.dataIdMap.get(dataId);
727
+ if (dataInfo && dataInfo.layoutInfo && dataInfo.layoutInfo.$node) {
728
+ return dataInfo.layoutInfo.$node;
729
+ }
730
+ return null;
731
+ }
732
+
733
+ // 辅助方法:批量获取卡片的新高度(用于 updateData)
734
+ Waterfall.prototype.getBatchCardNewHeights = async function(dataIds, newData) {
735
+ const options = this.options;
736
+ const $ = getEnv().$;
737
+ const $container = $(options.container);
738
+ const $viewport = $container.find('.waterfall-list-viewport');
739
+
740
+ // 用于记录每个卡片的信息
741
+ const cardInfos = new Map(); // dataId -> { $node, needCleanup, cleanupType }
742
+
743
+ // 记录从节点池借用的节点,需要在完成后归还
744
+ const borrowedNodes = [];
745
+ // 记录新创建的临时节点,需要在完成后删除
746
+ const tempNodesToDelete = [];
747
+
748
+ // 第一步:优先处理所有可视区域节点(activeNodes)
749
+ for (let dataId of dataIds) {
750
+ if (this.activeNodes.has(dataId)) {
751
+ const $node = this.activeNodes.get(dataId);
752
+ const data = newData[dataId];
753
+
754
+ // 重新渲染内容
755
+ this.updateRenderUI($node, data, dataId);
756
+
757
+ cardInfos.set(dataId, {
758
+ $node: $node,
759
+ needCleanup: false,
760
+ cleanupType: null
761
+ });
762
+ }
763
+ }
764
+
765
+ // 第二步:处理所有非可视区域节点
766
+ for (let dataId of dataIds) {
767
+ // 跳过已在第一步处理的可视区域节点
768
+ if (this.activeNodes.has(dataId)) {
769
+ continue;
770
+ }
771
+
772
+ const data = newData[dataId];
773
+
774
+ // 情况1: 卡片在 allReadyNodes 中
775
+ if (this.allReadyNodes.has(dataId)) {
776
+ const $existingNode = this.allReadyNodes.get(dataId);
777
+
778
+ // 特殊节点(null):通过 layoutInfo 获取 DOM 引用
779
+ if ($existingNode === null) {
780
+ const $specialNode = this.getSpecialNodeDOM(dataId);
781
+
782
+ if ($specialNode) {
783
+ // 特殊节点永远独占,无需检查重复
784
+ // 直接重新渲染特殊节点的内容
785
+ this.updateRenderUI($specialNode, data, dataId);
786
+
787
+ cardInfos.set(dataId, {
788
+ $node: $specialNode,
789
+ needCleanup: false,
790
+ cleanupType: 'special'
791
+ });
792
+ } else {
793
+ // 无法获取特殊节点DOM,使用旧高度
794
+ console.warn('Waterfall: Special node DOM not found for dataId', dataId);
795
+ cardInfos.set(dataId, {
796
+ $node: null,
797
+ needCleanup: false,
798
+ cleanupType: 'special-notfound'
799
+ });
800
+ }
801
+ continue;
802
+ }
803
+
804
+ // 情况2: 普通节点 - 从节点池获取或创建临时节点
805
+ let $node = getNodePoolPop(this.nodePool, this.activeNodes);
806
+
807
+ if ($node) {
808
+ // 从节点池借用节点
809
+ borrowedNodes.push($node);
810
+
811
+ // 设置位置和样式
812
+ $node.css({
813
+ 'transform': 'translate(-9999px, -9999px)',
814
+ });
815
+
816
+ // 设置宽度
817
+ if (options.columns !== 1) {
818
+ $node.width(this.columnWidth + 'px');
819
+ }
820
+
821
+ // 使用 updateRenderUI(节点池的节点已有结构)
822
+ this.updateRenderUI($node, data, dataId);
823
+
824
+ cardInfos.set(dataId, {
825
+ $node: $node,
826
+ needCleanup: false,
827
+ cleanupType: 'borrowed'
828
+ });
829
+ } else {
830
+ // 节点池空了,创建临时节点
831
+ $node = $(
832
+ `<div class="waterfall-item"
833
+ data-index="${dataId}"
834
+ style="position: absolute; transform: translate(-9999px, -9999px);"
835
+ >
836
+ </div>`
837
+ );
838
+ $viewport.append($node);
839
+ tempNodesToDelete.push($node);
840
+
841
+ // 设置宽度
842
+ if (options.columns !== 1) {
843
+ $node.width(this.columnWidth + 'px');
844
+ }
845
+
846
+ // 使用 renderUI(临时节点是全新的)
847
+ this.renderUI($node, data, dataId);
848
+
849
+ cardInfos.set(dataId, {
850
+ $node: $node,
851
+ needCleanup: false,
852
+ cleanupType: 'temp'
853
+ });
854
+ }
855
+ continue;
856
+ }
857
+
858
+ // 情况3: 未找到节点,标记为使用旧高度
859
+ cardInfos.set(dataId, {
860
+ $node: null,
861
+ needCleanup: false,
862
+ cleanupType: 'notfound'
625
863
  });
864
+ }
626
865
 
627
- await this.createCards({ end: 0, dataId })
866
+ // 第三步:在单个 requestAnimationFrame 中统一获取所有高度
867
+ return new Promise(resolve => {
868
+ window.requestAnimationFrame(() => {
869
+ const heightMap = new Map(); // dataId -> newHeight
628
870
 
629
- index += 1;
871
+ for (let [dataId, info] of cardInfos) {
872
+ if (info.$node) {
873
+ // 从DOM获取高度
874
+ heightMap.set(dataId, info.$node.height());
875
+ } else {
876
+ // 使用旧高度
877
+ heightMap.set(dataId, this.getCardOldHeight(dataId));
878
+ }
879
+ }
880
+
881
+ // 清理:归还借用的节点到节点池
882
+ for (let $node of borrowedNodes) {
883
+ $node.css('transform', 'translateY(-9999px)');
884
+ this.nodePool.push($node);
885
+ }
886
+
887
+ // 清理:删除临时节点
888
+ for (let $node of tempNodesToDelete) {
889
+ $node.remove();
890
+ }
891
+
892
+ resolve(heightMap);
893
+ });
894
+ });
895
+ }
896
+
897
+ // 辅助方法:获取卡片的新高度(通过渲染)- 用于单卡片更新
898
+ Waterfall.prototype.getCardNewHeight = async function(dataId, data) {
899
+ const options = this.options;
900
+ const $ = getEnv().$;
630
901
 
902
+ // 情况1: 卡片在可视区域(activeNodes)
903
+ if (this.activeNodes.has(dataId)) {
904
+ const $node = this.activeNodes.get(dataId);
905
+
906
+ // 重新渲染内容
907
+ this.updateRenderUI($node, data, dataId);
908
+
909
+ // 等待DOM更新
910
+ return new Promise(resolve => {
911
+ window.requestAnimationFrame(() => {
912
+ resolve($node.height());
913
+ });
914
+ });
631
915
  }
632
- // options.data.forEach((item, index) => {
633
- // const dataId = index; // this.nextDataId++;
634
- // if (!this.allReadyNodes.has(dataId)) {
635
- // this.dataIdMap.set(dataId, {
636
- // data: true,// item,
637
- // originalIndex: index,
638
- // layoutInfo: null // 将在布局时填充
639
- // });
640
- // // 如果没有准备好这个数据,这里要创建一个占位节点
641
- // this.createCards({ end: 0, dataId });
642
- // }
643
- // });
644
916
 
645
- // this.updateVisibleItems(true); // 强制更新渲染
917
+ // 情况2: 卡片不在可视区域(allReadyNodes)
918
+ if (this.allReadyNodes.has(dataId)) {
919
+ const $existingNode = this.allReadyNodes.get(dataId);
920
+
921
+ // 特殊节点(null):通过 layoutInfo 获取 DOM 引用并更新
922
+ if ($existingNode === null) {
923
+ const $specialNode = this.getSpecialNodeDOM(dataId);
924
+
925
+ if ($specialNode) {
926
+ // 重新渲染特殊节点的内容
927
+ this.updateRenderUI($specialNode, data, dataId);
928
+
929
+ // 等待DOM更新后获取新高度
930
+ return new Promise(resolve => {
931
+ window.requestAnimationFrame(() => {
932
+ resolve($specialNode.height());
933
+ });
934
+ });
935
+ }
936
+
937
+ // 无法获取特殊节点DOM,返回旧高度
938
+ console.warn('Waterfall: Special node DOM not found for dataId', dataId);
939
+ return this.getCardOldHeight(dataId);
940
+ }
646
941
 
942
+ // 普通节点:从节点池获取或创建临时节点
943
+ const $container = $(options.container);
944
+ const $viewport = $container.find('.waterfall-list-viewport');
647
945
 
946
+ let $node = getNodePoolPop(this.nodePool, this.activeNodes);
947
+ let isBorrowed = false;
948
+
949
+ if ($node) {
950
+ // 从节点池借用节点
951
+ isBorrowed = true;
952
+
953
+ // 设置位置和样式
954
+ $node.css({
955
+ 'transform': 'translate(-9999px, -9999px)',
956
+ });
957
+
958
+ // 设置宽度
959
+ if (options.columns !== 1) {
960
+ $node.width(this.columnWidth + 'px');
961
+ }
962
+
963
+ // 使用 updateRenderUI(节点池的节点已有结构)
964
+ this.updateRenderUI($node, data, dataId);
965
+ } else {
966
+ // 节点池空了,创建临时节点
967
+ $node = $(
968
+ `<div class="waterfall-item"
969
+ data-index="${dataId}"
970
+ style="position: absolute; transform: translate(-9999px, -9999px);"
971
+ >
972
+ </div>`
973
+ );
974
+ $viewport.append($node);
975
+
976
+ // 设置宽度
977
+ if (options.columns !== 1) {
978
+ $node.width(this.columnWidth + 'px');
979
+ }
980
+
981
+ // 使用 renderUI(临时节点是全新的)
982
+ this.renderUI($node, data, dataId);
983
+ }
984
+
985
+ // 等待DOM更新
986
+ return new Promise(resolve => {
987
+ window.requestAnimationFrame(() => {
988
+ const newHeight = $node.height();
989
+
990
+ // 清理
991
+ if (isBorrowed) {
992
+ // 归还借用的节点到节点池
993
+ $node.css('transform', 'translateY(-9999px)');
994
+ this.nodePool.push($node);
995
+ } else {
996
+ // 删除临时节点
997
+ $node.remove();
998
+ }
999
+
1000
+ resolve(newHeight);
1001
+ });
1002
+ });
1003
+ }
1004
+
1005
+ // 情况3: 未找到节点,返回旧高度
1006
+ return this.getCardOldHeight(dataId);
648
1007
  }
649
1008
 
650
1009
  // 某个数据进行了UI变更,触发高度重新绘制
651
- Waterfall.prototype.updateCard = function (data) {
1010
+ Waterfall.prototype.updateCard = async function (data) {
1011
+ const self = this;
652
1012
  const options = this.options;
653
1013
  let dataId = -1;
654
1014
  if (typeof data === 'number') {
@@ -667,49 +1027,75 @@ Waterfall.prototype.updateCard = function (data) {
667
1027
  return
668
1028
  }
669
1029
 
670
- // 从activeNodes中获取该数据的节点
671
- if (!this.activeNodes.has(dataId)) {
672
- console.log('Waterfall: Invalid dataId in activeNodes');
1030
+ // 检查数据是否已经渲染过
1031
+ if (!this.renderedDataIds.has(dataId)) {
1032
+ console.log('Waterfall: dataId not rendered yet', dataId);
673
1033
  return
674
1034
  }
675
1035
 
676
- const $node = this.activeNodes.get(dataId);
677
- const height = $node.height();
1036
+ const itemData = options.data[dataId];
1037
+
1038
+ // 获取旧高度
1039
+ const oldHeight = this.getCardOldHeight(dataId);
1040
+
1041
+ // 获取新高度(会自动处理渲染和临时节点)
1042
+ const newHeight = await this.getCardNewHeight(dataId, itemData);
1043
+
1044
+ // 应用高度变化
1045
+ this.applyHeightChange(dataId, oldHeight, newHeight);
1046
+ }
1047
+
1048
+ // 应用高度变化到布局
1049
+ Waterfall.prototype.applyHeightChange = function (dataId, oldHeight, newHeight) {
1050
+ const minus = newHeight - oldHeight;
1051
+
1052
+ // 如果高度没有变化,直接退出
1053
+ if (minus === 0) {
1054
+ console.log('Waterfall: Card height unchanged for dataId', dataId);
1055
+ return;
1056
+ }
1057
+
1058
+ console.log('Waterfall: Card height changed for dataId', dataId, 'from', oldHeight, 'to', newHeight, 'diff', minus);
678
1059
 
679
1060
  // 重新计算该数据所在列的卡片位置
680
- let needUpdate = false
1061
+ let needUpdate = false;
681
1062
  const columnItems = this.columnItems;
1063
+
682
1064
  for (let i = 0; i < columnItems.length; i++) {
683
1065
  const column = columnItems[i];
684
- let bool = false
685
- let minus = 0
1066
+ let foundCard = false;
1067
+
686
1068
  // 这里为了简化,各列的瀑布流保持不动,只更新各列下节点的top位置,不做节点的跨列位移
687
1069
  for (let j = 0; j < column.children.length; j++) {
688
1070
  const row = column.children[j];
689
- if (row.dataId === dataId) {
690
- bool = true
691
- const oldHeight = row.bottom - row.top;
692
1071
 
693
- minus = height - oldHeight;
1072
+ if (row.dataId === dataId) {
1073
+ foundCard = true;
1074
+ needUpdate = true;
694
1075
 
695
- if (minus === 0) {
696
- // 找到了原节点数据,对比后没有变更 那么直接退出
697
- return;
698
- }
699
- needUpdate = true
1076
+ // 更新当前卡片的bottom
700
1077
  row.bottom += minus;
701
- } else if (minus !== 0) {
1078
+
1079
+ } else if (foundCard) {
1080
+ // 更新该卡片以下所有卡片的位置(同列)
702
1081
  row.top += minus;
703
1082
  row.bottom += minus;
704
1083
  }
705
1084
  }
706
- if (bool) {
1085
+
1086
+ if (foundCard) {
1087
+ // 更新列的总高度
707
1088
  column.bottom += minus;
708
1089
  break;
709
1090
  }
710
1091
  }
1092
+
711
1093
  if (needUpdate) {
712
- this.updateVisibleItems(true); // 强制更新渲染
1094
+ // 更新滚动容器高度
1095
+ this.setScrollHeight();
1096
+
1097
+ // 强制更新渲染(更新所有卡片的实际位置)
1098
+ this.updateVisibleItems(true);
713
1099
  }
714
1100
  }
715
1101
 
@@ -761,11 +1147,11 @@ Waterfall.prototype.showLoading = function (callback = null) {
761
1147
  let loadingTop = this.getMaxHeight() + options.rowGap
762
1148
  this.$loadingNode.css('transform', `translate(0px,${loadingTop}px)`);
763
1149
  $node = this.$loadingNode;
764
- window.requestAnimationFrame(() => {
765
- setTimeout(() => {
766
- this.$scrollDom.scrollTop(loadingTop + this.$loadingNode.height());
767
- });
768
- });
1150
+ // window.requestAnimationFrame(() => {
1151
+ // setTimeout(() => {
1152
+ // this.$scrollDom.scrollTop(loadingTop + this.$loadingNode.height());
1153
+ // });
1154
+ // });
769
1155
  }
770
1156
 
771
1157
  if (callback) callback($node)
@@ -866,4 +1252,3 @@ function getNodePoolPop(nodePool, actives) {
866
1252
  }
867
1253
  return null;
868
1254
  }
869
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tencent.jquery.pix.component",
3
- "version": "1.0.76",
3
+ "version": "1.0.78",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "files": [
package/readme.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  - 用于web浏览器基于正常的jquery版本(1.9系列)
6
6
 
7
- - 用于pix小应用基于@tencent/jquery.pix
7
+ - 用于pix小应用基于tencent.jquery.pix
8
8
 
9
9
  git 地址
10
10