JSFiddle - React, Tailwind, and code Playground

by turiyag

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/5.0.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<div class="container">
  <h2>
    Pie Wheels
  </h2>
  <div class="row black-bg">
    <div class="dial dial-1"></div>
    <div class="dial dial-3"></div>
    <div class="dial dial-1"></div>
  </div>
  <div class="row">
    <div class="dial dial-2"></div>
    <div class="dial dial-3"></div>
    <div class="dial dial-2"></div>
  </div>
  <div class="row">
    <div class="dial dial-2"></div>
    <div class="dial dial-3"></div>
    <div class="dial dial-2"></div>
  </div>
  <div class="row">

    <p id="log">

    </p>
  </div>
</div>

SCSS

* { box-sizing: border-box; }

.pie-container {
	width: 320px;
  max-width: 320px;
	margin: 10% auto;
  box-sizing: border-box;
  border: 1px solid black;
}
.black-bg {
  background: black;
}

.dial {
	width: 144px;
	height: 144px;
	background: url('https://edgemontgeek.com/ziggurat/img/Ziggurat-rotiles-1.png');
	/* border-radius: 50%; */
	/* border: 20px solid black; */
	/* border-color: red green blue yellow; */
  /* box-sizing: border-box; */
  float: left;
}

.dial-1 {
	background: url('https://edgemontgeek.com/ziggurat/img/Ziggurat-rotiles-1.png');
}

.dial-2 {
	background: url('https://edgemontgeek.com/ziggurat/img/Ziggurat-rotiles-2.png');
}

.dial-3 {
	background: url('https://edgemontgeek.com/ziggurat/img/Ziggurat-rotiles-3.png');
}

JavaScript

function get_degrees(mouse_x, mouse_y, center_x, center_y) {

  const radians = Math.atan2(mouse_x - center_x, mouse_y - center_y);
  const degrees = Math.round((radians * (180 / Math.PI) * -1) + 100);

  return degrees;
}

function nearest_90(degrees) {
	let clean_degrees = degrees % 360
  if (clean_degrees < 0) clean_degrees += 360
  if (clean_degrees <= 45) return 0
  else if (clean_degrees <= 45 + 90) return 90
  else if (clean_degrees <= 45 + 180) return 180
  else if (clean_degrees <= 45 + 270) return 270
  else {
  	return 0
  }
}

const INITIAL_ROTATIONS = [
  180,90,0,
  0,0,180,
  180,90,0
];

(function($) {
  'use strict';

  /**
   * Dial element
   * @var object
   */
  $('.dial').each(function(idx) {
    const $dial = $(this);

    /**
     * Calculate mouse rotation relative to $dial center
     * @param  int  mouse_x
     * @param  int  mouse_y
     */
    const radius = $dial.outerWidth() / 2;
    const center_x = $dial.offset().left + radius;
    const center_y = $dial.offset().top + radius;
    let curr_degrees = INITIAL_ROTATIONS[idx];
    $dial.css('transform', 'rotate(' + curr_degrees + 'deg)');


    $dial.on('mousedown', function(event) {

      // Calculate the mouse position in degrees
      const click_degrees = get_degrees(event.pageX, event.pageY, center_x, center_y);
      const pre_click_degrees = curr_degrees;

      $(document).bind('mousemove', click_degrees, function(event) {
        // Calculate the mouse move position, removing starting point
        const degrees = get_degrees(event.pageX, event.pageY, center_x, center_y) - click_degrees;
				$("#log").text(`center (x,y): (${center_x},${center_y}, page (x,y): ${event.pageX}, ${event.pageY}, click_degrees: ${click_degrees}, degrees: ${degrees}`)
        curr_degrees = pre_click_degrees + degrees
        $dial.css('transform', 'rotate(' + curr_degrees + 'deg)');
      });
      $(document).bind('mouseup', click_degrees, function(event) {
    		$(document).unbind('mousemove');
 ...