简体   繁体   English

如何在不使用变换或上/左的情况下转换列表中项目的位置

[英]How is it possible to transition the position of items in a list without using transform or top/left

The other day I stumbled onto an example that uses Vue.js, but my question is more about the CSS and HTML that Vue uses to achieve the transition between states.前几天我偶然发现了一个使用 Vue.js的示例,但我的问题更多是关于 Vue 用于实现状态之间转换的 CSS 和 HTML。

The cards temporarily get the class .shuffleMedium-move which adds a transition: transform 1s and the order of the nodes change in the DOM, but I don't understand why the transition occurs since the transform property never seems to get set and the items are positioned simply using float:left .卡片暂时获得了.shuffleMedium-move类,它添加了一个transition: transform 1s并且节点的顺序在 DOM 中发生了变化,但我不明白为什么会发生转换,因为transform属性似乎永远不会被设置并且项目只需使用float:left即可定位。

I've been doing CSS for quite a while and I've always had to resort to using a combination of JavaScript position: absolute and transform to achieve a similar result.我做 CSS 已经有一段时间了,我总是不得不使用 JavaScript position: absolutetransform的组合来获得类似的结果。 Vue's solution seems really elegant, but I don't understand how it works. Vue 的解决方案看起来很优雅,但我不明白它是如何工作的。

From the documentation on list transition来自关于列表转换的文档

This might seem like magic, but under the hood, Vue is using an animation technique called FLIP to smoothly transition elements from their old position to their new position using transforms.这可能看起来很神奇,但在底层,Vue 使用了一种称为FLIP的动画技术,使用变换将元素从旧位置平滑过渡到新位置。

From the FLIP article来自FLIP 文章

FLIP stands for F irst, L ast, I nvert, P lay. FLIP代表 First、Last、 I nvert Play

Let's break it down:让我们分解一下:

  • First: the initial state of the element(s) involved in the transition.第一:转换中涉及的元素的初始状态。
  • Last: the final state of the element(s).最后:元素的最终状态。
  • Invert: here's the fun bit.反转:这是有趣的一点。 You figure out from the first and last how the element has changed, so – say – its width, height, opacity.你从第一个和最后一个元素中找出了元素是如何变化的,所以——比如说——它的宽度、高度、不透明度。 Next you apply transforms and opacity changes to reverse, or invert, them.接下来,您应用变换和不透明度更改来反转或反转它们。 If the element has moved 90px down between First and Last, you would apply a transform of -90px in Y. This makes the elements appear as though they're still in the First position but, crucially, they're not.如果元素在 First 和 Last 之间向下移动了 90px,您将在 Y 中应用 -90px 的变换。这使元素看起来好像它们仍然在 First 位置,但至关重要的是,它们不是。
  • Play: switch on transitions for any of the properties you changed, and then remove the inversion changes.播放:为您更改的任何属性打开过渡,然后删除反转更改。 Because the element or elements are in their final position removing the transforms and opacities will ease them from their faux First position, out to the Last position.因为一个或多个元素处于它们的最终位置,所以移除变换和不透明度将使它们从虚假的 First 位置缓和到 Last 位置。

Step by step example一步一步的例子

That way, we can inspect changes at each step of the animation process.这样,我们可以在动画过程的每一步检查变化。

When it's playing in real time, the transform is really quickly added inline and it's then removed immediately, so it looks like it's never set.当它实时播放时, transform很快就会被内联添加,然后立即删除,所以看起来它从未设置过。

 const el = document.getElementById('target'); const data = {}; function first() { data.first = el.getBoundingClientRect(); console.log('First: get initial position', data.first.left, 'px'); } function last() { el.classList.toggle('last'); data.last = el.getBoundingClientRect(); console.log('Last: get new position', data.last.left, 'px'); } function invert() { el.style.transform = `translateX(${data.first.left - data.last.left}px)`; console.log('Invert: applies a transform to place the item where it was.'); } function play() { requestAnimationFrame(() => { el.classList.add('animate'); el.style.transform = ''; }); console.log('Play: adds the transition class and removes the transform.'); } function end() { el.classList.remove('animate'); console.log('End: removes the transition class.'); } const steps = [first, last, invert, play, end]; let step = 0; function nextStep() { steps[step++ % steps.length](); } document.getElementById('next').addEventListener('click', nextStep);
 .last { margin-left: 35px; } .animate { transition: transform 1s; } #target { display: inline-block; padding: 5px; border: 1px solid #aaa; background-color: #6c6; } #next { margin-top: 5px; }
 <div id="target">target</div> <br> <button id="next" type="button">Next</button>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM