BASE

by whelkaholism

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.2/moment.min.js"></script>
<div>
<canvas data-bind="timeAndLevelMeter: { time: Time, level: Level, styles: Styles }"></canvas>
</div>
<br/>
<button data-bind="click: Time.bind(0, Time() - 1)">&lt; Time</button>
<button data-bind="click: Time.bind(0, Time() + 1)">Time &gt;</button>
<br/>
<button data-bind="click: Level.bind(0, Level() - 1)">&lt; Level</button>
<button data-bind="click: Level.bind(0, Level() + 1)">Level &gt;</button>

CSS

body {
  background: black;
}

div {
  display: flex;
  width: 
}

canvas {
  width: 50%;
  height: 50%;
  background: #ffffff;
}

button {
  background: #404040;
  color: #ffffff;
  font-weight: bold;
  border: none;
  padding: 10px;        
}

button:focus {
  background: #408080;
}

JavaScript

(function() 
{
  var FULL_CIRCLE = 2 * Math.PI;
  var START_ANGLE_TOP = FULL_CIRCLE - (FULL_CIRCLE * 0.25);

  var _drawArc = function(ctx, strokestyle, linewidth, angle)
  {
    ctx.save();
    //
    ctx.fillStyle = 'rgba(255, 0, 0, 0)';
    ctx.strokeStyle = strokestyle;
    ctx.lineWidth = linewidth;
    
    var radius =  (ctx._w / 2) - (linewidth / 2);

    ctx.beginPath();    
    ctx.arc(ctx._w / 2, ctx._h / 2, radius, START_ANGLE_TOP, angle);
    ctx.stroke();
    //
    ctx.restore();
  };
  
  var _limitPC = function(pc)
  {
    return pc < 0 ? 0 : (pc > 100 ? 100 : pc);
  };
  
  ko.bindingHandlers.timeAndLevelMeter = {
    init: 
      function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
      {
        if(!el.nodeName == 'CANVAS')
          console.log('timeAndLevelMeter must be bound to CANVAS');
      },
    update: 
      function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
      {
        var cfg = ko.unwrap(f_valueaccessor());
                
        el.width = el.offsetWidth;
				el.height = el.offsetHeight;

        var ctx = el.getContext("2d");
        ctx._w = el.width;
        ctx._h = el.height;        
        
        var styles = ko.unwrap(cfg.styles) || {};
        styles.bgColor = styles.bgColor || 'rgba(0, 0, 255, 0.5)';
        styles.timeColor = styles.timeColor || 'rgba(0, 0, 255, 0.5)';
        styles.levelColor = styles.levelColor || 'rgba(0, 0, 255, 0.5)';
        styles.lineWidth = styles.lineWidth || (ctx._w / 6);
        
        var time = _limitPC(parseFloat(ko.unwrap(cfg.time)) / 100);
        var level = _limitPC(parseFloat(ko.unwrap(cfg.level)) / 100);
                
        _drawArc(ctx, styles.bgColor, styles.lineWidth, START_ANGLE_TOP + FULL_CIRCLE); 
        
        !isNaN(time) && _drawArc(ctx, styles.timeColor, styles.lineWidth, START_ANGLE_TOP + (FULL_CIRCLE * time));
        !isNaN(level) && _drawArc(ctx, styles.levelColor, styles.lineWidth, START_ANGLE_TOP +...