在 javascript 中使用箭头键移动所选元素
move selected element with arrow keys in javascript
我有一个项目列表,我希望能够 select 一个项目(通过单击)并仅使用箭头键移动该特定项目。我完成了移动部分,但是当我 select 第二个元素时,它也移动了之前 selected 的元素。或者,如果我双击同一个元素,它会将其弹回到原来的位置。
我猜可能是因为位置是相对的?虽然我已经尝试将其更改为 absolute 并将 parent div 更改为 relative ,但仍然没有用。我也尝试过使用边距,但出现了同样的问题。
move();
function move(){
let list_items = document.querySelectorAll('.list-item');
for (let i = 0; i < list_items.length; i ++){
let list=list_items[i];
list.addEventListener('click',function(){
console.log(list);
var objImage= null;
objImage=list;
objImage.style.position='relative';
objImage.style.left='0px';
objImage.style.top='0px';
function getKeyAndMove(e){
var key_code=e.which||e.keyCode;
switch(key_code){
case 37: //left arrow key
moveLeft();
break;
case 38: //Up arrow key
moveUp();
break;
case 39: //right arrow key
moveRight();
break;
case 40: //down arrow key
moveDown();
break;
default:
console.log(e);
}
}
function moveLeft(){
objImage.style.left=parseInt(objImage.style.left)-5 +'px';
// objImage.style.position='static';
}
function moveUp(){
objImage.style.top=parseInt(objImage.style.top)-5 +'px';
// objImage.style.position='static';
}
function moveRight(){
objImage.style.left=parseInt(objImage.style.left)+5 +'px';
// objImage.style.position='static';
}
function moveDown(){
objImage.style.top=parseInt(objImage.style.top)+5 +'px';
// objImage.style.position='static';
}
window.addEventListener("keydown", getKeyAndMove);
});
}
}
.list {
display: flex;
flex-flow: column;
flex: 1;
width: 100%;
min-width: 250px;
max-width: 350px;
height: 100%;
min-height: 150px;
background-color: rgba(0, 0, 0, 0.1);
margin: 0 15px;
padding: 8px;
transition: all 0.2s linear;
}
.list .list-item {
background-color: #F3F3F3;
border-radius: 8px;
padding: 15px 20px;
text-align: center;
margin: 4px 0px;
}
<div class="list" id="list">
<h2>Menu Items</h2>
<div class="list-item" draggable="true">List item 1</div>
<div class="list-item" draggable="true">List item 2</div>
<div class="list-item" draggable="true">List item 3</div>
</div>
EDIT 通过@rexfordkelly 提出的解决方案让它工作。这是他 jsfiddle.net/r7ao2n5f/1
分享的 link 游乐场
如果我理解你的问题,并且你期望的行为是:
Move one or more selected items, selections being made using a mouse, and moving performed via key presses, up, down, left and right.
我想你几乎已经明白了,唯一的问题是你的选择永远不会被清除,这应该是在移动完成后发生任何点击时。
您可以考虑在模式中对行为进行建模。
- 选择
- 移动
用伪代码完成的行为是这样的:
let mode = 0; // selection mode
let selections = [];
... key press event Listeners
... click event Listeners
function processAction( action, event ) {
If ( 'click' == action && 0 != mode ){ // was in move mode
mode = 0; // Set to selection mode.
selections = []; // resets the selections made
... // reset DOM, and clear any currently decorated elements
}
if ( 'click' == action) {
selections.push(event.targetElement);
...// Update DOM and decorate elements
}
If ( 'move' === action && mode !== 1) {
mode = 1; // This enters us into "Move" mode.
}
If ( 'move' === action ){
// Execute moving logic
}
}
解决您的“双击”问题。
Or if I double click the same element, it snaps it back to it's original position
这是某些“标准”行为的结果,或者当用户拖动元素时浏览器对其行为的“预设”。您可以通过几种方式禁用此“标准”行为,一种是 CSS
.list-item {
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
user-drag: none;
}
您可以在 MDN here 上了解更多关于此“默认”行为的信息:
If this attribute is not set, its default value is auto, which means
drag behavior is the default browser behavior: only text selections,
images, and links can be dragged...
哦,我忘了说,你可以简单地将你的事件监听器附加到 id="list"
元素,因为所有 children 的点击事件都会冒泡并被拦截。
您可以找到有关如何确定单击了哪个元素的详细信息here and more about how events bubble here and on MDN here,特别是“冒泡和捕获解释”部分
PS:我在一些应用程序中也看到过,它们有类似的行为,用鼠标进行选择,用箭头键移动。当按住“shift”键并按下箭头键时,它们允许用户移动不同的距离。
我有一个项目列表,我希望能够 select 一个项目(通过单击)并仅使用箭头键移动该特定项目。我完成了移动部分,但是当我 select 第二个元素时,它也移动了之前 selected 的元素。或者,如果我双击同一个元素,它会将其弹回到原来的位置。
我猜可能是因为位置是相对的?虽然我已经尝试将其更改为 absolute 并将 parent div 更改为 relative ,但仍然没有用。我也尝试过使用边距,但出现了同样的问题。
move();
function move(){
let list_items = document.querySelectorAll('.list-item');
for (let i = 0; i < list_items.length; i ++){
let list=list_items[i];
list.addEventListener('click',function(){
console.log(list);
var objImage= null;
objImage=list;
objImage.style.position='relative';
objImage.style.left='0px';
objImage.style.top='0px';
function getKeyAndMove(e){
var key_code=e.which||e.keyCode;
switch(key_code){
case 37: //left arrow key
moveLeft();
break;
case 38: //Up arrow key
moveUp();
break;
case 39: //right arrow key
moveRight();
break;
case 40: //down arrow key
moveDown();
break;
default:
console.log(e);
}
}
function moveLeft(){
objImage.style.left=parseInt(objImage.style.left)-5 +'px';
// objImage.style.position='static';
}
function moveUp(){
objImage.style.top=parseInt(objImage.style.top)-5 +'px';
// objImage.style.position='static';
}
function moveRight(){
objImage.style.left=parseInt(objImage.style.left)+5 +'px';
// objImage.style.position='static';
}
function moveDown(){
objImage.style.top=parseInt(objImage.style.top)+5 +'px';
// objImage.style.position='static';
}
window.addEventListener("keydown", getKeyAndMove);
});
}
}
.list {
display: flex;
flex-flow: column;
flex: 1;
width: 100%;
min-width: 250px;
max-width: 350px;
height: 100%;
min-height: 150px;
background-color: rgba(0, 0, 0, 0.1);
margin: 0 15px;
padding: 8px;
transition: all 0.2s linear;
}
.list .list-item {
background-color: #F3F3F3;
border-radius: 8px;
padding: 15px 20px;
text-align: center;
margin: 4px 0px;
}
<div class="list" id="list">
<h2>Menu Items</h2>
<div class="list-item" draggable="true">List item 1</div>
<div class="list-item" draggable="true">List item 2</div>
<div class="list-item" draggable="true">List item 3</div>
</div>
EDIT 通过@rexfordkelly 提出的解决方案让它工作。这是他 jsfiddle.net/r7ao2n5f/1
分享的 link 游乐场如果我理解你的问题,并且你期望的行为是:
Move one or more selected items, selections being made using a mouse, and moving performed via key presses, up, down, left and right.
我想你几乎已经明白了,唯一的问题是你的选择永远不会被清除,这应该是在移动完成后发生任何点击时。
您可以考虑在模式中对行为进行建模。
- 选择
- 移动
用伪代码完成的行为是这样的:
let mode = 0; // selection mode
let selections = [];
... key press event Listeners
... click event Listeners
function processAction( action, event ) {
If ( 'click' == action && 0 != mode ){ // was in move mode
mode = 0; // Set to selection mode.
selections = []; // resets the selections made
... // reset DOM, and clear any currently decorated elements
}
if ( 'click' == action) {
selections.push(event.targetElement);
...// Update DOM and decorate elements
}
If ( 'move' === action && mode !== 1) {
mode = 1; // This enters us into "Move" mode.
}
If ( 'move' === action ){
// Execute moving logic
}
}
解决您的“双击”问题。
Or if I double click the same element, it snaps it back to it's original position
这是某些“标准”行为的结果,或者当用户拖动元素时浏览器对其行为的“预设”。您可以通过几种方式禁用此“标准”行为,一种是 CSS
.list-item {
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
user-drag: none;
}
您可以在 MDN here 上了解更多关于此“默认”行为的信息:
If this attribute is not set, its default value is auto, which means drag behavior is the default browser behavior: only text selections, images, and links can be dragged...
哦,我忘了说,你可以简单地将你的事件监听器附加到 id="list"
元素,因为所有 children 的点击事件都会冒泡并被拦截。
您可以找到有关如何确定单击了哪个元素的详细信息here and more about how events bubble here and on MDN here,特别是“冒泡和捕获解释”部分
PS:我在一些应用程序中也看到过,它们有类似的行为,用鼠标进行选择,用箭头键移动。当按住“shift”键并按下箭头键时,它们允许用户移动不同的距离。