【问题标题】:Safari 11.0.1: 3d transform bugSafari 11.0.1:3d 变换错误
【发布时间】:2018-05-06 19:29:29
【问题描述】:

我正在开发一个带有 CSS3 3d 变换的开放立方体,它在 Chrome、Firefox 和 Opera 中运行良好。 然而,在 Safari 中,由于某种原因,立方体正在移动到一个奇怪的地方。

let isExpanded = false;
let cube = document.querySelector(".cube");

document.querySelector("#toggle").onclick = function(e) {
  e.preventDefault();
  document.querySelector("#toggle").disabled = true;
  toggle();
}

function toggle() {
  if (!isExpanded) {
    isExpanded = true;
    // Pause Rotation
    document.querySelector(".cube").classList.add("pause");
    // Open Cube
    open();
  } else {
    isExpanded = false;
    close();
  }
}

function close() {
  // Close the cube
  cube.classList.remove("open");
  cube.style.bottom = "0";
  // Rotate to the start position and restart animation
  setTimeout(function() {
    cube.classList.remove("origin-bottom");
  }, 1000); // >= side transform's transition time
  setTimeout(function() {
    cube.style.animation = "spin 15s infinite linear";
    cube.style.webkitAnimation = "spin 15s infinite linear";
    document.querySelector("#toggle").disabled = false;
  }, 1200);
}

function open() {
  // Set transform value to current position & Disable Animation
  prop = window.getComputedStyle(cube, null).getPropertyValue("transform");
  cube.style.transform = prop;
  cube.style.webkitTransform = prop;
  cube.style.MozTransform = prop;
  cube.style.msTransform = prop;
  cube.style.OTransform = prop;
  cube.style.animation = "none";
  cube.style.webkitAnimation = "none";
  // Rotate the cube to its initial position & Remove pause
  setTimeout(function() {
    cube.classList.remove("pause");
    cube.classList.add("origin-bottom");
    cube.style.transform = "rotateX(-20deg) rotateY(42deg)";
    cube.style.webkitTransform = "rotateX(-20deg) rotateY(42deg)";
    cube.style.MozTransform = "rotateX(-20deg) rotateY(42deg)";
    cube.style.msTransform = "rotateX(-20deg) rotateY(42deg)";
    cube.style.OTransform = "rotateX(-20deg) rotateY(42deg)";
  }, 50);
  // Open the cube
  setTimeout(function() {
    cube.classList.add("open");
    document.querySelector("#toggle").disabled = false;
  }, 1000); // >= side transform's transition time
}
body {background: #333;}
.cube-wrapper {
  margin: auto;
  width: 200px;
  height: 200px;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  position: absolute;
  -webkit-perspective: 600px;
  perspective: 600px;
  perspective-origin: 50% 50%;
}
.cube-wrapper .cube {
  width: 200px;
  height: 200px;
  position: relative;
  bottom: 0;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  backface-visibility: visible;
  transition: all 1s ease-in-out;
  animation: spin 15s infinite linear;
}
.cube-wrapper .cube .side {
  transition: transform 1s ease-in-out, background 0.5s ease-in-out, opacity 0.5s ease-in-out;
  outline: 1px solid rgba(250, 250, 250, 0.3);
  position: absolute;
  left: 0;
  top: 0;
  width: 200px;
  height: 200px;
  transform-origin: 50% 50%;
  -webkit-transform-origin: 50% 50%;
}
.cube-wrapper .cube .right {
  transform: rotateX(0deg) rotateY(90deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .left {
  transform: rotateX(0deg) rotateY(270deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .top {
  transform: rotateX(90deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .bottom {
  transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .front {
  transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .behind {
  transform: rotateX(0deg) rotateY(180deg) rotateZ(0deg) translateZ(100px);
}
/* pause */
.preserve3d .cube-wrapper .cube.pause, .preserve3d .cube-wrapper .cube:hover {
  -webkit-animation-play-state: paused !important;
  animation-play-state: paused !important;
}
/* open */
.preserve3d .cube-wrapper .cube.open .right {
  transform: rotateY(90deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .left {
  transform: rotateY(-90deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .front {
  transform: rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .behind {
  transform: rotateY(180deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .right {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .left {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .top {
  opacity: 0;
  pointer-events: none;
}
.preserve3d .cube-wrapper .cube.origin-bottom .front {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .behind {
  transform-origin: bottom !important;
}
/* animation */
@keyframes spin {
  from {
    transform: rotateX(-20deg) rotateY(42deg);
  }
  to {
    transform: rotateX(340deg) rotateY(382deg);
  }
}
<button id="toggle">toggle</button>
<div class="preserve3d">
  <div class="cube-wrapper">
    <div class="cube">
      <div class="side right">Right
      </div>
      <div class="side left">Left
      </div>
      <div class="side top">Top
      </div>
      <div class="side bottom">Bottom
      </div>
      <div class="side front">Front
      </div>
      <div class="side behind">Behind
      </div>
    </div>
  </div>
</div>

虽然它被移动到一个奇怪的位置,检查员说它在一个正确的位置使用 getComputedStyle 也给出了正确的值,所以我不知道如何调试这个问题。

我搜索并发现 Safari 在 rotateY 方面存在一些问题,并尝试了给定的解决方案,给出了 z-index 值,但没有奏效。

这是代码的缩短版本:https://jsfiddle.net/7mxghcq9/

提前谢谢你:)

【问题讨论】:

  • 在 safari 中旋转不要超过 179 度,显然是非常老的 bug,看这里:stackoverflow.com/questions/35186768/…
  • @KresimirPendic 这不是 11.0.1 版本中解决的旧错误吗?无论如何,我删除了 179deg 以上的所有旋转值,但仍然有同样的问题:jsfiddle.net/7mxghcq9/2
  • @KresimirPendic caniuse 没有报告 Safari 的此类问题。
  • @jyoon 您需要在这里发布您的代码,而不是 jsfiddle:minimal reproducible example
  • @Rob 谢谢,我使用的是 jsfiddle,因为代码 sn-p 似乎没有 SCSS 编译器。但是我在代码中附加了编译后的 CSS,并尽可能地清理它们。

标签: javascript html css safari


【解决方案1】:

清除历史记录并尝试重新加载页面。这也发生在我身上,清除缓存效果很好。如果它是 safari 9,您可以完全旋转。您使用的是 webkit,所以它应该很好。自己测试过,对我来说很好用

【讨论】:

  • 感谢您告诉我。但不幸的是,我清空了完整的历史记录和缓存,但对我没有用 :) 还是谢谢!
【解决方案2】:

很抱歉,我不能确定会发生什么,也不能确定 Safari 的行为是否完全错误......

无论如何,一个可行的解决方案是将cube.style.animation = 'none'; 移动到您的第一个超时内,然后在移除其暂停状态之前触发回流。

function open() {
  // Set transform value to current position
  prop = window.getComputedStyle(cube, null).getPropertyValue("transform");

  cube.style.transform = prop;
  cube.style.webkitTransform = prop;
  cube.style.MozTransform = prop;
  cube.style.msTransform = prop;
  cube.style.OTransform = prop;
  
  // Disable Animation & Rotate the cube to its initial position & Remove pause
  setTimeout(function() {
    cube.style.animation = "none";
    cube.offsetWidth; // force a reflow
    cube.classList.remove("pause");
    cube.classList.add("origin-bottom");
    cube.style.transform = "rotateX(-20deg) rotateY(42deg)";
  }, 50);
  // Open the cube
  setTimeout(function() {
    cube.classList.add("open");
    document.querySelector("#toggle").disabled = false;
  }, 1000); // >= side transform's transition time
}

let isExpanded = false;
let cube = document.querySelector(".cube");

document.querySelector("#toggle").onclick = function(e) {
  e.preventDefault();
  document.querySelector("#toggle").disabled = true;
  toggle();
}

function toggle() {
  if (!isExpanded) {
    isExpanded = true;
    // Pause Rotation
    document.querySelector(".cube").classList.add("pause");
    // Open Cube
    open();
  } else {
    isExpanded = false;
    close();
  }
}

function close() {
  // Close the cube
  cube.classList.remove("open");
  cube.style.bottom = "0";
  // Rotate to the start position and restart animation
  setTimeout(function() {
    cube.classList.remove("origin-bottom");
  }, 1000); // >= side transform's transition time
  setTimeout(function() {
    cube.style.animation = "spin 15s infinite linear";
    cube.style.webkitAnimation = "spin 15s infinite linear";
    document.querySelector("#toggle").disabled = false;
  }, 1200);
}
body {background: #333;}
.cube-wrapper {
  margin: auto;
  width: 200px;
  height: 200px;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  position: absolute;
  -webkit-perspective: 600px;
  perspective: 600px;
  perspective-origin: 50% 50%;
}
.cube-wrapper .cube {
  width: 200px;
  height: 200px;
  position: relative;
  bottom: 0;
  -webkit-transform-style: preserve-3d;
  transform-style: preserve-3d;
  backface-visibility: visible;
  transition: all 1s ease-in-out;
  animation: spin 15s infinite linear;
}
.cube-wrapper .cube .side {
  transition: transform 1s ease-in-out, background 0.5s ease-in-out, opacity 0.5s ease-in-out;
  outline: 1px solid rgba(250, 250, 250, 0.3);
  position: absolute;
  left: 0;
  top: 0;
  width: 200px;
  height: 200px;
  transform-origin: 50% 50%;
  -webkit-transform-origin: 50% 50%;
}
.cube-wrapper .cube .right {
  transform: rotateX(0deg) rotateY(90deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .left {
  transform: rotateX(0deg) rotateY(270deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .top {
  transform: rotateX(90deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .bottom {
  transform: rotateX(-90deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .front {
  transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateZ(100px);
}
.cube-wrapper .cube .behind {
  transform: rotateX(0deg) rotateY(180deg) rotateZ(0deg) translateZ(100px);
}
/* pause */
.preserve3d .cube-wrapper .cube.pause, .preserve3d .cube-wrapper .cube:hover {
  -webkit-animation-play-state: paused !important;
  animation-play-state: paused !important;
}
/* open */
.preserve3d .cube-wrapper .cube.open .right {
  transform: rotateY(90deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .left {
  transform: rotateY(-90deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .front {
  transform: rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.open .behind {
  transform: rotateY(180deg) rotateX(-90deg) translateY(-100px) !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .right {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .left {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .top {
  opacity: 0;
  pointer-events: none;
}
.preserve3d .cube-wrapper .cube.origin-bottom .front {
  transform-origin: bottom !important;
}
.preserve3d .cube-wrapper .cube.origin-bottom .behind {
  transform-origin: bottom !important;
}
.cube.origin-bottom{
  animation-fill-mode: forwards;
}
/* animation */
@keyframes spin {
  from {
    transform: rotateX(-20deg) rotateY(42deg);
  }
  to {
    transform: rotateX(340deg) rotateY(382deg);
  }
}
<button id="toggle">toggle</button>
<div class="preserve3d">
  <div class="cube-wrapper">
    <div class="cube">
      <div class="side right">Right
      </div>
      <div class="side left">Left
      </div>
      <div class="side top">Top
      </div>
      <div class="side bottom">Bottom
      </div>
      <div class="side front">Front
      </div>
      <div class="side behind">Behind
      </div>
    </div>
  </div>
</div>

【讨论】:

  • 我发现它可以在没有暂停的情况下工作,但我猜你的解决方案更好!非常感谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 2017-08-21
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2020-12-27
  • 1970-01-01
相关资源
最近更新 更多