JSFiddle - React, Tailwind, and code Playground

by Rolf

HTML

<div class="smilyrating" tabindex="0"></div>

CSS

.smilyrating {
  position: relative;
  width: 500px;
  padding: 4px;
  border: 1px solid green;
}
   
.smilyrating div {
  display: block;
  box-sizing: border-box;
  width: 150px; 
  height: 150px;
  margin: 0;
  padding: 0;
}

JavaScript

EventTarget.provideEventsFor = function(object) {
  let eventTarget = new EventTarget();
  object.addEventListener = (t,l,o)=>eventTarget.addEventListener(t,l,o);
  object.removeEventListener = (t,l,o)=>eventTarget.removeEventListener(t,l,o);
  object.dispatchEvent = e=>eventTarget.dispatchEvent(e);
}

SmileRating = (function() {
	let symPrivates = Symbol("privates");
	
	function slantedEyePath(cx, cy, r, angle, opening) {
	   let d0 = angle - opening/2, d1 = angle + opening/2;
	   let w1 = d0*Math.PI/180, w2 = d1*Math.PI/180
   
	   let sx = Math.round(cx + r*Math.cos(w1), 0);
	   let sy = Math.round(cy - r*Math.sin(w1), 0);
   	let ex = Math.round(cx + r*Math.cos(w2), 0);
	   let ey = Math.round(cy - r*Math.sin(w2), 0);

	   return "M"+sx+" "+sy+" A"+r+" "+r+" 0 1 1 "+ex+" "+ey;
	}
	
	function changeEyes(eyes, rating) {
	      
		let angle=90, 
			 opening=10;
			 
      if (rating < .25) {
      	opening = 100;
      	angle = 65+rating*4*70;
      }
      else if (rating < .5) {
      	angle = 135;
      	opening = (0.5-rating)*4*100;
      }
  		eyes[0].setAttribute("d", slantedEyePath(300, 350, 100, angle, opening));
		eyes[1].setAttribute("d", slantedEyePath(700, 350, 100, 180-angle, opening))	;
	}
	
	function changeFaceColor(face, rating) {
	   let green = 255;
	   let red = 255;
      if (rating < .25) { 
      	red = 200 + rating*4*55;
      	green = 80 + rating*4*175;
      }
      let color = "rgb("+Math.round(red,0)+","+Math.round(green,0)+",80)";
      face.setAttribute("fill", color);
	}
	
	let mouthRanges = [
		{ value: 0.00, left: { y: 750, c1: 600, c2: 650 }, right: { y: 750, c1: 600, c2: 650 } },
		{ value: 0.25, left: { y: 750, c1: 600, c2: 650 }, right: { y: 750, c1: 600, c2: 650 } },
		{ value: 0.50, left: { y: 700, c1: 700, c2: 700 }, right: { y: 600, c1: 600, c2: 600 } },
		{ value: 0.75, left: { y: 600, c1: 750, c2: 650 }, right: { y: 600, c1: 750, c2: 650 } },
		{ value: 1.00, left: { y: 600, c1: 750, c2: 600 }, right: { y: 600, c1: 750,...