[英]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 arrow
和right 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.