Skip to content

fix(core): 修复文字底部边缘被裁剪 #435 - #584

Merged
apoint123 merged 1 commit into
mainfrom
fix/text-clip
Aug 15, 2026
Merged

fix(core): 修复文字底部边缘被裁剪 #435#584
apoint123 merged 1 commit into
mainfrom
fix/text-clip

Conversation

@apoint123

Copy link
Copy Markdown
Member

歌词播放器在这里设置了 line-height: 1.2,即行高只有 1.2em,在没有 padding 时,歌词行的 Border Box 实际高度会被限制在 1.2em

但主流西文字体一般有 1.3em ~ 1.35em 左右,浏览器会把多出来的部分画到 Border Box 之外

默认情况下的 overflow: visible 可以让多出来的部分能够显示,但 DOM 实现用了 CSS 遮罩来实现渐变过渡动画:

if (this.lyricPlayer.supportMaskImage) {
wordEl.style.maskImage = maskImage;
wordEl.style.maskRepeat = "no-repeat";
wordEl.style.maskOrigin = "left";
wordEl.style.maskSize = totalAspectStr;
} else {
wordEl.style.webkitMaskImage = maskImage;
wordEl.style.webkitMaskRepeat = "no-repeat";
wordEl.style.webkitMaskOrigin = "left";
wordEl.style.webkitMaskSize = totalAspectStr;
}

这里设置了 mask-repeat: no-repeatmask-clip: border-box,导致 Border Box 外面的内容都被当做透明区域裁剪掉了


不过强调音节没有被裁,只有普通音节被裁了:

& > span,
span.emphasizeWrapper {
display: inline-block;
margin: -1em;
padding: 1em;
white-space: pre-wrap;
vertical-align: bottom;
contain: layout style;
&.emphasize,
span.emphasize {
margin: -1em;
padding: 1em;
backface-visibility: hidden;
& > span {
margin: -1em;
padding: 1em;
backface-visibility: hidden;
}
}
}
}

被强调的单词会添加 .emphasize 类名,匹配 span.emphasize,获得 padding: 1em; margin: -1em;,其 Border Box 上下各扩展了 1em,遮罩有了充足的缓冲空间,因此强调音节不会被裁

而非强调音节的 mainWordElemphasizeWrapper 内部的普通 <span>(没有 .emphasize 类名,且不是 .lyricMainLine 的直接子元素 > span),它只能匹配到 .lyricMainLine span,其计算出来的 padding 是 0px

逐字音译所拥有的 line-height: 1em 则裁剪得比 1.2 更严重:

.romanWord {
display: flex;
padding-inline-end: 0.3em;
font-size: 0.5em;
line-height: 1em;
}


解决方案是将 margin: -1em; padding: 1em 的缓冲空间从 .emphasize 移出,应用到外层容器内部的每一个音节元素上,如 diff 所示

同时根据 Claude 的意见移除了两处 Dead lines 和调整一处逻辑,原文:

无效代码

在 lyric-line.ts 中:

  • maskOrigin = "left" / webkitMaskOrigin = "left" —— 分布在两个遮罩生成器中的共 4 行代码。left 并不是合法的 mask-origin 值;它会被丢弃并计算为 border-box,而这正是周围数学计算原本就已经假定的值。
  • generateCalcBasedMaskImagemaskPosition 中末尾多余的 , left top —— 相当于为一个单层 mask 指定了第二层的位置。

必要的连锁调整

generateCalcBasedMaskImage 此前曾使用包含 padding 的 clientWidth/clientHeight 覆盖了 word.width/word.height,导致 updateMaskImageSync 刚刚计算出的内容尺寸被丢弃。这对强调字来说本就是错误的逻辑,而现在由于每个字都带有 padding,这会导致所有字词的 fadeWidth 都被不正常地撑大。现在已改为使用内容尺寸,并在需要带 padding 宽度的位置显式加上 word.padding * 2,与 generateWebAnimationBasedMaskImage 的行为保持一致。

Fixes #435

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes lyric glyph clipping by expanding mask buffer space around syllables.

Changes:

  • Applies padding buffers to all syllable spans.
  • Corrects mask dimensions and positioning calculations.
  • Removes invalid/redundant mask declarations and adds a patch version plan.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
packages/core/src/styles/lyric-player.module.css Extends clipping protection to every syllable.
packages/core/src/lyric-player/dom/lyric-line.ts Corrects mask sizing and removes dead declarations.
.nx/version-plans/version-plan-1786796432700.md Records the patch release.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@apoint123
apoint123 merged commit a336358 into main Aug 15, 2026
3 checks passed
@apoint123
apoint123 deleted the fix/text-clip branch August 15, 2026 12:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

文字边缘发生裁切

2 participants