代码之家  ›  专栏  ›  技术社区  ›  a--m

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

  •  1
  • a--m  · 技术社区  · 5 年前

    我在试着创造一个水平视差。有两个要素: 名单 内容多变,而且 背景 与列表宽度相同的。视差提供了背景在列表后面移动的深度感。

    下面是一段代码,请检查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 回复  |  直到 5 年前
        1
  •  0
  •   vals    5 年前

    你的问题是这两个元素(透视图和转换图)有不同的大小。

    所以默认的起源是 中心 ,不匹配。

    将透视原点和变换原点设置为相同的值(任意一个,或多或少居中),它们将匹配:

    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>
    推荐文章