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);
}
...