拖动时旋转钟针以校正角度-Vanilla JS

时间:2020-01-14 14:33:34

标签: javascript geometry atan2

我用分针和时针实现了一个模拟时钟。此练习的目的是在拖动时将钟针旋转至小时标签的相应角度;即鼠标四处移动时。

我发现一些示例使用JQuery和其他库。我正在尝试仅使用香草js。我看过这里位于stackoverflow以及其他地方的一些示例,研究了逻辑并试图理解atan2的文档,这是我所能获得的:

//rotate handler
const rotateHand = (event)=>{
    const elem = event.target;
    elem.style.cursor = "grabbing";
    let rotating = true;
    const clock = document.querySelector(".gamut__timePicker__clock");
    const radius = 252 / 2;
    const rotateHandler = (e)=>{
        const radians = Math.atan2(e.pageX - radius, e.pageY - radius);
        let rotateDegrees = (radians * (180 / Math.PI) * -1) -180;
        if (rotating) {
            elem.style.transform = `rotate(${rotateDegrees}deg)`;
        }
    };
    document.addEventListener("mousemove", rotateHandler);
    const cancelRotate = (event)=>{
        elem.style.cursor = "grab";
        rotating = !rotating;
        document.removeEventListener("mousemove", rotateHandler);
        document.removeEventListener("mouseup", cancelRotate);

    };
    document.addEventListener("mouseup", cancelRotate);
};

document.querySelector(".gamut__timePicker__minHand").addEventListener("mousedown", rotateHand);
document.querySelector(".gamut__timePicker__hrHand").addEventListener("mousedown", rotateHand);
@import url("https://fonts.googleapis.com/css?family=Roboto&display=swap");
.gamut__timePicker {
  border: 1px solid gray;
  width: 300px;
  height: 335px;
  display: -webkit-box;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
          flex-direction: column;
  font-family: 'Roboto', sans-serif;
}

.gamut__timePicker__meridiamSelector {
  height: 20px;
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: justify;
          justify-content: space-between;
}

.gamut__timePicker__meridiamSelector--meridiam {
  text-align: center;
  -webkit-box-flex: 1;
          flex-grow: 1;
  border: 1px solid gray;
  font-size: 0.875rem;
  line-height: 20px;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}

.gamut__timePicker__meridiamSelector--meridiam:hover {
  background: #efefef;
}

.gamut__timePicker__meridiamSelector--selected {
  background: #607d8b !important;
  color: white;
}

.gamut__timePicker__clockWrapper {
  -webkit-box-flex: 1;
          flex-grow: 1;
  align-self: stretch;
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
  -webkit-box-align: center;
          align-items: center;
  position: relative;
}

.gamut__timePicker__clock {
  border-radius: 50%;
  width: 250px;
  height: 250px;
  border: 1px solid gray;
  margin: 0 auto;
  position: relative;
}

.gamut__timePicker__clock--minPointer {
  width: 1px;
  height: 10px;
  background-color: #424242;
  position: absolute;
  -webkit-transform-origin: 0% 0%;
          transform-origin: 0% 0%;
}

.gamut__timePicker__clock--hrPointer {
  position: absolute;
  -webkit-transform-origin: 0% 0%;
          transform-origin: 0% 0%;
}

.gamut__timePicker__clock--hrPointer::before {
  top: -4px;
  left: -7px;
  content: "\25BC";
  position: absolute;
}

.gamut__timePicker__labels {
  border-radius: 50%;
  width: 210px;
  height: 210px;
  margin: 0 auto;
  position: absolute;
  pointer-events: none;
}

.gamut__timePicker__labels--hourLabel {
  position: absolute;
  -webkit-transform: translate(-50%, -45%);
          transform: translate(-50%, -45%);
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
}

.gamut__timePicker__minHand {
  width: 20px;
  height: 100px;
  background-image: url(https://res.cloudinary.com/dvzwvxhev/image/upload/v1578025454/clock_min.svg);
  background-size: 100% 100%;
  position: absolute;
  -webkit-transform-origin: 49% 92%;
          transform-origin: 49% 92%;
  top: 15%;
  -webkit-transform: rotate(0deg);
          transform: rotate(0deg);
  cursor: -webkit-grab;
  cursor: grab;
}

.gamut__timePicker__hrHand {
  width: 40px;
  height: 70px;
  background-image: url(https://res.cloudinary.com/dvzwvxhev/image/upload/v1578274567/clock_hr.svg);
  background-size: 100% 100%;
  position: absolute;
  -webkit-transform-origin: 50% 93%;
          transform-origin: 50% 93%;
  top: 25%;
  -webkit-transform: rotate(0deg);
          transform: rotate(0deg);
  cursor: -webkit-grab;
  cursor: grab;
}

.gamut__timePicker__time {
  height: 34px;
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
}

.gamut__timePicker__time > input {
  width: 35px;
  border: none;
  border-bottom: 1px solid #ababab;
  text-align: center;
  font-size: 1.125rem;
  outline: none;
  height: 25px;
  padding: 0;
}

.gamut__timePicker__time > input:focus {
  border-bottom: 2px solid #607d8b;
}

.gamut__timePicker__time--separator {
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  font-size: 1.125rem;
  height: 25px;
}

.gamut__timePicker__done {
  background: #efefef;
  text-align: center;
  border-top: 1px solid gray;
  cursor: pointer;
}
<div class="gamut__timePicker" style="top: 31px; left: 8px; z-index: 9;"><div class="gamut__timePicker__meridiamSelector"><div data-meridiam-value="am" class="gamut__timePicker__meridiamSelector--meridiam gamut__timePicker__meridiamSelector--selected">AM</div><div data-meridiam-value="pm" class="gamut__timePicker__meridiamSelector--meridiam">PM</div></div><div class="gamut__timePicker__clockWrapper"><div class="gamut__timePicker__clock"><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(90deg); left: 100%; top: 50%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(96deg); left: 99.7261%; top: 55.2264%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(102deg); left: 98.9074%; top: 60.3956%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(108deg); left: 97.5528%; top: 65.4508%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(114deg); left: 95.6773%; top: 70.3368%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(120deg); left: 93.3013%; top: 75%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(126deg); left: 90.4508%; top: 79.3893%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(132deg); left: 87.1572%; top: 83.4565%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(138deg); left: 83.4565%; top: 87.1572%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(144deg); left: 79.3893%; top: 90.4508%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(150deg); left: 75%; top: 93.3013%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(156deg); left: 70.3368%; top: 95.6773%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(162deg); left: 65.4508%; top: 97.5528%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(168deg); left: 60.3956%; top: 98.9074%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(174deg); left: 55.2264%; top: 99.7261%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(180deg); left: 50%; top: 100%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(186deg); left: 44.7736%; top: 99.7261%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(192deg); left: 39.6044%; top: 98.9074%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(198deg); left: 34.5492%; top: 97.5528%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(204deg); left: 29.6632%; top: 95.6773%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(210deg); left: 25%; top: 93.3013%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(216deg); left: 20.6107%; top: 90.4508%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(222deg); left: 16.5435%; top: 87.1572%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(228deg); left: 12.8428%; top: 83.4565%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(234deg); left: 9.54915%; top: 79.3893%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(240deg); left: 6.69873%; top: 75%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(246deg); left: 4.32273%; top: 70.3368%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(252deg); left: 2.44717%; top: 65.4508%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(258deg); left: 1.09262%; top: 60.3956%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(264deg); left: 0.273905%; top: 55.2264%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(270deg); left: 0%; top: 50%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(276deg); left: 0.273905%; top: 44.7736%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(282deg); left: 1.09262%; top: 39.6044%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(288deg); left: 2.44717%; top: 34.5492%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(294deg); left: 4.32273%; top: 29.6632%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(300deg); left: 6.69873%; top: 25%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(306deg); left: 9.54915%; top: 20.6107%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(312deg); left: 12.8428%; top: 16.5435%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(318deg); left: 16.5435%; top: 12.8428%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(324deg); left: 20.6107%; top: 9.54915%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(330deg); left: 25%; top: 6.69873%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(336deg); left: 29.6632%; top: 4.32273%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(342deg); left: 34.5492%; top: 2.44717%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(348deg); left: 39.6044%; top: 1.09262%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(354deg); left: 44.7736%; top: 0.273905%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(360deg); left: 50%; top: 0%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(366deg); left: 55.2264%; top: 0.273905%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(372deg); left: 60.3956%; top: 1.09262%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(378deg); left: 65.4508%; top: 2.44717%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(384deg); left: 70.3368%; top: 4.32273%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(390deg); left: 75%; top: 6.69873%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(396deg); left: 79.3893%; top: 9.54915%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(402deg); left: 83.4565%; top: 12.8428%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(408deg); left: 87.1572%; top: 16.5435%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(414deg); left: 90.4508%; top: 20.6107%;"></div><div class="gamut__timePicker__clock--hrPointer" style="transform: rotate(420deg); left: 93.3013%; top: 25%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(426deg); left: 95.6773%; top: 29.6632%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(432deg); left: 97.5528%; top: 34.5492%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(438deg); left: 98.9074%; top: 39.6044%;"></div><div class="gamut__timePicker__clock--minPointer" style="transform: rotate(444deg); left: 99.7261%; top: 44.7736%;"></div></div><div class="gamut__timePicker__labels"><span class="gamut__timePicker__labels--hourLabel" style="left: 100%; top: 50%;">3</span><span class="gamut__timePicker__labels--hourLabel" style="left: 93.3013%; top: 75%;">4</span><span class="gamut__timePicker__labels--hourLabel" style="left: 75%; top: 93.3013%;">5</span><span class="gamut__timePicker__labels--hourLabel" style="left: 50%; top: 100%;">6</span><span class="gamut__timePicker__labels--hourLabel" style="left: 25%; top: 93.3013%;">7</span><span class="gamut__timePicker__labels--hourLabel" style="left: 6.69873%; top: 75%;">8</span><span class="gamut__timePicker__labels--hourLabel" style="left: 0%; top: 50%;">9</span><span class="gamut__timePicker__labels--hourLabel" style="left: 6.69873%; top: 25%;">10</span><span class="gamut__timePicker__labels--hourLabel" style="left: 25%; top: 6.69873%;">11</span><span class="gamut__timePicker__labels--hourLabel" style="left: 50%; top: 0%;">12</span><span class="gamut__timePicker__labels--hourLabel" style="left: 75%; top: 6.69873%;">1</span><span class="gamut__timePicker__labels--hourLabel" style="left: 93.3013%; top: 25%;">2</span></div><div class="gamut__timePicker__minHand" style="transform: rotate(0deg);"></div><div class="gamut__timePicker__hrHand" style="transform: rotate(240deg);"></div></div><div class="gamut__timePicker__time"><input type="text" data-time-param="hour"><span class="gamut__timePicker__time--separator">:</span><input type="text" data-time-param="minute"></div><div class="gamut__timePicker__done">DONE</div></div>

如您在上面的代码段中所见,时钟指针正在旋转,但是角度不精确,这之间存在一些差异。目的是当鼠标指针与各个小时相对应的角度时,指针指向正确的小时/分钟。

0 个答案:

没有答案
相关问题