headphone progress knob
by Soviut
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<body ng-app="App">
<div ng-controller="MainCtrl">
<div class="toolbar">
<input type="range" name="points" min="0" max="1" step="0.1" ng-model="percent" /> {{ percent * 100 }}%
</div>
<headphones width="300" height="300" initial-percent="0" percent="percent" />
</div>
</body>
CSS
.toolbar {
display: block;
}
headphones {
display: block;
}
JavaScript
var app = angular.module('App', []);
app.controller('MainCtrl', function($scope) {
$scope.percent = 0.5;
});
app.directive('headphones', function() {
return {
restrict: 'E',
scope: {
width: '@',
height: '@',
initialPercent: '=',
percent: '='
},
template: '<canvas></canvas>',
link: function(scope, el, attrs) {
el.width = scope.width;
el.height = scope.height;
var canvas = el.children('canvas')[0];
canvas.width = scope.width;
canvas.height = scope.height;
var ctx = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
var percent = scope.initialPercent;
var targetPercent = scope.percent;
var startAngle = Math.PI * 0.64;
var endAngle = Math.PI * 2.36;
var radius = width * 2;
var maskWidth = 100;
var maskHeight = 96;
var maskScale = Math.min(width / maskWidth, height / maskHeight);
var centerX = width / 2;
var centerY = height / 2;
var friction = 0.05;
var minDiff = 0.0001; // smallest distance before destination is considered reached
var refreshRate = 16; // milliseconds
var bgColor = '#DDDDDD';
var fgColor = '#DD0000';
function redraw() {
var angle = (endAngle - startAngle) * percent + startAngle;
ctx.save();
ctx.translate((width / 2) - (maskWidth * maskScale / 2), (height / 2) - (maskHeight * maskScale / 2));
ctx.scale(maskScale, maskScale);
ctx.beginPath();
ctx.moveTo(99.4, 52.0);
ctx.bezierCurveTo(99.5, 50.8, 99.6, 49.6, 99.7, 48.4);
...