The snippet below contains an array of 10 items. I'm able to drag and drop the list items and even able to achieve some basic animations when grabbing the list item:
const App = () => {
const [myArray, setMyArray] = React.useState([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const [draggedIndex, setDraggedIndex] = React.useState(-1);
const onDragStart = (e, index) => {
setDraggedIndex(index);
const emptyDiv = document.createElement('div');
emptyDiv.style.width = '0px';
emptyDiv.style.height = '0px';
e.dataTransfer.setDragImage(emptyDiv, 0, 0);
e.currentTarget.className = 'draggable';
};
const onMouseDown = (e) => {
e.currentTarget.className = 'draggable';
};
const onMouseUp = (e) => {
e.currentTarget.className = 'listItem';
};
const onDragOver = (e, index) => {
e.preventDefault();
if (draggedIndex === -1 || draggedIndex === index) {
return;
}
let items = myArray.filter((item, i) => i !== draggedIndex);
items.splice(index, 0, myArray[draggedIndex]);
setMyArray(items);
setDraggedIndex(index);
};
const onDragEnd = (e) => {
setDraggedIndex(-1);
e.target.className = 'listItem';
};
return (
<div className="App">
{myArray.map((x, i) => (
<div
className="listItem"
draggable
key={x}
onDragStart={(e) => onDragStart(e, i)}
onDragOver={(e) => onDragOver(e, i)}
onDragEnd={onDragEnd}
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
>
<h3>hello - {x}</h3>
</div>
))}
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
.App {
text-align: center;
align-items: center;
display: flex;
flex-direction: column;
}
.listItem {
border: 2px solid black;
margin: 5px;
width: 400px;
cursor: grab;
transform: scale(100%);
transition: transform 0.3s ease-in-out;
}
.draggable {
border: 2px solid green;
margin: 5px;
width: 400px;
cursor: grab;
transform: scale(108%);
transition: transform 0.3s ease-in-out;
}
.listItem:-moz-drag-over {
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Can I get help with CSS animations to make the list item movements smoother during dragging so it looks less choppy? The goal is to achieve the following effect - when I drag an item it would smoothly reposition itself up/down, and the item that is being dragged over would smoothly move in the opposite direction.
EDIT 1:
Please check the code snippet, run it, and try to drag the list items to understand my requirements.Basically, what I want is to animate the transition of the dragged item depending on which direction (up or down) the item is being dragged. In theory, while dragging an item up, it could apply a class something like .dragged-up and that class would have animation/transition that would create an illusion that that item moving from the lower to the higher position.
The same principle could be applied to the items above and below the item being dragged. For example, If the item that is being dragged over moves from the top to the bottom, a different class could be applied, something like .listItem-down, and that class could contain an opposite animation. Also, I suspect it would need to have a lower z-index so it would appear below the dragged item.
Not sure if it's the most efficient approach and if it's possible to do it that way at all. So far, while trying to implement something like this, I've been getting issues of items overlapping and as a result, the event function was being executed on the wrong div, causing some undesired effects.
Some help and a working snippet would be much appreciated!