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

5
我有一个元素,其CSS属性设置为position: fixed;在页面的右上角。
当单击该元素时,我想将其“扩大和移动”到屏幕中心。
我所知道的在页面中心定位一个元素的最佳解决方案是:
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

如何消除动画在水平中心的初始跳跃?(即,我希望反转“缩小到右上角”的效果,在那里一切正常)。


2
当使用 right 时,您可以使用 top: 50%; right: 50%; transform: translate(50%, -50%); 吗? - kukkuz
2
请返回翻译的文本。 - kukkuz
1
这个 &§***,我发誓我尝试了每一种变化;-) 不过还是谢谢! - TommyF
2个回答

3

你只需要在 foo 状态上将右边改为左边。
这也意味着你需要将 translate 属性更改为:translate(50%,-50%);,因为 translateX 的值应该是从左到右而不是居中元素:

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>

这会改变动画轨迹,并通过 transform 属性防止元素在上/右方向上同时动画,以及在另一个方向上进行动画。


0

我承认,一开始这给了我一些麻烦,但是通过一些毅力,我成功了哈哈

这是因为你没有为CSS转换指定一个起始点,以关联right属性的定位。你已经从给元素一个right属性的20px转变为left属性的50%。对于你想要的效果,你需要给它一个起始的right位置为20px和一个终止的right位置为50%.bar(摆脱left:50%;)。

现在,在您解决了上述问题之后,您需要通过将.bar类的transform方法更改为transform: translate(50%, -50%);来解决它。这是因为我们已经切换到使用right x轴定位,所以我们需要它从右边开始50%,而不是-50%(这会使元素超出父元素中心点-50%的空间)。

这是您的新实时演示。希望这有意义 :) CSS逻辑上要求所有转换都有一个起点和一个有效的共存终点。一些浏览器会为您做出假设,但它们永远不应该这样做,因为这会阻碍跨平台开发。


@TommyF,你检查了我的答案吗? - Pie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接