将固定元素动画化到视口的中心

Animate fixed element to the center of the viewport

我在页面右上角有一个元素position: fixed;
我希望它在点击时 "grow and move" 到屏幕中央。

据我所知,将某些内容放置在页面死角的最佳解决方案是

position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

如果我将元素最初定位为 topleft 属性,则一切正常,但如果元素最初定位为 right,则动画中会出现令人讨厌的跳跃而不是 left.

const myFunc = function() {
  let f = document.getElementById('element')

  if (f.className.includes('bar')) {
    f.className = 'foo'
  } else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 500px;
  height: 500px;
  background-color: red;
  transform: translate(-50%, -50%);
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

Codepen

如何消除动画中初始跳到水平中心的问题? (即我想要 "shrinking back to top right" 的反面,这里一切正常)。

只需要在 foo 状态下将右转为左即可。
这也意味着您将翻译 属性 更改为:translate(50%,-50%); 因为 tanslateX 值应该从左到右以使元素居中:

const myFunc = function () {
  let f = document.getElementById('element')

  if(f.className.includes('bar')) {
    f.className = 'foo'
  }
  else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: 50%;
  right: 50%;
  width: 500px;
  height: 500px;
  background-color: red;
  transform: translate(50%, -50%);
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

附带说明一下,如果您知道元素在两种状态下的大小,则可以使用 calc() 仅在顶部和右侧属性上进行过渡,如下所示:

const myFunc = function() {
  let f = document.getElementById('element')

  if (f.className.includes('bar')) {
    f.className = 'foo'
  } else {
    f.className = 'foo bar'
  }
}
.wrapper {
  position: relative;
  width: 100%;
  height: 100%;
}

.foo {
  position: fixed;
  top: 20px;
  right: 20px;
  width: 200px;
  height: 50px;
  background-color: blue;
  transition: 0.5s all;
}

.bar {
  position: fixed;
  top: calc(50% - 250px);
  right: calc(50% - 250px);
  width: 500px;
  height: 500px;
  background-color: red;
  transition: 0.5s all;
}
<div class="wrapper">
  <div class="foo" id="element" onclick="myFunc()">
  </div>
</div>

这会改变动画轨迹并防止元素在一个方向上用 top/right 和另一个方向同时用 transform 属性.

我承认,一开始这给了我一些麻烦,但凭借一些毅力,我能够让你到达那里哈哈

这是因为您没有为 CSS 转换提供与 right 属性 定位关联的起点。您已将元素 right 属性 of 20px 切换为 left 属性 of 50%。对于你想要的效果,你需要给它一个20px的起始right位置和50%结束right位置对于 .bar(摆脱 left: 50%;)。

现在,在您解决上述问题后,您需要解决 .bar class transform 方法 transform: translate(50%, -50%); 这是因为我们已经切换到使用 right x-axis 定位,所以我们需要它从右边开始 50%,而不是 -50%(这会使元素从 off-screen -50% of the space from the dead center of parent).

Here is your new live demo。我希望这是有道理的 :) CSS 逻辑上要求所有转换都有一个起点和一个有效的、同居的终点。有些浏览器会为您做出假设,但它们永远不应该这样做,因为这会阻碍开发 cross-platform.