简体   繁体   English

如何仅对水平和垂直进行框转换?

[英]How can I make box transition only for horizontal and vertical?

I'm trying to make a box moving by horizontal and vertical on the arrows press.我试图让一个盒子在箭头按下时水平和垂直移动。 But when I pres for example up arrow and right arrow it goes by diagonal.但是当我按下例如up arrowright arrow它会按对角线移动。 Here is my codepen这是我的代码笔

.box {
  background-color: gray;
  height: 100px;
  width: 100px;
  transition: margin 0.5s cubic-bezier(0, .7, 0, 1);
}
const box = document.getElementsByClassName('box')[0];

document.addEventListener('keydown', function({keyCode, which}) {
  const keycode = keyCode ? keyCode : which,
        startValue = '0px',
        shiftValue = '400px';

  console.log(box.style.marginLeft, box.style.marginTop)
  switch(keycode) {
    case(40):
      box.style.marginTop = shiftValue;
      break;
    case(39):
      box.style.marginLeft = shiftValue;
      break;
    case(38):
      box.style.marginTop = startValue;
      break;
    case(37):
      box.style.marginLeft = startValue;
      break;
  }
});

Try the following:请尝试以下操作:

const box = document.getElementsByClassName('box')[0];

let moving = false;

document.addEventListener('keydown', function({keyCode, which}) {
  const keycode = keyCode ? keyCode : which,
        startValue = '0px',
        shiftValue = '400px';

  console.log(box.style.marginLeft, box.style.marginTop)
  if (!moving && [37, 38, 39, 40].includes(keycode)){
      switch(keycode) {
        case(40):
          box.style.marginTop = shiftValue;
          break;
        case(39):
          box.style.marginLeft = shiftValue;
          break;
        case(38):
          box.style.marginTop = startValue;
          break;
        case(37):
          box.style.marginLeft = startValue;
          break;
      }
      moving = true;
      window.setTimeout(() => moving = false, 400); // Not 500, because visually it is very slow towards the end anyway.
  }
});

Either you could implement a Promise solution in here but I don't think it's worth justifying.您可以在这里实施Promise解决方案,但我认为这不值得证明。 Basically what we can do is to store all the keys pressed in an array and make sure the javascript only goes through the array of pressed keys once every x milliseconds.基本上我们可以做的是将所有按下的键存储在一个数组中,并确保 javascript 每x毫秒只遍历一次按下的键数组。

const box = document.getElementsByClassName('box')[0];
let pressedKeys = [];
let timeoutHandler = -1;

document.addEventListener('keydown', function({keyCode, which}) {
  // As soon as the user presses a key we will clear the time out
  clearTimeout(timeoutHandler);

  const keycode = keyCode ? keyCode : which,
    startValue = '0px',
    shiftValue = '400px';

  pressedKeys.push(keycode);

  // register the timeout to a variable in order for this function 
  // only run once every x second. This implementation is also 
  // known as 'debounce function to poor people'
  timeoutHandler = setTimeout(() => {
    pressedKeys.forEach((key, index) => {
      // The animation time for each key pressed will be incremental
      // which means the second key pressed will have an animation delay
      // higher than the first one
      const timeoutSeconds = index === 0 ? 1 : index + (index * 100);
      setTimeout(() => {
        switch(key) {
          case(40):
            box.style.marginTop = shiftValue;
            break;
          case(39):
            box.style.marginLeft = shiftValue;
            break;
          case(38):
            box.style.marginTop = startValue;
            break;
          case(37):
            box.style.marginLeft = startValue;
            break;
        }
      }, timeoutSeconds)
    });

    pressedKeys = [];
  }, 100)
});

One possible solution: you could keep track of which moves have been requested and wait to perform the move until the previous move has finished.一种可能的解决方案:您可以跟踪已请求的移动并等待执行移动,直到前一个移动完成。 Example:例子:

const box = document.getElementsByClassName('box')[0];

const startValue = '0px';
const shiftValue = '400px';

function moveDown() {
  // The move* functions only perform the move if is valid - i.e., 
  // if it would actually cause a visible change.
  if (box.style.marginTop !== shiftValue) {
    box.style.marginTop = shiftValue;
    return true;
  }
  // The move* functions return true iff the move was made.
  return false;
}

function moveRight() {
  if (box.style.marginLeft !== shiftValue) {
    box.style.marginLeft = shiftValue;
    return true;
  }
  return false;
}

function moveUp() {
  if (box.style.marginTop !== startValue) {
    box.style.marginTop = startValue;
    return true;
  }
  return false;
}

function moveLeft() {
  if (box.style.marginLeft !== startValue) {
    box.style.marginLeft = startValue;
    return true;
  }
  return false;
}

const moves = [];
let timeOfLastMoveInMilliseconds = null;
const animationDurationInSeconds = 0.5; // should match css transition duration
const animationDurationInMilliseconds = animationDurationInSeconds * 1000; 

function onFrame() {
  if (!timeOfLastMoveInMilliseconds) {
    timeOfLastMoveInMilliseconds = performance.now();
  }
  const timeSinceLastMove = performance.now() - timeOfLastMoveInMilliseconds;
  if (moves.length > 0 && timeSinceLastMove >= animationDurationInMilliseconds) {
    const wasMoved = moves.pop()();
    if (wasMoved) {
      timeOfLastMoveInMilliseconds = performance.now();
    }
  }
  window.requestAnimationFrame(onFrame);
}
window.requestAnimationFrame(onFrame);

document.addEventListener('keydown', function({keyCode, which}) {
  const keycode = keyCode ? keyCode : which;
  switch(keycode) {
    case(40):
      moves.unshift(moveDown);
      break;
    case(39):
      moves.unshift(moveRight);
      break;
    case(38):
      moves.unshift(moveUp);
      break;
    case(37):
      moves.unshift(moveLeft);
      break;
  }
});

Note that the code above keeps track of every move the user makes, so, eg, if you press down, up, down, up, down quickly, that sequence will play back.请注意,上面的代码会跟踪用户所做的每一个移动,因此,例如,如果您快速按下、向上、向下、向上、向下,该序列将播放。 Depending on your application, you might want to add restrictions so that, eg, only horizontal+diagonal moves are allowed and/or only moves coming from keypresses that happen within a short timeframe.根据您的应用程序,您可能想要添加限制,例如,仅允许水平+对角线移动和/或仅允许在短时间内发生的按键移动。

So, I decided to set 500 milliseconds breaks between every press on the key with animation and if it's faster without animation, but without any additional asynchronous code.所以,我决定在每次按下带有动画的键之间设置 500 毫秒的间隔,如果没有动画会更快,但没有任何额外的异步代码。 Thanks for the help.谢谢您的帮助。

.box {
  background-color: gray;
  height: 100px;
  width: 100px;
}

.animation {
  transition: margin 0.5s cubic-bezier(0, .7, 0, 1);
}
const box = document.getElementsByClassName('box')[0];
let prevTime = 0;

document.addEventListener('keydown', function({keyCode, which}) {
  const keycode = keyCode ? keyCode : which,
        startValue = '0px',
        shiftValue = '400px',
        currentTime = Date.now();
  let diff = 0;

  diff = currentTime - prevTime;

  if (diff > 500) {
    box.classList.add('animation');
  } else {
    box.classList.remove('animation');
  }

  switch(keycode) {
    case(40):
      box.style.marginTop = shiftValue;
      break;
    case(39):
      box.style.marginLeft = shiftValue;
      break;
    case(38):
      box.style.marginTop = startValue;
      break;
    case(37):
      box.style.marginLeft = startValue;
      break;
  }

  prevTime = currentTime;
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何制作水平/垂直滚动动画? - How can I make horizontal/vertical scroll animation in/out? 如何在全屏模式下使垂直div变为水平 - How can i make a vertical div go horizontal in full screen 我可以在网页上劫持垂直滚动动作并将其水平移动吗? - On a webpage can I hijack the vertical scrolling action and make it horizontal? 在HTML表格中,如何使垂直线可见(与默认水平线相同)? - In an HTML table, how can I make vertical lines visible (the same kind as the default horizontal ones)? 如何在单轴上(例如,对于特定旋转)在水平或垂直轴上制作图像动画 - How can I make animation of image in a single axis ie., for a particular rotation - on horizontal or vertical axis 当水平内容溢出时,如何使垂直滚动条停留在视口中? - How can I make the vertical scrollbar stay in viewport while its horizontal content overflows? 如何将自定义列表的方向从垂直转换为水平 - How can I shift the orientation of a custom list from vertical to horizontal 如何进行平滑的幻灯片过渡? - How can I make smooth slide transition? 如何使我的水平Spry菜单栏垂直? - How to make my horizontal Spry menubar vertical? 如何仅绘制垂直和水平线(画布) - how draw only vertical and horizontal lines (Canvas)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM