JSFiddle - React, Tailwind, and code Playground

by neonDog

HTML

<!-- source https://codepen.io/kris-ellery/pen/vGfeL -->

<section class="row">
  <div class="column">
    <div class="donut-chart gradient-border" data-donut-chart="1">
      <div class="ticker"></div>
    </div>
    
  </div>
  <div class="column">
    <div class="donut-chart" data-donut-chart="2"></div>
  </div>
</section>


<!--<audio id="start_sound" src="https://sounds.pond5.com/prize-wheel-award-spin-sound-effect-074718219_nw_prev.m4a" preload></audio>
<audio id="tick_sound" src="https://howdoweb.com/temp/prize-wheel-tick.webm" preload></audio> <!--https://howdoweb.com/images/temp/wheel-spin.mp3-->

<!--<audio id="start_sound" src="https://howdoweb.com/temp/prize-wheel-start2b.webm" preload></audio>
<audio id="tick_sound" src="https://howdoweb.com/temp/prize-wheel-tick2b.webm" preload></audio>-->


<audio id="start_sound" src="https://howdoweb.com/temp/prize-wheel-start.webm" preload></audio>
<audio id="tick_sound" src="https://howdoweb.com/temp/prize-wheel-tick.webm" preload></audio>


<audio id="prize_sound" src="https://sounds.pond5.com/sparkly-bonus-b-1-sound-effect-123688935_nw_prev.m4a" preload></audio>

CSS

/**
  * Demo scaffolding
  * --------------------------------------------------
  */
*,
*:before,
*:after {
   box-sizing: border-box;
}

body {
    position: relative;
    margin: 0;
    background: #222;
    text-rendering: optimizeSpeed;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

.row {
    display: block;
    width: 300px;
    margin: 50px auto;
    animation: fadeIn .4s ease-in .4s both;
}
.row:before,
.row:after {
    display: table;
    content: ' ';
}
.row:after {
    clear: both;
}

.column {
    float: left;
    width: 500px;
    padding: 25px;
}

@keyframes fadeIn {
    0%
    {
        opacity: 0;
    }

    100%
    {
        opacity: 1;
    }
}
/**
  * Donut Chart
  * --------------------------------------------------
  */
.donut-chart {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
    position: relative;
    /*overflow: hidden;*/
    width: 450px;
    height: 450px;
    border-radius: 50%;
    background-color: #f5f7fa;
    box-shadow: 0 0 0 6px rgba(0, 0, 0, .2);
}


.outer-circle,
.inner-circle {
    position: absolute;
    border-radius: 50%;
}

.outer-circle {
    top: 1%;
    right: 1%;
    bottom: 1%;
    left: 1%;
    background-color: #fff;
    box-shadow: inset 0 0 0 6px rgba(0, 0, 0, .2);
    transform: rotate(calc(var(--rotate) * 1deg));
}
.outer-circle.spinning {
   transition: transform 8s cubic-bezier(0.1, -0.01, 0, 1);
}

.inner-circle {
    top: 38%;
    right: 38%;
    bottom: 38%;
    left: 38%;
    background-color: #f5f7fa;
    background-color: #222;
    box-shadow: 0 0 0 6px rgba(0, 0, 0, .2);
}

.inner-circle-label,
.inner-circle-value {
    position: absolute;
    top: 50%;
    left: 0;
    display: block;
    width: 100%;
    text-align: center;
}

.inner-circle-label {
    font-size: 18px;
    line-height: 1;
    margin-top: -30px;
    color: #aab2bd;
    display: none;
}

.inner-circle-value {
    font-size: 42px;
    font-weight: bold;
    line-height: 1;
   ...

JavaScript

/**
  * Donut Chart
  * --------------------------------------------------
  */

  class NeonDonutChart {
	
    constructor(options) {
			
      this.currentColorIndex = 0;
      
      this.settings(options);
      this.createChartStructre();
      this.setChartMeta();
      this.build();
    }

    update(options) {

      this.settings(options);
      this.setChartMeta();
      this.build();

    }

    settings(options) {
			
      if (!this.config) this.config = {};
      
      const defaults = {
      	colors: ['#4FC1E9', '#A0D468', '#ED5565', '#AC92EC', '#5D9CEC', '#FFCE54'],
      	container: this.config.container,
      	data: this.config.data,
      	label: 'Total',
        offset: 0
      };
      
      this.config = Object.assign({}, defaults, options);

    }
    
    build() {

      const container = this.config.container.querySelector('.outer-circle');
      const wedges = container.querySelectorAll('[data-wedge-id]');
      const wedgesIdArray = [];

      for (let i = 0; i < wedges.length; i++) {
        wedgesIdArray.push(wedges[i].dataset.wedgeId);
      }

      for (let j = 0; j < this.config.data.wedges.length; j++) {
        if (wedgesIdArray.indexOf(this.config.data.wedges[j].id) == -1) {
          var wedge = this.createWedge(this.config.data.wedges[j]);
          container.appendChild(wedge);
        }
        this.setWedge(this.config.data.wedges[j]);
      }

    }

    createChartStructre() {

      const outer = document.createElement('div');
     	const inner = document.createElement('div');
      const label = document.createElement('span');
      const value = document.createElement('span');

      outer.className = 'outer-circle';
      inner.className = 'inner-circle';
      label.className = 'inner-circle-label';
      value.className = 'inner-circle-value';

      this.config.container.appendChild(outer);
      this.config.container.appendChild(inner);
      inner.appendChild(label);
      inner.appendChild(value);

    }

...