【问题标题】:Use absolute coordinates with transform translate将绝对坐标与变换转换一起使用
【发布时间】:2021-10-11 11:24:47
【问题描述】:

我可以用以下内容制作一个跟随鼠标的框。

document.addEventListener('mousemove', (e) => {
    document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
    document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});
.box {
  width: 50px;
  height: 50px;
  
  background-color: blue;
  
  transform: translate(calc(var(--mouse-x) - 50%), calc(var(--mouse-y) - 50%));
}
<div class="box"></div>

但只要元素不在左上角,它就会中断。

document.addEventListener('mousemove', (e) => {
    document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
    document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});
.box {
  width: 50px;
  height: 50px;
  
  margin-left: 150px;
  
  background-color: blue;
  
  transform: translate(calc(var(--mouse-x) - 50%), calc(var(--mouse-y) - 50%));
}
<div class="box"></div>

如何在变换中使用绝对坐标?我不想使用 left/top/position: fixed/absolute 因为我需要保留元素在流中的位置。

我可以使用 JavaScript 来获取中心位置,然后使用该信息来获取正确的中心。

document.addEventListener('mousemove', (e) => {
    document.documentElement.style.setProperty('--mouse-x', e.clientX + 'px');
    document.documentElement.style.setProperty('--mouse-y', e.clientY + 'px');
});

window.addEventListener('load', (e) => {
    const box = document.querySelector('.box');
    const rect = box.getBoundingClientRect();
    box.setAttribute('style', `
      --center-x: ${rect.left + (rect.width / 2)}px;
      --center-y: ${rect.top + (rect.height / 2)}px;
    `);
});
.box {
  width: 50px;
  height: 50px;
  
  margin-left: 150px;
  
  background-color: blue;
  
  transform: translate(calc(var(--mouse-x) - var(--center-x)), calc(var(--mouse-y) - var(--center-y)));
}
<div class="box"></div>

这可行,但如果页面中的其他任何内容发生变化,它并不理想并且很容易被破坏。它也会随着更多元素而减慢,我希望它尽可能快。有更好的方法吗?我可以使用 CSS/Vanilla JS。

【问题讨论】:

    标签: javascript html css


    【解决方案1】:

    您不必使用translate(),我建议您在CSS 中使用lefttop 属性。它们可以帮助您根据坐标定位元素。

    window.addEventListener('load', (e) => {
        const box = document.querySelector('.box');
        const rect = box.getBoundingClientRect();
        document.addEventListener('mousemove', (e) => {
        box.style.left = e.pageX + 'px';
        box.style.top = e.pageY + 'px';
    });
    });
    .box {
      width: 50px;
      height: 50px;
      position:absolute;
      transform:translate(-50%,-50%);
      background-color: blue;
    }
    <div class="box"></div>

    transform: translate() 属性相对于框的大小起作用,但 lefttop 属性不起作用。在某些情况下它也可以更快,因为在您的代码中进行了大量计算。然而,这很简单。

    【讨论】:

    • 感谢您的回答。它可以满足我的需要,但我想避免使用 top 和 left,这样我就可以在进入和退出内容流之间平滑地制作动画。
    • 好的@Jack,所以你想使用翻译而不是顶部和左侧?
    • 理想情况下,但我不知道在保持快速的同时如何做到这一点。我要让尽可能多的元素移动,所以速度对我来说真的很重要。我发现当我使用 top 并离开时,一切都变慢了。我必须做更多的测试,看看最好的方法是什么。
    • @Jack 我不确定我是否知道方法
    • @Jack 你想看到requestAnimationFrame()的答案吗?它通常用于制作高质量的动画,所以我们也可以在这里使用它
    【解决方案2】:

    这是使用requestAnimationFrame() 函数的解决方案。 requestAnimationFrame() 方法告诉浏览器您希望执行动画并请求浏览器在下一次重绘之前调用指定的函数来更新动画。对于更高刷新率的显示器,此函数将运行更多次以匹配刷新率。

    更多信息here

    这是可行的解决方案:

    const box = document.querySelector('.box');
    const rect = box.getBoundingClientRect();
    let mouseX = 0;
    let mouseY = 0
    document.addEventListener('mousemove', (e) => {
      mouseX = e.pageX + 'px';
      mouseY = e.pageY + 'px';
    })
    
    function mouseMove() {
      box.style.left = mouseX;
      box.style.top = mouseY;
      requestAnimationFrame(mouseMove)
    };
    mouseMove()
    .box {
      width: 50px;
      height: 50px;
      position: absolute;
      transform: translate(-50%, -50%);
      background-color: blue;
    }
    <div class="box"></div>

    【讨论】:

    • 谢谢!因为你的答案仍然使用左右,所以我不会接受。不过还是谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 1970-01-01
    • 2013-10-17
    • 2013-03-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多