JavaScript中transform origin未按预期工作问题排查
问题分析与修复方案
为啥会出问题?
- 坐标计算错误:你用
e.target获取元素位置时,若鼠标落在按钮内部的<span>元素上,得到的坐标是相对于<span>而非按钮本身的,直接导致原点位置偏差。 - 浏览器渲染合并:在同一个
mouseenter回调里连续修改transformOrigin和transform,浏览器会把这两个样式操作合并到同一帧渲染,结果波纹动画启动时,新的原点还没生效,只能用上一次的坐标。
修正后的代码
HTML(无需修改)
<div class="parent"> <a href="www.gotohell.com" class='button ripple'> <span></span> Live fullest! </a> </div>
CSS(无需修改)
.parent { display: flex; align-items: center; justify-content: center; height: 100vh; } .button { text-decoration: none; color: black; border: 1px solid black; padding: 20px 30px; border-radius: 32px; } .ripple { position: relative; overflow: hidden; transition: all .3s ease; } .ripple > span { border-radius: 32px; content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: black; transform: scale(0); transition: all .3s ease; z-index: -1; } .ripple:hover { color: white; }
JavaScript(关键修改)
const button = document.querySelector(".button"); const ripple = document.querySelector(".ripple > span"); button.addEventListener("mouseenter", function (e) { // 用currentTarget确保拿到绑定事件的按钮本身,不受内部子元素干扰 const rect = e.currentTarget.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; ripple.style.transformOrigin = `${x}px ${y}px`; // 延迟触发动画,让浏览器先完成原点更新再启动波纹扩散 requestAnimationFrame(() => { ripple.style.transform = "scale(1)"; }); }); button.addEventListener("mouseout", function () { ripple.style.transform = "scale(0)"; });
核心改动说明
- 替换
e.target为e.currentTarget:无论鼠标点击按钮内的哪个区域,都基于按钮本身的位置计算坐标,确保原点准确。 - 使用
requestAnimationFrame延迟动画:让浏览器先渲染完新的原点设置,再启动波纹缩放动画,保证动画使用当前鼠标位置作为扩散中心。
内容的提问来源于stack exchange,提问作者Darpan Aneja
相关产品推荐
相关产品推荐

