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

Posted

技术标签:

【中文标题】如何在不使用变换或上/左的情况下转换列表中项目的位置【英文标题】:How is it possible to transition the position of items in a list without using transform or top/left 【发布时间】:2018-09-27 15:33:49 【问题描述】:

前几天我偶然发现了使用 Vue.js 的 an example,但我的问题更多是关于 Vue 用于实现状态之间转换的 CSS 和 html

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

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

【问题讨论】:

动画是通过类完成的,而您在检查时看不到这些类,因为它们会立即添加/删除。但是,如果你在 shuffle 函数中添加 debugger 行,在 vue(...) 行之后并检查 dom,你会看到其他类。您必须先检查卡然后运行代码,如果您运行代码并开始调试,您可能无法检查 hmm 我没有看到除了 shuffleMedium-move 之外添加的任何其他类,它只添加了 transition: transform 1s 我希望还会看到类似:shuffleMedium-startshuffleMedium-end 或添加内联样式,但是 vuejs 似乎并没有做任何事情。 transform 确实很快被内联添加,然后立即删除。 @duprasa 这些类被添加然后删除,你不会在检查器中看到它们。我测试了 25 秒的转换时间,当我在调试器中设置断点时,我能够看到类 【参考方案1】:

来自documentation on list transition

这可能看起来很神奇,但实际上,Vue 使用了一种名为 FLIP 的动画技术,通过变换将元素从旧位置平滑过渡到新位置。

来自FLIP article

FLIP 代表 First、Last、Invert、P躺着。

让我们分解一下:

First:过渡中涉及的元素的初始状态。 Last:元素的最终状态。 反转:这是有趣的部分。你从第一个和最后一个元素中找出了元素是如何变化的,所以——比如说——它的宽度、高度、 不透明度。接下来,您应用变换和不透明度更改来反转,或者 倒置,他们。如果元素在 First 和 最后,您将在 Y 中应用 -90px 的变换。这使得 元素看起来好像它们仍然在第一个位置但是, 至关重要的是,它们不是。 播放:为您更改的任何属性打开过渡,然后移除反转更改。因为元素或 元素处于其最终位置,移除变换和 不透明度将使它们从虚假的第一位置缓解到 最后一个位置。

分步示例

这样,我们可以检查动画过程每一步的变化。

在实时播放时,transform 会很快被内联添加,然后立即删除,所以看起来它从未设置过。

var $el = $('.target');
var el = $el.get(0);
var data = ;

function first() 
  data.first = el.getBoundingClientRect();
  console.log('First: get initial position', data.first.left, 'px');


function last() 
  $el.toggleClass('last');
  data.last = el.getBoundingClientRect();
  console.log('Last: get new position', data.last.left, 'px');


function invert() 
  var invert = data.first.left - data.last.left;
  el.style.transform = `translateX($invertpx)`;
  console.log('Invert: applies a transform to place the item where it was.');


function play() 
  requestAnimationFrame(function() 
    $el.addClass('animate');
    el.style.transform = '';
  );
  console.log('Play: adds the transition class and removes the transform.');


function end() 
  $el.removeClass('animate');
  console.log('End: removes the transition class.');



var steps = [first, last, invert, play, end];

var step = 0;

function nextStep() 
  steps[step++ % steps.length]();


$('button').click(nextStep);
.last 
  margin-left: 35px;


.animate 
  transition: transform 1s;


.target 
  display: inline-block;
  padding: 5px;
  border: 1px solid #aaa;
  background-color: #6c6;
<div class="target">target</div>
<br>
<button type="button">Next</button>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【讨论】:

感谢您的详细回答:)。我将对此进行大量实验,我仍然很惊讶 chrome 没有显示内联 transform,即使它几乎是瞬时的。

以上是关于如何在不使用变换或上/左的情况下转换列表中项目的位置的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 foreach 的情况下将 ArrayList 转换为强类型泛型列表?

在不使用 opencv 的情况下在 python 中应用 Homography 变换

如何在不强制转换为数字的情况下迭代日期列表?

如何在不使用 for 循环的情况下将列表中的所有项目与整数进行比较

如何在不使用任何图像项目符号或任何跨度标签的情况下通过 CSS 定义 OL/LI 列表中字符的颜色?

如何在不指定集群数量的情况下对列表中的项目进行集群