JSFiddle - React, Tailwind, and code Playground

by neonDog

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css">
<div class="d-md-flex mt-3">

  <div class="options-container d-none">
    <textarea class="form-control mb-2" v-model="items_str"></textarea>
    <div>
      <button class="btn btn-outline-secondary" @click="toggleItems">Check Other Spin Wheel</button>
      <br>
      <br>
      <button class="btn btn-primary float-right" @click="spin">Spin The Wheel</button>
    </div>
  </div>
  <div class="col wheel-col">
      <div class="ticker"></div>
    <div id="wheel_container">
      <svg id="wheel" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" :transform="`rotate(${currDeg})`">
        <defs>
          <circle id="graph" r="15.9154943092" cx="16" cy="16" transform="rotate(-90 16 16)" />
            <mask id="clip">
              <use xlink:href="#graph" fill="#FFF" />
          </mask>
        </defs>
        
        <g mask="url(#clip)" stroke-width="32" class="graph">
          <use xlink:href="#graph" fill="none" stroke="#a94fca" stroke-dasharray="0 0 10 100" class="graph__percent graph__percent--0"></use>
          <text dy=".60" x=".5" y="16" font-size="1.5" transform=" rotate(108,16,16)" class="text">&nbsp;&nbsp;&nbsp;🍕Pizza</text>

          <use xlink:href="#graph" fill="none" stroke="#EE4266" stroke-dasharray="0 10 10 100" class="graph__percent graph__percent--1"></use> 
          <text dy=".60" x=".5" y="16" font-size="1.5" transform=" rotate(144,16,16)" class="text">&nbsp;&nbsp;&nbsp;🌮Mexican</text>

          <use xlink:href="#graph" fill="none" stroke="#FFD23F" stroke-dasharray="0 20 10 100" class="graph__percent graph__percent--2"></use> 
          <text dy=".60" x=".5" y="16" font-size="1.5" transform=" rotate(180,16,16)" class="text">&nbsp;&nbsp;&nbsp;🍔Burgers</text>
          
          <use xlink:href="#graph" fill="none" stroke="#3BCEAC" stroke-dasharray="0 30 10 100"...

SCSS

@import url('https://fonts.googleapis.com/css?family=Roboto+Condensed&display=swap');

html,body{
  height: 100%;
}

textarea.form-control{
  height:300px;
}

:root{
  --border:#bfbfbf;
}

#wheel_container {
  background:var(--border);
  border:10px solid var(--border);
  border-radius:50%;
  box-shadow:0 0 8px #000000bd;
  position:relative;
  max-width:90vh;
  //margin:auto;
  transform: rotate(calc(var(--rotate, 25) * 1deg));
}

#wheel_container.spinning {
  transition: transform 8s cubic-bezier(0.1, -0.01, 0, 1);
}
  
#wheel_container::after{
  content: '';
  display: block;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  border-left: 1vw solid transparent;
  border-right: 1vw solid transparent;
  border-top: 3vw solid var(--border);
  z-index: 9;
  top: 0;
  border-top: 2vw solid var(--border);
}


#wheel .text {
  fill:#252525;
  font-family:'Roboto Condensed', sans-serif;
  //font:bold 1 sans-serif;
  z-index:55;
  //transform-origin: center right;
}

/* Selected prize animation */
#wheel .selected{
  color: white;
  animation: selected 800ms ease;
}

.wheel-col {
  overflow: hidden;
  position: relative;
}

@keyframes selected {
  25% {
    transform: scale(1.25);
    //text-shadow: 1vmin 1vmin 0 hsla(0 0% 0% / 0.1);
  }
  40% {
    transform: scale(0.92);
    //text-shadow: 0 0 0 hsla(0 0% 0% / 0.2);
  }
  60% {
    transform: scale(1.02);
    //text-shadow: 0.5vmin 0.5vmin 0 hsla(0 0% 0% / 0.1);
  }
  75% {
    transform: scale(0.98);
  }
  85% {
    transform: scale(1);
  }
}

@keyframes tick {
  40% {
    transform: rotate(-16deg);
  }
}

.ticker {
  position: absolute;
  --size: clamp(250px, 80vmin, 700px);
  left: 0px;
  top: 50%;
  width: calc(var(--size) / 10);
  height: calc(var(--size) / 20);
  background: linear-gradient(#000 0 50%, #333 50% 100%);
  z-index: 1;
  clip-path: polygon(20% 0, 100% 50%, 20% 100%, 0% 50%);
  transform-origin: center left;
}
.ticker.animate {
  animation: tick 700ms cubic-bezier(0.34, 1.56, 0.64,...

JavaScript

const spinertia = (min, max) => {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
};
function randomNumber(min, max) {
  return Math.random() * (max - min) + min;
}


class WheelSpin {
	
  constructor() {
  	
    this.colors = ['#FFABE5', '#C7F5FF', '#D89FFF', '#F6FCAE']; //'hsl(197 30% 43%)', 'hsl(173 58% 39%)', 'hsl(43 74% 66%)', 'hsl(27 87% 67%)', 
    this.colors = ['#a94fca', '#EE4266', '#FFD23F', '#3BCEAC', '#2765d4'];
    
  	this.prizes = [{
        text: "Shoutout",
        //color: "hsl(197 30% 43%)",
        reaction: "dancing"
      },
      { 
        text: "5x jumps",
        //color: "hsl(173 58% 39%)",
        reaction: "shocked"
      },
      { 
        text: "Jump",
        //color: "hsl(43 74% 66%)",
        reaction: "shocked" 
      },
      {
				text: "Hug",
        //color: "hsl(27 87% 67%)",
        reaction: "shocked"
      },
      {
        text: "Shower 🚿",
        //color: "hsl(12 76% 61%)",
        reaction: "dancing"
      },
      {
        text: "Eternal Damnation",
        //color: "hsl(350 60% 52%)",
        reaction: "laughing"
      },
      {
        text: "Yoga pose",
        //color: "hsl(91 43% 54%)",
        reaction: "laughing"
      },
      {
        text: "Shoutout 💬",
        //color: "hsl(140 36% 74%)",
        reaction: "dancing"
      }
    ];

		this.currentColorIndex = 0;
		this.wheelEl = document.getElementById('wheel_container');
    this.ticker = document.getElementsByClassName('ticker')[0];
    this.runTickerAnimation = this.runTickerAnimation.bind(this);
    
    this.spinnerStyles = window.getComputedStyle(this.wheelEl);

  }
  
  tickSound() {
  	spin_sound.mozPreservesPitch = false;
  	spin_sound.playbackRate = randomNumber(1.5,1.6);
  	spin_sound.play();
  }
  
  runTickerAnimation() {
    // https://css-tricks.com/get-value-of-css-rotation-through-javascript/
    const values =...