有没有一种方法可以在不定义任何属性的情况下使用CSS transition?

gjmwrych  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(154)

我有一个JavaScript函数可以在父div中移动不同的子元素,但我想添加一个过渡,使元素移动到它们在div中的新位置,而不是立即改变位置。
至于我使用的过渡,对我来说,它只适用于定义的属性,如top/bottomheight/width。在这种情况下,我没有定义任何属性,所以我想知道过渡效果是否仍然可能。
在这里,你可以看到我设置的子元素和父元素,以及移动子元素的函数:

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)
});

个字符
由于我所有的尝试,使一个工作过渡失败,我只留下了切换功能,所以他们立即交换位置。
我尝试使用transition-duration,但由于没有定义CSS属性,所以预期什么也没有发生。
提前感谢!
请不要使用jQuery,因为我从来没有使用过它,所以如果可能的话,我会喜欢香草JavaScript:)

xuo3flqw

xuo3flqw1#

正如注解所建议的,CSS转换发生在CSS属性更改时,因此某些CSS属性必须更改才能发生转换。对于顺序或DOM元素的动画更改,您可以考虑使用 First,Last,Invert,Play(FLIP)技术1234,其中:
1.First:获取元素的初始位置。
1.最后一个:使元素到达其结束状态。
1.反转:使用前面步骤中的信息,将位置更改反转回更改发生前的元素外观。
1.播放:移除反转,但带有过渡,以便元素从反转动画返回到新位置。

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)
});

个字符
1 Layout Animation FLIP Technique
2 Animating Layouts with the FLIP Technique
3 FLIP Your Animations
4 Animating the Unanimatable

ijxebb2r

ijxebb2r2#

用动画重新排列兄弟元素

  • 存储所有需要移动的元素的当前boundingClientRect(基本上包括从minIndex到maxIndex的所有元素)
  • 将元素移动到新的DOM位置索引中(在同一个父元素中),注意:如果索引与可用的总索引匹配,则必须通过传递null作为第二个参数ParentElement.insertBefore(elToInsert, null)或使用ParentElement.append(elToInsert)来 * 追加**移动元素。
  • 使用Animation APItranslate从起始boundingClientRect(重排之前)到当前boundingClientRect(0px left and top)的元素:
const moveElement = (elA, iB) => {
  const par = elA.parentElement
  const ch = [...par.children];
  const elB = ch[iB];
  const iA = ch.indexOf(elA);
  const iTot = ch.length - 1;
  const iMin = Math.min(iA, iB, 0);
  const iMax = Math.max(iA, iB, iTot);
  const chMove = ch.slice(iMin, iMax + 1);
  const bcr = chMove.map(el => el.getBoundingClientRect());

  // Rearrange
  par.insertBefore(elA, iB === iTot ? null : elB); 
  
  // Animate elements
  chMove.forEach((el, i) => { 
    const {left: xA, top: yA} = bcr[i];
    const {left: xB, top: yB} = el.getBoundingClientRect();
    el.animate([
      { translate: `${xA - xB}px ${yA - yB}px`},
      { translate: "0px 0px" },
    ], { duration: 280 });
  });
};

const par = document.querySelector("#parent");
par.addEventListener("click", () => {
  const elA = par.children[2];
  moveElement(elA, 0);
});

个字符

相关问题