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

如何实现圆形hover缩放时始终精准贴合?求对应公式方案

解决圆形Hover放大自适应填补侧边间隙的问题

你的需求很清晰:一排相切的圆形,hover时放大后要刚好填补与侧边圆形的间隙,而且这个效果要适配任意初始尺寸,而不是固定的100px→200px的场景。你提到的三角公式确实是核心,我们先从几何逻辑入手,再给出具体实现方案。

先理清核心几何关系

假设初始圆形的直径为 s(也就是CSS里的width/height),hover时我们要把它放大到目标直径 S(比如你例子里的200px,或者按比例放大到k*s,k是缩放倍数)。

初始状态下,相邻圆形的中心间距等于s(因为flex布局下圆形紧挨着,直径为s的两个圆形中心距离就是s)。当hover圆形放大到直径S后,要让它和左右圆形仍然保持相切,我们需要满足:

放大后hover圆形的半径 + 侧边圆形的半径 = 两者的中心间距

代入数值就是:(S/2) + (s/2) = 中心间距,而初始中心间距是s,所以如果我们不移动侧边圆形,就需要通过调整hover圆形的缩放原点(transform-origin)或者位移,来让这个等式成立。

方案一:纯CSS(适配任意初始尺寸,用CSS变量+三角函数)

我们用CSS变量定义初始尺寸、目标放大尺寸,然后通过计算得到合适的transform-origin,让hover后的圆形刚好和侧边圆形相切,完全不需要JS。

代码实现

/* 定义可配置的CSS变量 */
.circles {
  display: flex;
  /* 初始圆形直径 */
  --initial-size: 100px;
  /* hover后的目标直径 */
  --hover-size: 200px;
  /* 计算初始半径和hover后的半径 */
  --initial-r: calc(var(--initial-size) / 2);
  --hover-r: calc(var(--hover-size) / 2);
  /* 计算缩放倍数 */
  --scale: calc(var(--hover-size) / var(--initial-size));
  /* 计算transform-origin的x偏移量:确保放大后与侧边圆形相切 */
  --origin-x: calc(var(--initial-r) * (1 - var(--scale)) + var(--hover-r));
}

.circles__item {
  height: var(--initial-size);
  width: var(--initial-size);
  background: limegreen;
  border-radius: 50%;
  transition: all 500ms ease-out;
  /* 初始transform-origin基于初始尺寸 */
  transform-origin: calc(var(--origin-x)) center;
}

.circles__item:hover {
  /* 直接设置hover后的尺寸,不需要同时用scale(之前的代码里混合了两种放大方式,会导致混乱) */
  height: var(--hover-size);
  width: var(--hover-size);
  background-color: rebeccapurple;
  /* 如果想用scale放大而不是直接改尺寸,也可以用下面的写法:
  transform: scale(var(--scale));
  */
}
<div class="circles">
  <div class="circles__item"></div>
  <div class="circles__item"></div>
  <div class="circles__item"></div>
  <div class="circles__item"></div>
  <div class="circles__item"></div>
</div>

原理说明

  1. 我们用CSS变量把所有尺寸参数化,你只需要修改--initial-size和--hover-size就能适配任意尺寸;
  2. --origin-x的计算逻辑:通过几何推导,让hover圆形的缩放原点刚好处于一个位置,使得放大后的圆形边缘刚好和侧边圆形的边缘相切;
  3. 如果你不想直接修改width/height,而是想用transform: scale()来放大,只需要把hover状态的代码换成transform: scale(var(--scale)),同时去掉width/height的修改,效果是一样的。

方案二:JS动态计算(适配更复杂的场景)

如果你的场景需要更灵活的控制(比如动态修改尺寸、缩放倍数随交互变化),可以用JS来获取圆形的初始尺寸,计算需要的transform参数,然后应用到元素上。

代码实现

.circles {
  display: flex;
}

.circles__item {
  height: 150px; /* 可以任意修改这个初始尺寸 */
  width: 150px;
  background: limegreen;
  border-radius: 50%;
  transition: all 500ms ease-out;
}

.circles__item:hover {
  background-color: rebeccapurple;
}
const circles = document.querySelectorAll('.circles__item');
const scaleFactor = 1.1; // 缩放倍数,可自定义

circles.forEach(circle => {
  const initialSize = circle.offsetWidth;
  const initialR = initialSize / 2;
  const hoverR = initialR * scaleFactor;
  // 计算需要的transform-origin x坐标
  const originX = initialR * (1 - scaleFactor) + hoverR;
  
  // 初始设置transform-origin
  circle.style.transformOrigin = `${originX}px center`;
  
  // hover时应用缩放
  circle.addEventListener('mouseenter', () => {
    circle.style.transform = `scale(${scaleFactor})`;
  });
  
  circle.addEventListener('mouseleave', () => {
    circle.style.transform = 'scale(1)';
  });
});

原理说明

  1. JS先获取每个圆形的初始尺寸,根据缩放倍数计算出hover后的半径;
  2. 通过几何公式计算transform-origin的x坐标,确保缩放后的圆形刚好和侧边圆形相切;
  3. 监听hover事件,动态应用缩放效果,完全适配任意初始尺寸。

关键注意点

  • 不要同时混合width/height修改和transform: scale():这两种方式都会改变元素尺寸,同时使用会导致计算混乱,选一种即可;
  • 如果你用flex布局,确保容器有足够的宽度容纳放大后的元素,或者设置flex-wrap: nowrap避免换行;
  • 两种方案都支持任意初始尺寸和缩放倍数,你只需要修改对应的参数(CSS变量或JS里的scaleFactor)即可。

内容的提问来源于stack exchange,提问作者Afron Orana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 09:22:32