【问题标题】:How do I remove the bounce effect when translating away from the screen with css transition?使用 css 过渡从屏幕平移时如何消除反弹效果?
【发布时间】:2020-09-17 12:49:15
【问题描述】:

如果没有视觉示例,很难用语言解释我在寻找什么,所以这是基本概念: https://codepen.io/jwiggiff/full/xxwvVbr

var cube = $('.cube');
var wrapper = $('.wrapper');

$(document).mousemove((e) => {
  if(!cube.hasClass('locked')) {
    var deltaX = e.pageX - (wrapper.offset().left+(wrapper.width()/2));
    var deltaY = e.pageY - (wrapper.offset().top+(wrapper.height()/2));
    var rotateY = deltaX/($(document).width()/2) * 90;
    var rotateX = deltaY/(($(document).height()/2)) * -90;
    cube.css("transform", " rotateY("+rotateY+"deg) rotateX("+rotateX+"deg)");
  }
});

$('.top-label').click((e) => {
  cube.toggleClass('locked locked-bottom');
  $('.labels div:not(.top-label)').fadeToggle();
});
$('.bottom-label').click((e) => {
  cube.toggleClass('locked locked-top');
  $('.labels div:not(.bottom-label)').fadeToggle();
});
$('.left-label').click((e) => {
  cube.toggleClass('locked locked-right');
  $('.labels div:not(.left-label)').fadeToggle();
});
$('.right-label').click((e) => {
  cube.toggleClass('locked locked-left');
  $('.labels div:not(.right-label)').fadeToggle();
});
/* Variables */
:root {
  --cube-scale: 60vh;
}


/* Styles */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: "Montserrat", sans-serif;
  overflow: hidden;
}

.cube div {
  padding: 10vh;
  border: 5px solid blue;
  transition: all 500ms ease-in-out;
}

.cube div h1 {
  font-family: "Carter One", cursive;
}

.cube div p {
  font-size: 14px;
}


/* Labels */
.labels {
  color: black;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.labels div {
  transition: all 500ms ease-in-out;
}

.left-label {
  position: absolute;
  top: 50%;
  left: 0;
  transform: translate(0, -50%);
  padding: 20px 10px;
}

.right-label {
  position: absolute;
  top: 50%;
  right: 0;
  transform: translate(0, -50%);
  padding: 20px 10px;
}

.top-label {
  position: absolute;
  top: 0;
  left: 50%;
  width: 100%;
  text-align: center;
  transform: translate(-50%, 0);
  padding: 10px 20px;
}

.bottom-label {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 100%;
  text-align: center;
  transform: translate(-50%, 0);
  padding: 10px 20px;
}


/* 3D Cube */
.wrapper {
  width: var(--cube-scale);
  height: var(--cube-scale);
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  perspective: calc(var(--cube-scale)*4);
}

.cube {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
}

.cube.locked.locked-bottom {
  transition: all 500ms ease-in-out;
  transform: rotateX(90deg) translateY(calc(var(--cube-scale) / -2)) !important;
}
.locked-bottom .bottom {
  height: 100vh;
  width: 100vw;
  transform: rotateX(-90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
}

.cube.locked.locked-top {
  transition: all 500ms ease-in-out;
  transform: rotateX(-90deg) translateY(calc(var(--cube-scale) / 2)) !important;
}
.locked-top .top {
  height: 100vh;
  width: 100vw;
  transform: rotateX(90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
}

.cube.locked.locked-right {
  transition: all 500ms ease-in-out;
  transform: rotateY(-90deg) translateX(calc(var(--cube-scale) / -2)) !important;
}
.locked-right .right {
  height: 100vh;
  width: 100vw;
  transform: rotateY(90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
}

.cube.locked.locked-left {
  transition: all 500ms ease-in-out;
  transform: rotateY(90deg) translateX(calc(var(--cube-scale) / 2)) !important;
}
.locked-left .left {
  height: 100vh;
  width: 100vw;
  transform: rotateY(-90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
}

.cube div {
  transform-origin: calc(var(--cube-scale)/2) calc(var(--cube-scale)/2);
	position: absolute;
	width: var(--cube-scale);
	height: var(--cube-scale);
}

.front {
  background: rgba(255,0,0,0.7);
  transform: rotateY(0deg) translateZ(calc(var(--cube-scale) / 2));
}

.right {
  background-color: rgba(0,255,0,0.7);
  transform: rotateY(90deg) translateZ(calc(var(--cube-scale) / 2));
}

.back {
  background-color: rgba(0,0,255,0.7);
  transform: rotateY(180deg) translateZ(calc(var(--cube-scale) / 2));
}

.left {
  background-color: rgba(255,165,0,0.7);
  transform: rotateY(-90deg) translateZ(calc(var(--cube-scale) / 2));
}

.top {
  background-color: rgba(128,0,128,0.7);
  transform: rotateX(90deg) translateZ(calc(var(--cube-scale) / 2));
}

.bottom {
  background-color: rgba(255,0,255,0.7);
  transform: rotateX(-90deg) translateZ(calc(var(--cube-scale) / 2));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
  <div class="cube">
    <div class="front"></div>
    <div class="back"></div>
    <div class="left"></div>
    <div class="right"></div>
    <div class="top"></div>
    <div class="bottom"></div>
  </div>
</div>
<div class="labels">
  <div class="left-label"><span>Right</span></div>
  <div class="right-label"><span>Left</span></div>
  <div class="top-label"><span>Bottom</span></div>
  <div class="bottom-label"><span>Top</span></div>
</div>

在 codepen 中,如果您单击屏幕边缘的文本,它会移动当前面以覆盖整个窗口。当您单击左侧或右侧文本时,它具有预期的结果。但是,如果您单击顶部或底部的文本,您会看到立方体在远离屏幕平移时有一点弧度,而左/右的则没有。任何关于导致此反弹/弧线的原因以及如何解决它的想法都将不胜感激!

【问题讨论】:

    标签: javascript html css css-transitions css-transforms


    【解决方案1】:

    rotateY(0) 添加到.cube.locked.locked-bottom.cube.locked.locked-top 以避免此问题。

    这有点棘手,但这是因为您正在使用rotateY(a) rotateX(b) 应用动态转换,这不会以相同的方式转换到rotateX() translateZ()rotateY() translateZ()。如果您使rotateX() translateZ() 等于rotateY(0) rotateX() translateZ(),您将有相同的转换:

    var cube = $('.cube');
    var wrapper = $('.wrapper');
    
    $(document).mousemove((e) => {
      if(!cube.hasClass('locked')) {
        var deltaX = e.pageX - (wrapper.offset().left+(wrapper.width()/2));
        var deltaY = e.pageY - (wrapper.offset().top+(wrapper.height()/2));
        var rotateY = deltaX/($(document).width()/2) * 90;
        var rotateX = deltaY/(($(document).height()/2)) * -90;
        cube.css("transform", " rotateY("+rotateY+"deg) rotateX("+rotateX+"deg)");
      }
    });
    
    $('.top-label').click((e) => {
      cube.toggleClass('locked locked-bottom');
      $('.labels div:not(.top-label)').fadeToggle();
    });
    $('.bottom-label').click((e) => {
      cube.toggleClass('locked locked-top');
      $('.labels div:not(.bottom-label)').fadeToggle();
    });
    $('.left-label').click((e) => {
      cube.toggleClass('locked locked-right');
      $('.labels div:not(.left-label)').fadeToggle();
    });
    $('.right-label').click((e) => {
      cube.toggleClass('locked locked-left');
      $('.labels div:not(.right-label)').fadeToggle();
    });
    /* Variables */
    :root {
      --cube-scale: 60vh;
    }
    
    
    /* Styles */
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    body {
      font-family: "Montserrat", sans-serif;
      overflow: hidden;
    }
    
    .cube div {
      padding: 10vh;
      border: 5px solid blue;
      transition: all 500ms ease-in-out;
    }
    
    .cube div h1 {
      font-family: "Carter One", cursive;
    }
    
    .cube div p {
      font-size: 14px;
    }
    
    
    /* Labels */
    .labels {
      color: black;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    .labels div {
      transition: all 500ms ease-in-out;
    }
    
    .left-label {
      position: absolute;
      top: 50%;
      left: 0;
      transform: translate(0, -50%);
      padding: 20px 10px;
    }
    
    .right-label {
      position: absolute;
      top: 50%;
      right: 0;
      transform: translate(0, -50%);
      padding: 20px 10px;
    }
    
    .top-label {
      position: absolute;
      top: 0;
      left: 50%;
      width: 100%;
      text-align: center;
      transform: translate(-50%, 0);
      padding: 10px 20px;
    }
    
    .bottom-label {
      position: absolute;
      bottom: 0;
      left: 50%;
      width: 100%;
      text-align: center;
      transform: translate(-50%, 0);
      padding: 10px 20px;
    }
    
    
    /* 3D Cube */
    .wrapper {
      width: var(--cube-scale);
      height: var(--cube-scale);
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      perspective: calc(var(--cube-scale)*4);
    }
    
    .cube {
      width: 100%;
      height: 100%;
      position: relative;
      transform-style: preserve-3d;
    }
    
    /*here*/
    .cube.locked.locked-bottom {
      transition: all 500ms ease-in-out;
      transform:rotateY(0) rotateX(90deg) translateY(calc(var(--cube-scale) / -2)) !important;
    }
    .locked-bottom .bottom {
      height: 100vh;
      width: 100vw;
      transform: rotateX(-90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
    }
    
    /* here */
    .cube.locked.locked-top {
      transition: all 500ms ease-in-out;
      transform:rotateY(0) rotateX(-90deg) translateY(calc(var(--cube-scale) / 2)) !important;
    }
    .locked-top .top {
      height: 100vh;
      width: 100vw;
      transform:rotateY(0) rotateX(90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
    }
    
    .cube.locked.locked-right {
      transition: all 500ms ease-in-out;
      transform: rotateY(-90deg) translateX(calc(var(--cube-scale) / -2)) !important;
    }
    .locked-right .right {
      height: 100vh;
      width: 100vw;
      transform: rotateY(90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
    }
    
    .cube.locked.locked-left {
      transition: all 500ms ease-in-out;
      transform: rotateY(90deg) translateX(calc(var(--cube-scale) / 2)) !important;
    }
    .locked-left .left {
      height: 100vh;
      width: 100vw;
      transform: rotateY(-90deg) translateZ(calc(var(--cube-scale) / 2)) translate(calc(((100vw/2) - (var(--cube-scale)/2)) * -1), calc(((100vh/2) - (var(--cube-scale)/2)) * -1));
    }
    
    .cube div {
      transform-origin: calc(var(--cube-scale)/2) calc(var(--cube-scale)/2);
    	position: absolute;
    	width: var(--cube-scale);
    	height: var(--cube-scale);
    }
    
    .front {
      background: rgba(255,0,0,0.7);
      transform: rotateY(0deg) translateZ(calc(var(--cube-scale) / 2));
    }
    
    .right {
      background-color: rgba(0,255,0,0.7);
      transform: rotateY(90deg) translateZ(calc(var(--cube-scale) / 2));
    }
    
    .back {
      background-color: rgba(0,0,255,0.7);
      transform: rotateY(180deg) translateZ(calc(var(--cube-scale) / 2));
    }
    
    .left {
      background-color: rgba(255,165,0,0.7);
      transform: rotateY(-90deg) translateZ(calc(var(--cube-scale) / 2));
    }
    
    .top {
      background-color: rgba(128,0,128,0.7);
      transform:  rotateX(90deg) translateZ(calc(var(--cube-scale) / 2));
    }
    
    .bottom {
      background-color: rgba(255,0,255,0.7);
      transform: rotateX(-90deg) translateZ(calc(var(--cube-scale) / 2));
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="wrapper">
      <div class="cube">
        <div class="front"></div>
        <div class="back"></div>
        <div class="left"></div>
        <div class="right"></div>
        <div class="top"></div>
        <div class="bottom"></div>
      </div>
    </div>
    <div class="labels">
      <div class="left-label"><span>Right</span></div>
      <div class="right-label"><span>Left</span></div>
      <div class="top-label"><span>Bottom</span></div>
      <div class="bottom-label"><span>Top</span></div>
    </div>

    获取更多关于如何在transform 之间进行插值的相关问题:Weird behavior when rotating an element on hover

    【讨论】:

    • 你,我的朋友,绝对是个传奇!谢谢一百万!
    猜你喜欢
    • 2020-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 2016-12-14
    • 2019-03-26
    • 1970-01-01
    相关资源
    最近更新 更多