CSS 变换透视错误行为

CSS transform perspective wrong behavoir

我一直在试验一些 css 悬停效果。 当我尝试应用 transform: perspective() 时,它表现得很奇怪。 当我将光标指向图像的左上角时,图像的透视发生了巨大的变化。

这是我面临的问题 https://imgur.com/dXswIj6

const mouse = document.querySelector(".cursor");

window.addEventListener("mousemove", e => {
  mouse.style.transform = `translate(${e.clientX -
    (mouse.clientWidth / 2 + 2)}px, ${e.clientY -
    (mouse.clientHeight / 2 + 2)}px)`;

  // console.log(e);

  if (e.target.nodeName == "A") {
    mouse.classList = "cursor active";
  } else {
    mouse.classList = "cursor";
  }
});
body {
  background-color: #090a0c;
  color: #eee;
}
.cursor {
  width: 48px;
  height: 48px;
  border: 1px solid #222;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
  transition: 0.3s all ease-out;
  z-index: -1;
  touch-action: none;
}
.cursor .cursor-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: red;
}
.cursor.active {
  background-color: #111;
  transform: scale(1.5);
  transition: 0.3s all ease-out;
}
#feautured-work {
  padding: 36px 0;
}
.item {
  overflow: hidden;
  transition: 0.6s all ease;
}
.item .item-img img {
  width: 100%;
  transition: 1s all ease-out;
}
.item:hover {
  transform: perspective(8rem) rotateY(-2deg);
}
.item:hover .item-img img {
  transform: scale(1.05);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <h1>Hi kids</h1>
  <a href="#">Anchor</a>
  <div class="cursor">
    <div class="cursor-dot"></div>
  </div>
  <div id="app">
    <div id="feautured-work">
      <div class="container">
        <div class="row">
          <div class="col-sm-6" data-rellax-speed=>
            <div class="item">
              <div class="item-img">
                <img src="https://images.unsplash.com/photo-1574237237524-cf9468af5d5c?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
              </div>
              <div class="item-desc"></div>
            </div>
          </div>
          <div class="col-sm-6">
            <div class="item">
              <div class="item-img">
                <img src="https://images.unsplash.com/photo-1575043635751-f8cf3ffb9471?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
              </div>
              <div class="item-desc"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

是什么导致转换 属性 工作不正常?

问题出在您为变换设置动画的方式上。这里:

.item {
  overflow: hidden;
  transition: 0.6s all ease;
  //no transform property by default, so by default perspective - 0rem
}

.item:hover {
  transform: perspective(8rem) rotateY(-2deg); //animating both perspective and rotate
}

您已经告诉 .item 您想要在 hover 旋转部分和透视部分上制作所有变换 属性 的动画。动画透视会导致此类问题。

因此您可以使用预定义的视角简单地定义项目的默认状态:

.item {
  overflow: hidden;
  transform: perspective(8rem) rotateY(0);
  transition: 0.6s transform ease;
}

.item:hover {
  transform: perspective(8rem) rotateY(-2deg); //now only rotate part will be animate
}

const mouse = document.querySelector(".cursor");

window.addEventListener("mousemove", e => {
  mouse.style.transform = `translate(${e.clientX -
    (mouse.clientWidth / 2 + 2)}px, ${e.clientY -
    (mouse.clientHeight / 2 + 2)}px)`;

  // console.log(e);

  if (e.target.nodeName == "A") {
    mouse.classList = "cursor active";
  } else {
    mouse.classList = "cursor";
  }
});
body {
  background-color: #090a0c;
  color: #eee;
}

.cursor {
  width: 48px;
  height: 48px;
  border: 1px solid #222;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  top: 0;
  left: 0;
  transition: 0.3s all ease-out;
  z-index: -1;
  touch-action: none;
}

.cursor .cursor-dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: red;
}

.cursor.active {
  background-color: #111;
  transform: scale(1.5);
  transition: 0.3s all ease-out;
}

#feautured-work {
  padding: 36px 0;
}

.item {
  overflow: hidden;
  transform: perspective(8rem) rotateY(0);
  transition: 0.6s transform ease;
}

.item .item-img img {
  width: 100%;
  transition: 1s all ease-out;
}

.item:hover {
  transform: perspective(8rem) rotateY(-2deg);
}

.item:hover .item-img img {
  transform: scale(1.05);
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
  <h1>Hi kids</h1>
  <a href="#">Anchor</a>
  <div class="cursor">
    <div class="cursor-dot"></div>
  </div>
  <div id="app">
    <div id="feautured-work">
      <div class="container">
        <div class="row">
          <div class="col-sm-6" data-rellax-speed=>
            <div class="item">
              <div class="item-img">
                <img src="https://images.unsplash.com/photo-1574237237524-cf9468af5d5c?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
              </div>
              <div class="item-desc"></div>
            </div>
          </div>
          <div class="col-sm-6">
            <div class="item">
              <div class="item-img">
                <img src="https://images.unsplash.com/photo-1575043635751-f8cf3ffb9471?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ" alt="">
              </div>
              <div class="item-desc"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>