Как убрать эффект отскока при переводе от экрана с переходом css? - PullRequest
6 голосов
/ 30 мая 2020

Трудно объяснить словами, что я ищу, без наглядного примера, поэтому вот основная c идея: 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>

В кодовом поле, если вы щелкните текст на краю экрана, текущая грань переместится, чтобы покрыть все окно. Когда вы нажимаете левый или правый текст, он дает ожидаемый результат. Однако, если вы щелкните верхний или нижний текст, вы увидите, что куб имеет немного ar c при перемещении от экрана, тогда как левый / правый - нет. Мы будем очень признательны за любые идеи относительно того, что вызывает этот отскок / ar c и как его исправить!

1 Ответ

5 голосов
/ 30 мая 2020

Добавьте rotateY(0) к .cube.locked.locked-bottom и .cube.locked.locked-top, чтобы избежать этой проблемы.

Это немного сложно, но это связано с тем, что вы применяете динамическое преобразование c с использованием 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: Странное поведение при повороте элемента при наведении

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...