背景

背景

背景

使用 MetaPost 在覆盖层上绘制一条线,该覆盖层用作框架层的背景。该层嵌入在设置这样每次都会重新计算时间线上的点的位置。计算基于当前部分的标题文本的值。

问题

时间线两端的水平条略有移动。比较:

第1章

第2章

当重叠显示时,差异很明显,尽管很微妙:

移位条形图

代码

这个最小工作示例相当简单。大部分代码都是通过解析节标题中的数字来完成的\startuseMPgraphic

\definepapersize[BookPaperSize][
  width=8in,
  height=6in,
]

\setuppapersize[BookPaperSize]

% Specify the width and height here because the inline figures need to
% maintain aspect ratio while setting a pleasing width.
\startsetups[BookIllustrationSetups]
  \setlayerframed[BookIllustrationLayer][
    frame=off,
    x=\zeropoint,
    y=1.25in,
    width=\makeupwidth,
    background=BookTimelineOverlay,
  ]{}
\stopsetups

\setupbackgrounds[page][
  background=BookIllustrationLayer,
  setups=BookIllustrationSetups
]

\definelayer[BookIllustrationLayer][
  width=\paperwidth,
  height=\paperheight,
]

\defineoverlay[BookTimelineOverlay][\useMPgraphic{BookTimelineGraphic}]

\startuseMPgraphic{BookTimelineGraphic}
  % Define constants
  numeric EVENT_BEGAN, TIME_OFFSET, PATH_THICKNESS;
  EVENT_BEGAN := 13799;
  TIME_OFFSET := 1.25in;
  PATH_THICKNESS := 2pt;

  % The book timeline title macro contains a number representing when the
  % event transpired and additional information.
  string sectionTitle, sectionTitleDigits;
  sectionTitle := "\getspecificstructuretitle{3}";
  sectionTitleDigits := "";

  % Extract only digits and decimals from the book timeline title macro.
  for i = 0 upto length( sectionTitle ):
    string sectionChar;
    sectionChar := substring( i, i + 1 ) of sectionTitle;

    % A space indicates that the number has no more digits.
    if sectionChar = " ":
      break;
    fi;

    % Concatentate all the digits together.
    if ((sectionChar >= "0") and (sectionChar <= "9")) or (sectionChar = "."):
      sectionTitleDigits := sectionTitleDigits & sectionChar;
    fi;
  endfor;

  % Convert the digits from a string to a numeric value.
  numeric eventTime;
  eventTime := 0;

  for i = scantokens( sectionTitleDigits ):
    eventTime := i;
  endfor;

  numeric eventX;
  eventX := 1 - (eventTime / EVENT_BEGAN);

  % Draw the line.
  draw (TIME_OFFSET, .5*\overlayheight) -- (\overlaywidth, .5*\overlayheight) \
    withpen pencircle scaled PATH_THICKNESS;

  % Draw starting |.
  draw (TIME_OFFSET, 0) -- (TIME_OFFSET, \overlayheight) \
    withpen pencircle scaled PATH_THICKNESS;

  % Draw ending |.
  draw (\overlaywidth, 0) -- (\overlaywidth, \overlayheight) \
    withpen pencircle scaled PATH_THICKNESS;

  % Draw the timeline's dot relative to the event on the timeline.
  filldraw fullcircle scaled 9 \
    shifted( \
      TIME_OFFSET + eventX * (\overlaywidth - TIME_OFFSET), .5*\overlayheight \
    );
\stopuseMPgraphic

\starttext
  \chapter[title={Inflation Theory},reference={inflation-theory}]
  \section[title={13,799 ± 0.021},reference={section}]
  \input ward

  \chapter[title={First Stars},reference={first-stars}]
  \section[title={13,689 ± 70},reference={section-1}]
  \input ward
\stoptext

问题

我在想:

  • 时间轴栏为何略微发生偏移?
  • 如何消除这种移位,使得时间轴条能够精确重叠,而不管时间线点的位置如何?

附加问题:

  • 如何简化代码,特别是解析标题?

示例输出

以下示例展示了如何使用时间线图形:

预览

解决

经过一些上下文调整,Henri 的解决方案完美地发挥了作用:

  numeric wb, hb;
  wb := \overlaywidth - 1in;
  hb := .5in;

  draw image(
    draw image(
      % Draw the line.
      draw (0, .5*hb) -- (wb, .5*hb);

      % Draw starting |.
      draw (0, 0) -- (0, hb);

      % Draw ending |.
      draw (wb, 0) -- (wb, hb);
    )
    withpen pencircle scaled 2pt withcolor \MPcolor{\overlaylinecolor};

    draw image(
      % Draw the timeline's dot relative to the event on the timeline.
      filldraw fullcircle scaled 11 shifted( eventX * wb, .5*hb );
    )
    withcolor \MPcolor{BookTimelineColour};
  )
  shifted( .55in, OverlayHeight - .25 * hb );

答案1

点的位置会修改边界框。此问题最临时的解决方案是

  1. 在绘制点之前保存边界框
  2. 画点
  3. 恢复没有点的边界框

然后,该点将会泄漏出边界框,但那只是一点点。

\definepapersize[BookPaperSize][
  width=8in,
  height=6in,
]

\setuppapersize[BookPaperSize]

% Specify the width and height here because the inline figures need to
% maintain aspect ratio while setting a pleasing width.
\startsetups[BookIllustrationSetups]
  \setlayerframed[BookIllustrationLayer][
    frame=off,
    x=\zeropoint,
    y=1.25in,
    width=\makeupwidth,
    background=BookTimelineOverlay,
  ]{}
\stopsetups

\setupbackgrounds[page][
  background=BookIllustrationLayer,
  setups=BookIllustrationSetups
]

\definelayer[BookIllustrationLayer][
  width=\paperwidth,
  height=\paperheight,
]

\defineoverlay[BookTimelineOverlay][\useMPgraphic{BookTimelineGraphic}]

\startuseMPgraphic{BookTimelineGraphic}
  % Define constants
  numeric EVENT_BEGAN, TIME_OFFSET, PATH_THICKNESS;
  EVENT_BEGAN := 13799;
  TIME_OFFSET := 1.25in;
  PATH_THICKNESS := 2pt;

  % The book timeline title macro contains a number representing when the
  % event transpired and additional information.
  string sectionTitle, sectionTitleDigits;
  sectionTitle := "\getspecificstructuretitle{3}";
  sectionTitleDigits := "";

  % Extract only digits and decimals from the book timeline title macro.
  for i = 0 upto length( sectionTitle ):
    string sectionChar;
    sectionChar := substring( i, i + 1 ) of sectionTitle;

    % A space indicates that the number has no more digits.
    if sectionChar = " ":
      break;
    fi;

    % Concatentate all the digits together.
    if ((sectionChar >= "0") and (sectionChar <= "9")) or (sectionChar = "."):
      sectionTitleDigits := sectionTitleDigits & sectionChar;
    fi;
  endfor;

  % Convert the digits from a string to a numeric value.
  numeric eventTime;
  eventTime := 0;

  for i = scantokens( sectionTitleDigits ):
    eventTime := i;
  endfor;

  numeric eventX;
  eventX := 1 - (eventTime / EVENT_BEGAN);

  % Draw the line.
  draw (TIME_OFFSET, .5*\overlayheight) -- (\overlaywidth, .5*\overlayheight)
    withpen pencircle scaled PATH_THICKNESS;

  % Draw starting |.
  draw (TIME_OFFSET, 0) -- (TIME_OFFSET, \overlayheight)
    withpen pencircle scaled PATH_THICKNESS;

  % Draw ending |.
  draw (\overlaywidth, 0) -- (\overlaywidth, \overlayheight)
    withpen pencircle scaled PATH_THICKNESS;

  % The dot will change the size of bounding box, so we will just save the
  % bounding box without the dot for later
  path p ; p := bbox currentpicture ;

  % Draw the timeline's dot relative to the event on the timeline.
  filldraw fullcircle scaled 9
    shifted(
      TIME_OFFSET + eventX * (\overlaywidth - TIME_OFFSET), .5*\overlayheight
    );

  % Restore the bounding box without dot
  setbounds currentpicture to p ;
\stopuseMPgraphic

\starttext
  \chapter[title={Inflation Theory},reference={inflation-theory}]
  \section[title={13,799 ± 0.021},reference={section}]
  \input ward

  \chapter[title={First Stars},reference={first-stars}]
  \section[title={13,689 ± 70},reference={section-1}]
  \input ward
\stoptext

这是您的代码的稍短版本,使用 Lua 解析章节标题并使用 MetaPost 绘图直接作为页面文本层的背景。

\definepapersize
  [BookPaperSize]
  [width=8in,
   height=6in]

\setuppapersize[BookPaperSize]

\defineoverlay
  [BookTimelineOverlay]
  [\useMPgraphic{BookTimelineGraphic}]

\setupbackgrounds
  [text]
  [background=BookTimelineOverlay]


\startluacode
function userdata.parsetitle(title)
    local a, b = string.match(title, "(%d+),(%d+)")
    return table.concat({ a, b }, "")
end
\stopluacode

\startuseMPgraphic{BookTimelineGraphic}
  % Define constants
  numeric EVENT_BEGAN;
  EVENT_BEGAN := 13799;

  % Convert the digits from a string to a numeric value.
  numeric eventX;
  eventX := lua("mp.print(userdata.parsetitle('\getspecificstructuretitle{3}'))") ;
  eventX := 1 - (eventX / EVENT_BEGAN);

  numeric wb, hb ; wb := 3.33in ; hb := .33in ;
  pickup pencircle scaled 2pt;
  picture p ; p := image(
      % Draw the line.
      draw (0, .5*hb) -- (wb, .5*hb) ;
      % Draw starting |.
      draw (0, 0) -- (0, hb) ;
      % Draw ending |.
      draw (wb, 0) -- (wb, hb) ;
      % Draw the timeline's dot relative to the event on the timeline.
      filldraw fullcircle scaled 9 shifted (eventX * wb, .5*hb);
  );

  numeric h ; h := OverlayHeight ;
  draw p shifted (-.33in, h - hb - .33in);

  setbounds currentpicture to OverlayBox ;
\stopuseMPgraphic

\starttext
  \chapter[title={Inflation Theory},reference={inflation-theory}]
  \section[title={13,799 ± 0.021},reference={section}]
  \input ward

  \chapter[title={First Stars},reference={first-stars}]
  \section[title={13,689 ± 70},reference={section-1}]
  \input ward
\stoptext

答案2

Henri 已经回答了如何修复移位。我将回答您的附加问题,即如何简化代码。为此,我将使用视觉计数器模块。

首先,我定义一个新的 visualcounter 名为progressmarker

\usemodule[visualcounter]

\definevisualcounter
  [progressmarker]
  [         
    mp=visualcounter::progressmarker,
    width=\the\dimexpr\textwidth/2\relax,
    height=4ExHeight,
    rulethickness=2bp,
    mpsetups=visualcounter::markers:circle,
  ]

\startuseMPgraphic {visualcounter::progressmarker}
  begingroup;

  \includeMPgraphic{visualcounter::initialization}
  \includeMPgraphic{\visualcounterparameter{mpsetups}}

  shift := (current_counter-1)/(last_counter-1);

  newpath boundary;
  boundary := (0,-height/2) -- (width,-height/2) -- (width,height/2) -- (0, height/2) -- cycle;

  newpath pastline;
  pastline := (0, 0) -- (shift*width, 0);

  newpath futureline;
  futureline := (shift*width, 0) -- (width, 0);

  drawoptions(withpen pencircle scaled rulethickness);
  linecap := butt;

  draw leftboundary   boundary withcolor past_color;
  draw rightboundary  boundary withcolor future_color;
  draw pastline                withcolor past_color;
  draw futureline              withcolor future_color;
  drawoptions();

  show_marker(height/2, shift*width, active_color);

  setbounds currentpicture to boundary ;

  endgroup;
\stopuseMPgraphic

可以按如下方式使用:

\starttext
\startTEXpage[offset=2mm]
\usevisualcounter[n=4, last=10]{progressmarker}
\stopTEXpage
\stoptext

这使:

在此处输入图片描述

颜色有点不对,因为它使用的是 visualcounter 的默认调色板。为了获得单一的纯色,我们更改了调色板:

\definepalet[blue][past=blue, active=blue, future=blue]
\setupvisualcounter[progressmarker][palette=blue]

这使:

在此处输入图片描述

因此,只需将其插入部分计数器即可。可以使用以下方法完成此操作:

\definevisualcounter
  [visualsection]
  [progressmarker]
  [
    n={\somenamedheadnumber{section}{current}},
    last={\somenamedheadnumber{section}{last}},
  ]

\setuphead[section]
          [after={\usevisualcounter{visualsection}}]

\starttext
\startTEXpage[offset=2mm]
  \startsection[title=Inflation Theory]
    \input ward
  \stopsection
  \startsection[title=First Starts]
    \input ward
  \stopsection
  \startsection[title=Second Starts]
    \input ward
  \stopsection
\stopTEXpage
\stoptext

这使 在此处输入图片描述

相关内容