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



前几天我偶然发现了一个使用 Vue.js 的例子,但我的问题更多的是关于 Vue 用来实现状态之间转换的 CSS 和 HTML。

卡片暂时获得类.shuffleMedium-move,它增加了一个transition: transform 1s并且节点的顺序在 DOM 中发生了变化,但我不明白为什么会发生过渡,因为transform属性似乎从未被设置并且项目只是使用float:left定位。

我做CSS已经有一段时间了,我总是不得不使用JavaScriptposition: absolutetransform的组合来实现类似的结果。Vue 的解决方案看起来真的很优雅,但我不明白它是如何工作的。

来自有关列表转换的文档

这可能看起来像是魔术,但在幕后,Vue 正在使用一种名为 FLIP 的动画技术,使用变换将元素从旧位置平滑地过渡到新位置。

来自翻转文章

FLIP代表First,Last,Invert,Play。

让我们分解一下:

  • 首先:过渡中涉及的元素的初始状态。
  • 最后:元素的最终状态。
  • 反转:这是有趣的一点。你从第一个和最后一个弄清楚元素是如何变化的,所以——比如说——它的宽度、高度、 不透明度。接下来,应用变换和不透明度更改来反转,或 反转,他们。如果元素在"第一个"和"之间向下移动了 90px" 最后,您将在 Y 中应用 -90px 的变换。这使得 元素看起来好像它们仍然处于第一个位置,但是, 至关重要的是,他们不是。
  • 播放:打开您更改的任何属性的过渡,然后删除反转更改。因为元素或 元素处于其最终位置,删除转换和 不透明将使他们从虚假的第一位置轻松到 最后一个位置。

分步示例

这样,我们就可以检查动画过程的每一步的更改。

当它实时播放时,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>

最新更新