Skip to content

Commit cc29624

Browse files
committed
fix: Harden MagicMoveText measurement caching (#8684)
1 parent a08e658 commit cc29624

1 file changed

Lines changed: 42 additions & 5 deletions

File tree

src/component/MagicMoveText.mjs

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ class MagicMoveText extends Component {
5050
* @reactive
5151
*/
5252
autoCycleInterval_: 2000,
53+
/**
54+
* The number of text cycles before the measurement cache is automatically cleared.
55+
* Set to 0 to disable automatic clearing.
56+
* @member {Number} cacheClearInterval_=10
57+
* @reactive
58+
*/
59+
cacheClearInterval_: 10,
5360
/**
5461
* @member {String[]} baseCls=['neo-magic-move-text']
5562
* @protected
@@ -132,6 +139,12 @@ class MagicMoveText extends Component {
132139
* @protected
133140
*/
134141
contentWidth = 0
142+
/**
143+
* Counter for the number of text cycles since the last cache clear.
144+
* @member {Number} cycleCount=0
145+
* @protected
146+
*/
147+
cycleCount = 0
135148
/**
136149
* The index of the string currently displayed from the `cycleTexts` array.
137150
* @member {Number} currentIndex=0
@@ -321,6 +334,15 @@ class MagicMoveText extends Component {
321334
}
322335

323336
if (value) {
337+
if (me.cacheClearInterval > 0) {
338+
me.cycleCount++;
339+
340+
if (me.cycleCount >= me.cacheClearInterval) {
341+
me.measureCache = {};
342+
me.cycleCount = 0
343+
}
344+
}
345+
324346
try {
325347
me.chars = [];
326348
measureElement.cn = [];
@@ -413,10 +435,10 @@ class MagicMoveText extends Component {
413435
async measureChars() {
414436
let me = this,
415437
{measureCache, measureElement, measureWrapper, text} = me,
416-
parentRect, rects;
438+
parentRect, rects, rootRect;
417439

418-
if (measureCache[text]) {
419-
rects = [...measureCache[text]];
440+
if (measureCache[text] && measureCache[text].width === me.contentWidth && measureCache[text].height === me.contentHeight) {
441+
rects = [...measureCache[text].rects];
420442
parentRect = rects.shift()
421443
} else {
422444
measureWrapper.style = {
@@ -429,10 +451,25 @@ class MagicMoveText extends Component {
429451
await me.promiseUpdate();
430452
await me.timeout(20);
431453

432-
rects = await me.getDomRect([measureWrapper.id, ...measureElement.cn.map(node => node.id)]);
454+
rects = await me.getDomRect([me.id, measureWrapper.id, ...measureElement.cn.map(node => node.id)]);
455+
rootRect = rects.shift();
433456
parentRect = rects.shift();
434457

435-
measureCache[text] = [parentRect, ...rects]
458+
// Self-Correction: If the real DOM size differs from our expected size, we update and retry.
459+
// We allow a small tolerance (2px) for sub-pixel rendering differences.
460+
// We also check for > 0 to avoid zeroing out dimensions if the component is temporarily hidden.
461+
if (rootRect.width > 0 && (Math.abs(rootRect.width - me.contentWidth) > 2 || Math.abs(rootRect.height - me.contentHeight) > 2)) {
462+
me.contentWidth = rootRect.width;
463+
me.contentHeight = rootRect.height;
464+
465+
return me.measureChars()
466+
}
467+
468+
measureCache[text] = {
469+
height: me.contentHeight,
470+
rects : [parentRect, ...rects],
471+
width : me.contentWidth
472+
}
436473
}
437474

438475
rects.forEach((rect, index) => {

0 commit comments

Comments
 (0)