变换后的元素宽度和位置(translateZ和scale)

问题描述 投票:1回答:1

我正在尝试创建一个水平视差。有两个元素:具有可变内容的列表,以及与列表具有相同宽度的背景。视差给出了背景在列表后面移动的深度感。

这是一个代码段,请检查CSS注释作为后续跟踪:

document.querySelector('#transform').onchange = () => {
  document.querySelector('.background').classList.toggle('background--transformed')
}
/*
its scrolls content and sets the value for the perspective 
to enable the parallax effect
*/
.parallax {
  perspective: 1px;
  transform-style: preserve-3d;
  overflow-y: hidden;
  overflow-x: scroll;
}

/*
wrapper element for both list and background
used to make the background match the size of the list,
as the list grows it will expand the container and the
background will follow.
*/
.content {
  position: relative;
  display: inline-block;
}

/*
horizontal list
*/
.list {
  display: inline-flex;
}

.list-item {
  width: 20vw;
  height: 80vh;
  margin: 10vh 0;
  background-color: red;
  opacity: 0.9;
}

.list-item+.list-item {
  margin-left: 1vw;
}

/*
background element that fill the entire width of it's parent
*/
.background {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background-color: black;
  height: 100vh;
  z-index: -1;
  background: url(https://images.unsplash.com/photo-1499242165110-131f6ccd0c9a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80);
  background-size: auto 100%;
}

/*
translates the element back into space, and scales it to the double 
to match the original size. And this is what fails!
*/
.background--transformed {
  transform: translateZ(-1px) scale(2);
}

.option {
  position: fixed;
  top: 0;
  left: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />

<div class="parallax">
  <div class="content">
    <ul class="list">
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
    </ul>
    <div class="background"></div>
  </div>
</div>

<div class="option">
  <input type="checkbox" id="transform" name="transform">
  <label for="transform">transform</label>
</div>

请注意,当启用translate时(勾选左上角的复选框),背景大小会比列表大(向右滚动以查看)。

理论上,根据为透视设置的值,缩放到double应该“重置”大小。但我肯定在这里遗漏了一些东西......

html css css3
1个回答
0
投票

您的问题是2个元素(具有透视的元素和具有变换的元素)具有不同的大小。

因此,默认的起点是中心,不匹配。

将perspective-origin和transform-origin设置为相同的值(并且对一个,或多或少的居中进行仲裁),它们将匹配:

document.querySelector('#transform').onchange = () => {
  document.querySelector('.background').classList.toggle('background--transformed')
}
/*
its scrolls content and sets the value for the perspective 
to enable the parallax effect
*/
.parallax {
  perspective: 1px;
  transform-style: preserve-3d;
  overflow-y: hidden;
  overflow-x: scroll;
  perspective-origin: 300px 220px;
}

/*
wrapper element for both list and background
used to make the background match the size of the list,
as the list grows it will expand the container and the
background will follow.
*/
.content {
  position: relative;
  display: inline-block;
}

/*
horizontal list
*/
.list {
  display: inline-flex;
}

.list-item {
  width: 20vw;
  height: 80vh;
  margin: 10vh 0;
  background-color: red;
  opacity: 0.9;
}

.list-item+.list-item {
  margin-left: 1vw;
}

/*
background element that fill the entire width of it's parent
*/
.background {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  background-color: black;
  height: 100vh;
  z-index: -1;
  background: url(https://images.unsplash.com/photo-1499242165110-131f6ccd0c9a?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1500&q=80);
  background-size: auto 100%;
}

/*
translates the element back into space, and scales it to the double 
to match the original size. And this is what fails!
*/
.background--transformed {
  transform: translateZ(-1px) scale(2);
  transform-origin: 300px 220px;

}

.option {
  position: fixed;
  top: 0;
  left: 0;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css" rel="stylesheet" />

<div class="parallax">
  <div class="content">
    <ul class="list">
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
      <li class="list-item"></li>
    </ul>
    <div class="background"></div>
  </div>
</div>

<div class="option">
  <input type="checkbox" id="transform" name="transform">
  <label for="transform">transform</label>
</div>
© www.soinside.com 2019 - 2024. All rights reserved.