You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LilyPond中\change Staff引发的垂直间距与碰撞问题求助

LilyPond连音线与歌词碰撞问题的解决思路

问题复现

代码示例

\version "2.24.0"

BassVoice =  \relative d
{
  \clef bass
  d2 d4 d4 |
}

BassVoiceLyrics =  \lyricmode
{
  Word word word
}

PianoRightHand =  \relative g'
{
  \clef treble
  s1 |
  \bar "|."
}

PianoLeftHand =  \relative g'
{
  \clef bass
  g,8^( \change Staff = "up" g'8 d'8^[ d'8 b8 g8 d8] g,8) |
  \bar "|."
}

\score
{
  <<
    \new StaffGroup
    <<
      \new Staff = "Bass"
      <<
        \context Staff
        <<
          \context Voice = "BassVoice" { \voiceTwo \BassVoice }
          \new Lyrics \with { alignBelowContext = "Bass" }
              \lyricsto "BassVoice" \BassVoiceLyrics
        >>
      >>
    >>
    \new PianoStaff
    <<
      \context Staff = "up" \with { \override VerticalAxisGroup.default-staff-staff-spacing =
                                      #'((basic-distance . 100)
                                        (minimum-distance . 100)
                                        (padding . 100)
                                        (stretchability . 100))
                                  }
      <<
        \context Voice = "PianoRightHand" { \voiceOne \PianoRightHand }
      >>
      \context Staff = "down"
      <<
        \context Voice = "PianoLeftHand" { \voiceOne \PianoLeftHand }
      >>
    >>
  >>
}

碰撞效果

乐谱中连音线与上方歌词碰撞的效果

问题分析

1. 为何调整default-staff-staff-spacing无效?

你之前修改的VerticalAxisGroup.default-staff-staff-spacing是同一容器内谱表的间距参数——比如它只影响PianoStaff内部左右手谱表的距离,对Bass StaffGroup和PianoStaff这两个独立的顶级布局容器之间的间距完全不起作用。

2. 为何LilyPond未自动检测碰撞?

LilyPond的自动碰撞检测默认只在同一顶级容器内生效。你的歌词属于Bass StaffGroup,连音线属于PianoStaff,二者分属不同顶级容器,系统不会跨容器计算碰撞并调整间距。

解决办法

方法一:合并顶级容器(推荐)

把Bass Staff和PianoStaff放到同一个StaffGroup里,让LilyPond可以统一处理所有元素的布局和碰撞:

\score
{
  <<
    \new StaffGroup
    <<
      \new Staff = "Bass"
      <<
        \context Staff
        <<
          \context Voice = "BassVoice" { \voiceTwo \BassVoice }
          \new Lyrics \with { alignBelowContext = "Bass" }
              \lyricsto "BassVoice" \BassVoiceLyrics
        >>
      >>
      \new PianoStaff
      <<
        \context Staff = "up"
        <<
          \context Voice = "PianoRightHand" { \voiceOne \PianoRightHand }
        >>
        \context Staff = "down"
        <<
          \context Voice = "PianoLeftHand" { \voiceOne \PianoLeftHand }
        >>
      >>
    >>
  >>
}

这种方式下,LilyPond会自动检测连音线和歌词的碰撞并调整间距,不需要手动设置数值。

方法二:手动设置顶级容器间的间距

如果不想合并容器,可以直接调整Bass StaffGroup和PianoStaff之间的全局间距:

\score
{
  <<
    \new StaffGroup \with {
      system-system-spacing = #'((basic-distance . 60)
                                 (minimum-distance . 60))
    }
    <<
      \new Staff = "Bass"
      <<
        \context Staff
        <<
          \context Voice = "BassVoice" { \voiceTwo \BassVoice }
          \new Lyrics \with { alignBelowContext = "Bass" }
              \lyricsto "BassVoice" \BassVoiceLyrics
        >>
      >>
    >>
    \new PianoStaff
    <<
      \context Staff = "up"
      <<
        \context Voice = "PianoRightHand" { \voiceOne \PianoRightHand }
      >>
      \context Staff = "down"
      <<
        \context Voice = "PianoLeftHand" { \voiceOne \PianoLeftHand }
      >>
    >>
  >>
}

通过system-system-spacing设置当前StaffGroup与下方容器的基础间距和最小间距,数值可根据实际效果调整。

方法三:局部偏移连音线

如果只想调整连音线位置而不改动整体布局,可以给连音线添加垂直偏移:

PianoLeftHand =  \relative g'
{
  \clef bass
  g,8^( \offset #'(0 . -2) \change Staff = "up" g'8 d'8^[ d'8 b8 g8 d8] g,8) |
  \bar "|."
}

\offset #'(0 . -2)表示将后续元素(这里是跨谱表的连音线部分)向下移动2个单位,避开歌词。

内容的提问来源于stack exchange,提问作者Jim Liddle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 16:14:51