【问题标题】:How to move a button near to cursor when cursor is coming and move a little more far when cursor is leaving如何在光标到来时将按钮移动到光标附近并在光标离开时将按钮移动得更远
【发布时间】:2019-12-25 16:52:38
【问题描述】:

我正在尝试创建一个小鼠标移动动画。当光标靠近按钮时,我称之为 borderline - 距离按钮一定距离时,按钮会向光标方向移动。

在这里,为了清晰和理解,我用 css 显示了两个虚线 borderline 步骤。 我通过计算按钮的中心点并在 x 和 y 轴上减少和添加按钮的宽度和高度,从代码中创建了最近的 borderline

我想在我正在工作的同一过程中解决这个问题,而不是通过将其他 event-listener 添加到按钮的 parent-elements 中。

这是我尝试过的..

const button = document.querySelector(".button");
let { width, height, x: buttonX, y: buttonY } = button.getBoundingClientRect(); // gives you width, height, left-X,top-y of the button

buttonX = buttonX + width / 2; //  center point of button on x-axis
buttonY = buttonY + height / 2; //  center point of button on y-axis

/*************** Functions ***************/

let distance = width;
let mouseHasEntered = true;
let mouseIsInButtonTerritory;

function mouseMove(e) {
  const x = e.x; // current x of cursor
  const y = e.y; // current y of cursor

  const leftBorderLine = buttonX - distance;
  const rightBorderLine = buttonX + distance;
  const topBorderLine = buttonY - distance;
  const bottomBorderline = buttonY + distance;
  const xWalk = (x - buttonX) / 2; // the distance to move the button when mouse moves on X axis
  const yWalk = (y - buttonY) / 2; // the distance to move the button when mouse moves on Y axis

  mouseIsInButtonTerritory =
    x > leftBorderLine &&
    x < rightBorderLine &&
    y > topBorderLine &&
    y < bottomBorderline; // becomes true if  mouse is inside all of these border-line

  if (mouseIsInButtonTerritory) {
    if (mouseHasEntered) {
      // this must happen only once to create outside borderline
      //creating another level borderline by incresing distance;
      // while cursor is returing the button comes out of nearest border-line and return from this borderline
      distance = distance + distance;
      mouseHasEntered = false;
    }
    catchCursor(xWalk, yWalk); // call the function when mouse in in the button's territory
  } else {
    resetPositon();
  }
}

function catchCursor(xWalk, yWalk) {
  // translates the button in the direction where cursor is.
  button.style.transform = `translate(${xWalk}px, ${yWalk}px)`;
}

function resetPositon() {
  // resets the postion of the button as it was initial.
  button.style.transform = `translate(${0}px, ${0}px)`;
  mouseHasEntered = true;
  // when button is return to it's position (mouseHasEntered = true) lets to increase the initial borderline of button for the next time
}

/*************** Event-handler ***************/

window.addEventListener("mousemove", mouseMove);
window.addEventListener("mouseout", resetPositon);
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --gutter-lg: 4rem;
  --gutter-md: 3rem;
  --gutter-sm: 1rem;
  --gutter-xm: 1rem;
  --color-white: #fff;
  --color-black: #000;
}

body {
  background: var(--color-black);
  font: 16px verdana;
  color: var(--color-white);
}

.banner {
  display: flex;
  height: 100vh;
}

.button {
  margin: auto;
  cursor: pointer;
  transition: all 0.2s ease-out;
}

.button-wrap-wrapper {
  width: 192px;
  height: 192px;
  border: 1px dashed #fff;
  margin: auto;
  display: flex;
}

.button-wrap {
  width: 128px;
  height: 128px;
  margin: auto;
  /* background: orange; */
  display: flex;
  justify-content: center;
  align-items: center;
  border: 1px dashed #fff;
}

.button__like-text {
  display: block;
  color: var(--color-black);
  background: var(--color-white);
  width: var(--gutter-lg);
  height: var(--gutter-lg);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
<section class="banner">
      <div class="button-wrap-wrapper">
        <div class="button-wrap">
          <div class="button">
            <span class="button__like-text">
              Like
            </span>
          </div>
        </div>
      </div>
    </section>

没有按预期工作的是:mouseIsInButtonTerritory 变为真,我正在尝试在此处增加 borderline

 if (mouseHasEntered) {
      // this must happen only once to create outside borderline
      //creating another level borderline by incresing distance;
      // while cursor is returing the button comes out of nearest border-line and return from this borderline
      distance = distance + distance;
    }

按钮一直跟随光标。

我要解决的是,如果光标从两条 borderlines 出来,则按钮必须越过第一个 borderline 并靠近最后一个 边界线 并回到初始阶段的位置。

我没有找到我做错的地方。有什么遗漏的吗?

【问题讨论】:

    标签: javascript mouseevent mousemove


    【解决方案1】:
    • 你应该在鼠标离开时重新设置距离。 (我不确定,猜猜这就是你想要的,因为你在重置时写了mouseHasEntered = true
    • 因为你处理鼠标离开自己(else mouseIsInButtonTerritory 部分)不要听窗口。

    const button = document.querySelector(".button");
    let { width, height, x: buttonX, y: buttonY } = button.getBoundingClientRect(); // gives you width, height, left-X,top-y of the button
    
    buttonX = buttonX + width / 2; //  center point of button on x-axis
    buttonY = buttonY + height / 2; //  center point of button on y-axis
    
    /*************** Functions ***************/
    
    let distance = width;
    let mouseHasEntered = true;
    let mouseIsInButtonTerritory;
    
    function mouseMove(e) {
      const x = e.x; // current x of cursor
      const y = e.y; // current y of cursor
    
      const leftBorderLine = buttonX - distance;
      const rightBorderLine = buttonX + distance;
      const topBorderLine = buttonY - distance;
      const bottomBorderline = buttonY + distance;
      const xWalk = (x - buttonX) / 2; // the distance to move the button when mouse moves on X axis
      const yWalk = (y - buttonY) / 2; // the distance to move the button when mouse moves on Y axis
    
      mouseIsInButtonTerritory =
        x > leftBorderLine &&
        x < rightBorderLine &&
        y > topBorderLine &&
        y < bottomBorderline; // becomes true if  mouse is inside all of these border-line
    
      if (mouseIsInButtonTerritory) {
        if (mouseHasEntered) {
          // this must happen only once to create outside borderline
          //creating another level borderline by incresing distance;
          // while cursor is returing the button comes out of nearest border-line and return from this borderline
          distance = distance + distance;
          mouseHasEntered = false;
        }
        catchCursor(xWalk, yWalk); // call the function when mouse in in the button's territory
      } else {
        resetPositon();
      }
    }
    
    function catchCursor(xWalk, yWalk) {
      // translates the button in the direction where cursor is.
      button.style.transform = `translate(${xWalk}px, ${yWalk}px)`;
    }
    
    function resetPositon() {
      // resets the postion of the button as it was initial.
      button.style.transform = `translate(${0}px, ${0}px)`;
      if(!mouseHasEntered)distance/=2;
      mouseHasEntered = true;
      // when button is return to it's position (mouseHasEntered = true) lets to increase the initial borderline of button for the next time
    }
    
    /*************** Event-handler ***************/
    
    window.addEventListener("mousemove", mouseMove);
    //window.addEventListener("mouseout", resetPositon);
    *,
    *::before,
    *::after {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    :root {
      --gutter-lg: 4rem;
      --gutter-md: 3rem;
      --gutter-sm: 1rem;
      --gutter-xm: 1rem;
      --color-white: #fff;
      --color-black: #000;
    }
    
    body {
      background: var(--color-black);
      font: 16px verdana;
      color: var(--color-white);
    }
    
    .banner {
      display: flex;
      height: 100vh;
    }
    
    .button {
      margin: auto;
      cursor: pointer;
      transition: all 0.2s ease-out;
    }
    
    .button-wrap-wrapper {
      width: 192px;
      height: 192px;
      border: 1px dashed #fff;
      margin: auto;
      display: flex;
    }
    
    .button-wrap {
      width: 128px;
      height: 128px;
      margin: auto;
      /* background: orange; */
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px dashed #fff;
    }
    
    .button__like-text {
      display: block;
      color: var(--color-black);
      background: var(--color-white);
      width: var(--gutter-lg);
      height: var(--gutter-lg);
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
    }
    <section class="banner">
          <div class="button-wrap-wrapper">
            <div class="button-wrap">
              <div class="button">
                <span class="button__like-text">
                  Like
                </span>
              </div>
            </div>
          </div>
        </section>

    【讨论】:

    • 是的!这就是结果。但我不明白为什么: :else { resetPositon(); } 不要听做窗口。
    • @SandeshSapkota 好吧,我的意思是你应该删除 window.addEventListener("mouseout", resetPositon);
    【解决方案2】:

    如果我正确理解您的意图,我认为您需要:

    1. 添加 buttonWrapWrapper 选择器
    const button = document.querySelector(".button");
    const buttonWrapWrapper = document.querySelector(".button-wrap-wrapper");
    
    1. 附加事件监听器到buttonWrapWrapper而不是window
    buttonWrapWrapper.addEventListener("mousemove", mouseMove);
    buttonWrapWrapper.addEventListener("mouseout", resetPositon);
    

    【讨论】:

    • 好吧,OP 的代码中没有button.addEventListener
    • @appleapple,对不起,而不是window.addEventListener。我已经修好了
    • @MuhammedIbrahim 我不想通过添加其他事件处理程序和使用其他元素来解决它。我通过计算在代码上创建了一步边界。评论if (mouseHasEntered) {}块,看看你会明白更多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多