鼠标移动事件 - 根据鼠标位置定位的div位置发生了翻转。

3

编辑 - 这里有一个fiddle:http://jsfiddle.net/cLahpqoj/1/,这是我想要做的一个示例:https://www.seventh.tv/


也许我的设置门位置的数学计算有误导致出现问题。注意到鼠标位置和门位置在值上交换了。日志记录:

{doorX: -1066, x: 396, doorY: -1367, y: 164}
{doorX: 396, x: -1065, doorY: 164, y: -1367}

来源:

   let mouseX =  e.offsetX;
        let mouseY = e.offsetY;

        let doorX = currentDoorRect.x;
        let doorY = currentDoorRect.y;

        let x = doorX;
        let y = doorY;

        x =  -( x + (mouseX) );
        y =  -( y + (mouseY) );

        let transform = 'translate(' + x + 'px,' + y + 'px)';
        currentDoor.style.transform = transform;




          console.log( {
            doorX,
            x,
            doorY,
            y
          });


我正在尝试使用 transform:translate(x,y) css 属性根据当前 div 位置和鼠标位置移动一个 div。

我记录了传递给变换的 x 和 y 值,并注意到对于每个值更改,都会有一个前置值为 x: -1,y:0 的值更改,然后立即回到应该的值(即 x:-563,y:424

我正在使用 Vue.js,该函数是:

<template>
  <div ref="test-container" id="test-container" class="h-full relative" 
  @mousedown.prevent="disableMiddleClickScroll"
  @mousemove="moveDoors"
  @wheel="disableWheelScroll">
    <div
      :ref="`door-${index}`"
      v-for="index in numDoors" :key="index"
      class="door bg-gray-300 p-8  text-center rounded flex-none">
      Door
      </div>
  </div>
</template>

...

moveDoors(e) {
        let mouseX =  e.offsetX;
        let mouseY = e.offsetY;

   
          let currentDoor = this.$refs[`door-1`];
          let currentDoorRect = currentDoor.getBoundingClientRect();

          let doorX = currentDoorRect.x;
          let doorY = currentDoorRect.y;

          let x =  -( doorX + (mouseX) );
          let y =  -( doorY + (mouseY) );

          console.log( {
            x,
            y
          });

          let transform = 'translate(' + x + 'px,' + y + 'px)';
          currentDoor.style.transform = transform;

    
        
      },

这个事件被称为这样:
控制台日志示例:
{x: 1, y: -0}
{x: -547, y: -426}
{x: 1, y: -0}
{x: -545, y: -426}
{x: -0, y: 1}
{x: -544, y: -425}
{x: -0, y: 1}
{x: -546, y: -424}
{x: -1, y: -0}
容器的CSS样式是:
#test-container {
  position: fixed;
    left: 0%;
    top: 0%;
    right: 0%;
    bottom: 0%;
    
}

如果没有足够的信息进行调试,请告知我。我认为这就是所有相关的信息。


我会更改我的示例,因为我在循环中只设置了1个门。即使没有循环,问题仍然存在。门div闪烁,x和y值显示奇怪的0和-1值。mousemove事件也在容器上而不是门上。 - good_afternoon
你能让你的示例可验证吗?也就是说,能提供一个可工作的代码片段吗? - Lawrence Cherone
好的,我会做。我使用Vue CLI生成了这个,所以我会看看在jsfiddle里我能做些什么。 - good_afternoon
@LawrenceCherone 抱歉回复晚了,以下是一个 jsfiddle 链接:http://jsfiddle.net/cLahpqoj/1/ - good_afternoon
这里的“relative”是什么意思?它目前相对于鼠标位置在移动。它可以沿着相反方向、同一方向乘以3000倍,实际上任何方式移动,所有这些都将是“相对于鼠标位置”,但你可以猜测它们完全不同。 - Kaiido
显示剩余6条评论
1个回答

3
如果您想要的是这个网站正在做的事情,那么是的,您不需要数学知识,并且您的策略也有点不对。他们所做的是将视口位置简单映射到内容位置。您不需要单独移动每个元素,只需移动主容器即可。
基本上,如果您将光标移动到视口中心,则内容将移动,使其中心位于视口中心。如果您将其移动到屏幕左上角,则内容将移动,以便您看到内容的左上角。
要实现此操作,有多种策略。其中一种是将鼠标位置映射到[0,1]范围内,然后将此比率乘以内容大小。然后,您只需调整一半的视口大小,整个内容就会正确居中。

const content = document.querySelector(".content");

document.onmousemove = (evt) => {
  // the mouse position (in the viewport)
  const viewport_x = evt.clientX;
  const viewport_y = evt.clientY;
  // the viewport size
  const viewport_width  = window.innerWidth;
  const viewport_height = window.innerHeight;
  // the mouse position, still relative to the viewport
  // but in a range [0, 1]
  const ratio_x = viewport_x / viewport_width;
  const ratio_y = viewport_y / viewport_height;
  
  // our content's size
  const content_rect = content.getBoundingClientRect();
  const content_width = content_rect.width;
  const content_height = content_rect.height;
  // transform the mouse position to the content's position
  const content_x = content_width * ratio_x;
  const content_y = content_height * ratio_y;
  // remove it from half the size of the viewport
  // so that aiming at the center of the viewport
  // shows the center of our content
  const translate_x = viewport_width  / 2 - content_x;
  const translate_y = viewport_height / 2 - content_y;

  content.style.setProperty("--translate-x", translate_x + "px");
  content.style.setProperty("--translate-y", translate_y + "px");

};
.content {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
  transition: transform .5s ease-out;
  width: 150vw;
  height: 250vh;
  transform: translate(var(--translate-x), var(--translate-y));
  --translate-x: -25vw; /* (150vw - 100vw) / 2 */
  --translate-y: -75vh; /* (250vh - 100vw) / 2 */
}
.frame {
  border: 1px solid;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  counter-increment: frame;
}
.frame::after {
  content: counter(frame);
}
body, :root {
  overflow: auto;
  border: 0px;
}
<div class="content">
  <div class="frame"></div>  
  <div class="frame"></div>
  <div class="frame"></div>

  <div class="frame"></div>
  <div class="frame"></div>
  <div class="frame"></div>

  <div class="frame"></div>
  <div class="frame"></div>
  <div class="frame"></div>

  <div class="frame"></div>
  <div class="frame"></div>
  <div class="frame"></div>

  <div class="frame"></div>
  <div class="frame"></div>
  <div class="frame"></div>
</div>


谢谢Kaiido。我今天会研究一下这个。当我检查他们的网站时,我看到每个元素都在变化,而不是容器。所以这就是为什么我尝试了我所做的事情。 - good_afternoon
说实话,我甚至没有看过他们是如何做到的,就像我说的,有各种策略,但对我来说,只移动容器似乎是最简单的方法。 - Kaiido
谢谢。这似乎是一个更好的方法来处理问题,而且更容易。我认为我参考的网站也在使用工具(无论 https://webflow.com/ 是什么)。我认为这很棒 - 我只需要在容器到达边界时不允许太多的空白空间在 x、y 坐标上。这应该不是问题。再次感谢。 - good_afternoon
@Kaiido 你好,使用这个解决方案,移动会被限制在内容的边界内吗?也就是说,没有空白空间。 - undefined
@good_afternoon 你好,你是如何去除两侧的空白空间的? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接