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

时间:2019-01-25 17:32:35

标签: html css css3

我正在尝试创建水平视差。有两个元素:具有可变内容的列表和具有与列表相同宽度的背景。视差使背景在列表后面移动时具有深度感。

这是一个代码段,请检查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(选中左上方的复选框)后,背景尺寸将大于列表尺寸(向右滚动以查看)。

理论上,按比例设置为双精度值应根据为透视图设置的值“重置”大小。但是我肯定在这里遗漏了一些东西...

1 个答案:

答案 0 :(得分:0)

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

因此默认的原点是 center

将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>