Javascript CSS 旋转不准确

Javascript CSS rotation inaccuracy

我一直在通过 CSS 和 Javascript 制作一个小模拟时钟图标,并且 运行 变成了一个奇怪的图形故障。

function r() {
  var vwMin, r;
  if (window.innerWidth < window.innerHeight) {
    vwMin = window.innerWidth;
  } else {
    vwMin = window.innerHeight;
  }
  r = vwMin * .0225 - 1;
  if (r < 0) {
    r += 1;
  }
  document.getElementById("min").style.transformOrigin = "50% calc(100% - " + r + "px)";
  document.getElementById("min").style.bottom = "calc(50% - " + r + "px)";
  document.getElementById("hr").style.transformOrigin = "50% calc(100% - " + r + "px)";
  document.getElementById("hr").style.bottom = "calc(50% - " + r + "px)";
}

function clock() {
  r();
  var date = new Date(),
      hours;
  if (date.getHours() > 12) {
    hours = ((date.getHours() - 12) / 12) + (date.getMinutes() / 720);
  } else {
    hours = (date.getHours() / 12) + (date.getMinutes() / 720);
  }
  var mins = date.getMinutes() / 60;
  var hours = .5;
  var mins = 0;
  document.querySelector('#hr').style.transform = 'rotate(' + hours + 'turn)';
  document.querySelector('#min').style.transform = 'rotate(' + mins + 'turn)';
}

$(document).ready(function() {
  clock();
  window.onresize = function(event) {
    r();
  };
});
#clock {
  position: absolute;
  border: solid;
  width: 70vmin;
  height: 70vmin;
  border-radius: 50%;
  border-width: 6vmin;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

#clock>* {
  position: absolute;
  left: 50%;
  margin-left: -2.25vmin;
  border: 2.25vmin solid;
  border-radius: 2.25vmin;
  background: black;
}

#min {
  height: 25vmin;
}

#hr {
  height: 16vmin;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="clock">
  <div id="hr"></div>
  <div id="min"></div>
</div>

脚本找到 wherr 到 transform-origin 的位置并偏移 div 使得时钟指针始终干净地相交。然而,CSS 旋转似乎并没有在 div 的精确水平中心旋转。例如,如果我手动将时钟设置为6:00,则分针会很干净,而旋转的时针会模糊。

这是怎么回事,我该如何解决(如果可能)?

变换在子像素移动时表现得非常奇怪,即使不应该有任何移动也是如此。您通常可以通过设置 translateZ(0) 来解决这个问题,看起来它适用于您的情况。由于您已经在修改内联 transform,只需像这样将 Z 添加到其中:

 document.querySelector('#hr').style.transform = 'rotate(' + hours + 'turn) translateZ(0)';
 document.querySelector('#min').style.transform = 'rotate(' + mins + 'turn) translateZ(0)';

编辑:

有趣的是,这似乎实际上使时针变得模糊 有时 基于屏幕大小 - 在我的全屏代码片段中工作正常,但在小代码片段框中有点模糊

function r() {
  var vwMin, r;
  if (window.innerWidth < window.innerHeight) {
    vwMin = window.innerWidth;
  } else {
    vwMin = window.innerHeight;
  }
  r = vwMin * .0225 - 1;
  if (r < 0) {
    r += 1;
  }
  document.getElementById("min").style.transformOrigin = "50% calc(100% - " + r + "px)";
  document.getElementById("min").style.bottom = "calc(50% - " + r + "px)";
  document.getElementById("hr").style.transformOrigin = "50% calc(100% - " + r + "px)";
  document.getElementById("hr").style.bottom = "calc(50% - " + r + "px)";
}

function clock() {
  r();
  var date = new Date(),
    hours;
  if (date.getHours() > 12) {
    hours = ((date.getHours() - 12) / 12) + (date.getMinutes() / 720);
  } else {
    hours = (date.getHours() / 12) + (date.getMinutes() / 720);
  }
  var mins = date.getMinutes() / 60;
  
  hours = 6;
  mins = 0;
  document.querySelector('#hr').style.transform = 'rotate(' + hours + 'turn)';
  document.querySelector('#min').style.transform = 'rotate(' + mins + 'turn) translateZ(0)';
}

$(document).ready(function() {
  clock();
  window.onresize = function(event) {
    r();
  };
});
#clock {
  position: absolute;
  border: solid;
  width: 70vmin;
  height: 70vmin;
  border-radius: 50%;
  border-width: 6vmin;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

#clock>* {
  position: absolute;
  left: 50%;
  border: 2.25vmin solid;
  border-radius: 2.25vmin;
  background: black;
}

#min {
  height: 25vmin;
}

#hr {
  height: 16vmin;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="clock">
  <div id="hr"></div>
  <div id="min"></div>
</div>

我最终想出的解决方案是使用 SVG 而不是使用 div 进行返工。我认为正在发生的事情是,由于手 div 的中心几乎总是在一个子像素上,因此大多数浏览器会混叠或舍入到最近的像素,从而导致时钟指针在旋转时分离。 SVG 允许人们从解决问题的不同来源进行绘制。这是解决此问题的代码:

HTML

<html>
  <body>
    <div class="analog-clock">
      <svg width="100vmin" height="100vmin" viewBox="-50 -50 100 100">
        <circle id="clock-face" cx="0" cy="0" r="45"/>
        <line id="h-hand" x1="0" y1="0" x2="0" y2="-22"/>
        <line id="m-hand" x1="0" y1="0" x2="0" y2="-33"/>
      </svg>
    </div>
  </body>
</html>

CSS

html {
  overflow: hidden;
}
.analog-clock{
  position: absolute;
  width: 100vmin;
  height: 100vmin;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}
#clock-face{
  stroke: black;
  stroke-width: 6;
  fill: white;
}
#h-hand, #m-hand{
  stroke: black;
  stroke-linecap: round;
  stroke-width: 4.5;
}

JS

function clock() {
  var d = new Date();
  function setAttr(id,deg) {
    document.getElementById(id).setAttribute('transform', 'rotate(' + deg + ', 0, 0)');
  };
  setAttr('h-hand', 30 * ((d.getHours() % 12) + d.getMinutes() / 60));
  setAttr('m-hand', 6 * d.getMinutes());
}

window.onload = clock();
setInterval(function() {
  clock();
}, 1000);