[{"data":1,"prerenderedAt":233},["ShallowReactive",2],{"page-\u002Ftest\u002Ffan-toc-demo":3},{"id":4,"title":5,"body":6,"description":225,"extension":226,"meta":227,"navigation":228,"path":229,"seo":230,"stem":231,"__hash__":232},"content\u002Ftest\u002Ffan-toc-demo.md","扇形锚点导航测试页",{"type":7,"value":8,"toc":212},"minimark",[9,12,25,30,33,44,48,55,66,70,77,86,90,93,112,116,119,122,126,133,140,144,154,168,172,184,205,209],[10,11,5],"h1",{"id":5},[13,14,15,16,20,21,24],"p",{},"这一页专门用来试 ",[17,18,19],"code",{},"TocFanNav","：下面的每个 ",[17,22,23],{},"##"," 都会出现在右侧的扇形容器里，点击即可跳转。\n（测试用文件，不需要了直接删掉即可。）",[26,27,29],"h2",{"id":28},"一-准备工作","一 · 准备工作",[13,31,32],{},"先确认右侧导轨里同时出现了两个东西：滚动指示条和扇形锚点导航。",[13,34,35,36,39,40,43],{},"扇形导航用的是 ",[17,37,38],{},"FanVirtualList"," 的默认 ",[17,41,42],{},"driver=\"self\"","，也就是它自己带一条滚动轨道；\n滚动指示条则继续跟随窗口滚动。两者互不干扰，这一点在下面几节里会反复验证。",[26,45,47],{"id":46},"二-几何关系","二 · 几何关系",[13,49,50,51,54],{},"扇形把「轨道距离」换算成圆心角：",[17,52,53],{},"theta = (progress - index) * itemHeight \u002F radius","。",[13,56,57,58,61,62,65],{},"圆心落在锚点右侧 ",[17,59,60],{},"radius"," 处，所以 ",[17,63,64],{},"theta = 0"," 的那一条正好压在锚点上，\n其余条目沿弧向两端张开，横向会轻微外凸。半径越小，弧越弯、条目倾角越大；\n半径越大，越接近一条直列。",[26,67,69],{"id":68},"三-前位与淡出","三 · 前位与淡出",[13,71,72,73,76],{},"距离前位越远，条目越淡、倾角越大，超出 ",[17,74,75],{},"maxAngle"," 后就不再渲染。",[13,78,79,81,82,85],{},[17,80,75],{}," 同时决定虚拟窗口的 ",[17,83,84],{},"overscan","：窗口必须比可见角度范围更宽，\n否则弧上的条目会被提前卸载，滚动时会出现\"边缘条目闪一下\"的现象。",[26,87,89],{"id":88},"四-点击跳转","四 · 点击跳转",[13,91,92],{},"点击任意一条，正文会平滑滚动到对应标题，同时把这条转到扇形的前位。",[13,94,95,96,99,100,103,104,107,108,111],{},"跳转做两件事：页面 ",[17,97,98],{},"scrollIntoView({ behavior: 'smooth' })"," 到 heading，\n轨道 ",[17,101,102],{},"scrollTo({ behavior: 'smooth' })"," 到 ",[17,105,106],{},"index * itemHeight","。\n和 ",[17,109,110],{},"window"," 模式不同，这里不需要任何窗口进度的参与 —— 前位完全由轨道决定。",[26,113,115],{"id":114},"五-手写滚动","五 · 手写滚动",[13,117,118],{},"扇形自己是一条可滚动的轨道，把鼠标放在它上面滚动只会动扇形，不会动页面。",[13,120,121],{},"这也意味着：用户可以用滚轮浏览锚点列表，而正文保持不动；\n真要读某一节，再点一下跳过去。",[26,123,125],{"id":124},"六-末尾留白","六 · 末尾留白",[13,127,128,129,132],{},"容器末尾补了一段留白（",[17,130,131],{},"end-padding=\"container\"","），否则最后一条永远到不了前位。",[13,134,135,136,139],{},"原因很直接：轨道的 ",[17,137,138],{},"scrollTop"," 上限是「内容总高 − 容器高」，\n不加留白的话，最后「容器高 \u002F itemHeight」条根本没有机会滚到锚点位置。",[26,141,143],{"id":142},"七-键盘","七 · 键盘",[13,145,146,147,149,150,153],{},"当前只做了点击；如果要加方向键，在 ",[17,148,19],{}," 里接 ",[17,151,152],{},"reader.jumpBy(±1)"," 就行。",[13,155,156,159,160,163,164,167],{},[17,157,158],{},"reader"," 里已经把 ",[17,161,162],{},"jumpBy"," 写好了，它按 ",[17,165,166],{},"activeIndex"," 前后移动并复用同一条跳转逻辑。",[26,169,171],{"id":170},"八-与文档列表的差别","八 · 与文档列表的差别",[13,173,174,177,178,181,182,54],{},[17,175,176],{},"RightTabWithNav"," 用 ",[17,179,180],{},"driver=\"window\""," 跟随页面滚动；这里用默认的 ",[17,183,42],{},[13,185,186,187,190,191,194,195,190,197,200,201,204],{},"还有一个区别是数据源：文档列表来自 ",[17,188,189],{},"content"," store 的 ",[17,192,193],{},"summaries","，\n这里来自 ",[17,196,158],{},[17,198,199],{},"toc","（当前文档的 ",[17,202,203],{},"page.body.toc","）。",[26,206,208],{"id":207},"九-结束","九 · 结束",[13,210,211],{},"滚到最后一条，它会稳稳停在扇形的前位上。",{"title":213,"searchDepth":214,"depth":214,"links":215},"",2,[216,217,218,219,220,221,222,223,224],{"id":28,"depth":214,"text":29},{"id":46,"depth":214,"text":47},{"id":68,"depth":214,"text":69},{"id":88,"depth":214,"text":89},{"id":114,"depth":214,"text":115},{"id":124,"depth":214,"text":125},{"id":142,"depth":214,"text":143},{"id":170,"depth":214,"text":171},{"id":207,"depth":214,"text":208},"这一页专门用来试 TocFanNav：下面的每个 ## 都会出现在右侧的扇形容器里，点击即可跳转。\n（测试用文件，不需要了直接删掉即可。）","md",{},true,"\u002Ftest\u002Ffan-toc-demo",{"title":5,"description":225},"test\u002Ffan-toc-demo","I7TFo1sXtdeDrm8G6jXIGmqC9t2DkgRwBnrR1LP5B1Y",1791042466924]