Issue
I have a JavaScript function to move different child elements across a parent div, but I want to add a transition so the elements move to their new position in the div instead of changing the position instantly.
As far as I used transitions, for me it only worked with defined properties, like top
/bottom
or height
/width
. In this case, I didn't define any properties, so I wonder if a transition effect is still possible.
Here you can see the children and the parent I set up, and my function for moving the child elements:
function moveElement(elementId, place) {
let div = document.getElementById('parent')
let element = document.getElementById(String(elementId))
let referencenode = div.children[place]
div.insertBefore(element, referencenode)
}
var children = document.getElementById('parent').children;
document.addEventListener("click", function(event) {
let id = children.item(2).id;
moveElement(id, 0)
});
<div id="parent">
<div id="child1" style="background-color:red" class="child">
<p>child1</p>
</div>
<div id="child2" style="background-color:lightblue" class="child">
<p>child2</p>
</div>
<div id="child3" style="background-color:green" class="child">
<p>child3</p>
</div>
<div id="child4" style="background-color:yellow" class="child">
<p>child4</p>
</div>
</div>
since all my attempts of making a working transition failed, I only left the switching function, so they switch places instantly.
I tried using transition-duration
, but since no CSS properties were defined, expected nothing happened.
Thanks in advance!
And please no jQuery, since I didn't ever use it, so if possible I would appreciate vanilla JavaScript :)
Solution
As the comments suggest, CSS transitions happen on CSS property changes, so some CSS property has to change for a transition to happen. For animating changes in order or DOM elements, you could consider using the First, Last, Invert, Play (FLIP) technique1234 whereby:
- First: get the initial position of the element(s).
- Last: make the element(s) to their ending state.
- Invert: use the information from the previous steps to invert the positional change back to how the element(s) look before the change occurred.
- Play: remove the inversion but with transitions, so that the element(s) animate back from inversion back to their new positions.
function moveElement(elementId, place) {
let div = document.getElementById('parent')
let element = document.getElementById(String(elementId))
const children = Array.from(element.parentElement.children);
let referencenode = children[place]
// Get the child index of the element being moved.
const elementIndex = children.indexOf(element);
// Get the list of elements that will move.
const movingChildren = children.slice(
elementIndex > place ? place : elementIndex,
(elementIndex > place ? elementIndex : place) + 1,
);
// Capture the positions of the elements being moved (First).
const before = movingChildren.map(
movingChild => movingChild.getBoundingClientRect(),
);
// Do the moving (Last).
div.insertBefore(element, referencenode);
// Do the animations.
movingChildren.forEach((child, i) => {
// Get the moved position.
const newPosition = child.getBoundingClientRect();
// `transform` the element back to their old position (Invert).
child.style.transform = `translate(${before[i].x - newPosition.x}px, ${before[i].y - newPosition.y}px)`;
// Initialize the transition on the next render frame.
requestAnimationFrame(() => {
// Clear transitioning.
const clearTransition = () => {
child.style.transition = '';
child.removeEventListener('transitionend', clearTransition);
};
child.addEventListener('transitionend', clearTransition);
// Do the transition (Play).
child.style.transition = 'transform 250ms';
child.style.transform = '';
});
});
}
var children = document.getElementById('parent').children;
document.addEventListener("click", function(event) {
let id = children.item(2).id;
moveElement(id, 0)
});
<div id="parent">
<div id="child1" style="background-color:red" class="child">
<p>child1</p>
</div>
<div id="child2" style="background-color:lightblue" class="child">
<p>child2</p>
</div>
<div id="child3" style="background-color:green" class="child">
<p>child3</p>
</div>
<div id="child4" style="background-color:yellow" class="child">
<p>child4</p>
</div>
</div>
1Layout Animation FLIP Technique
2Animating Layouts with the FLIP Technique
3FLIP Your Animations
4Animating the Unanimatable
Answered By - Wongjn
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.