首页修改记录 06:最近摄影光圈的几种实现方案
这次最近摄影光圈先后试过覆盖线、SVG 叶片、clip-path 分区和几何内缩。真正稳定的是把间隔放进照片叶片自身。
最近摄影光圈最终看起来是一组照片扇区加一个中心光圈,但过程中其实试了好几种方案。每种方案都能解决一部分问题,也都会暴露自己的代价。
把这些方案记下来,比只记最终代码更有用。因为这次最大的教训不是“某个 CSS 写法更好”,而是实现方式必须和未来动画目标一致。
方案一:照片圆盘 + 覆盖分隔线
最直接的方案是先把照片放进一个圆盘,再用 SVG 在上面画分隔线:
<div className="rounded-full overflow-hidden">
<PhotoSectors />
<SectorGuideLines />
</div>这很容易实现。每张照片用 clip-path: polygon(...) 裁成扇区,分隔线单独画在上层。
问题也很明显:分隔线不是照片的一部分。照片 hover 浮起时,分隔线仍然留在原位。把分隔线层级调低,只能让 hover 状态看起来稍好,但本质上仍然是两套图层互相遮挡。
这就是后来决定取消 SectorGuideLines 的原因。
方案二:中心光圈用几条 SVG 线拼
中心模拟光圈最早也试过用线条描述叶片边界。外面画圆,里面画六边形,再把几条线连到外圆。
这个方案的问题是太像“画示意图”,不像真实叶片。参考图里叶片之间的关系不是线段围出来的,而是每个叶片的边贴着下一个叶片,让中心自然形成六边形。
用线拼会出现两个结果:
- 线条很容易显得粗、突兀。
- 中心六边形会变成额外填色块,而不是镂空。
只要后续要做叶片开合动画,这个方案就不合适。
方案三:每个叶片用 SVG path
更合理的方案,是把中心光圈拆成 6 个叶片,每个叶片都是一个 SVG path。
每片叶片都有四个关键点:
- 外圆上的起点。
- 外圆上的终点。
- 中心六边形的一条边。
- 沿短边方向偏移后的起点。
叶片之间的缝隙不是 stroke,而是 path 之间留出的空白。这样中心六边形可以由叶片围出来,不需要额外画白色或黑色形状。
这个方案解决了中心光圈的主要问题,也让后续动画有了基础:只要改变中心半径、外侧角度和偏移量,叶片就能从接近闭合到展开。
方案四:照片扇区也用几何内缩
最后一个关键修改,是照片外圈也不再画分隔线。
照片扇区原本是这样的:
twistedSectorClipPolygon(..., sideInset = 0)现在改成:
twistedSectorClipPolygon(..., sideInset = PHOTO_SECTOR_GAP_WIDTH / 2)sideInset 不是角度魔法,而是把扇区两侧边界向扇区内部平移一小段距离。然后重新求这两条偏移线和内外圆的交点,生成新的 polygon。
这样做之后,间隔不再是画出来的线,而是照片叶片自己让出的透明区域。底色从下面露出来,hover 时也不会有独立线条穿过照片。
为什么不是简单缩小角度
简单把 start angle 加一点、end angle 减一点也能做出空隙,但它的问题是间隔宽度会随半径变化。
靠近中心时很窄,靠近外圆时很宽,最后看起来不像稳定缝隙,而像扇区被切歪了。
这次采用的是“边界平移”的思路:沿叶片边界的法线向内移动固定距离。这样更接近真实几何里的平行缝隙,也和用户指出的“长边沿着短边方向移动一定距离”一致。
哪个方案最终留下
最终结构保留了两套数学:
- 中心光圈:6 个 SVG path 叶片,中心洞由叶片自然围出。
- 外部照片:6 个 clip-path 照片扇区,左右边界内缩露出底色。
被移除的是两类覆盖层:
- 固定外圆线。
- 照片分隔线 SVG。
它们在静态截图里像是有帮助,但在 hover 和载入动画里会变成冲突源。删掉以后,结构反而更简单,也更接近后续动画要用的真实模型。

