var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.reveal = false;
  
  $scope.config = {
    width: 100,
    blurRadius: 6,
    ratio: 10,
    opacity: 0.6
  };
});
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
    <script src="app.js"></script>
    <script src="yt-progress.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <div class="container"
      ng-class="{
        reveal: reveal
      }">
      <div class="demo-wrap">
        <div class="demo" ng-repeat="scale in [2, 4]">
          <yt-progress config="config"
            ng-attr-data-scale="{{scale}}"
            ng-style="{transform: 'scale('+ scale +')'}"></yt-progress>
        </div>
      </div>
      <div class="controls">
        <div class="row">
          <div class="col-sm-10">
            <div class="form-group">
              <label for="width">寬度</label>
              <input type="range" id="width" ng-model="config.width" min="20" max="200">
            </div>
          </div>
          <div class="col-sm-2">
            <div class="number">{{config.width}}px</div>
          </div>
        </div>
        <div class="row">
          <div class="col-sm-10">
            <div class="form-group">
              <label for="ratio">頭/尾 比例</label>
              <input type="range" id="ratio" ng-model="config.ratio" min="1" max="99">
            </div>            
          </div>
          <div class="col-sm-2">
            <div class="number">{{config.ratio}}/{{100 - config.ratio}}</div>
          </div>
        </div>
        <div class="row">
          <div class="col-sm-10">
            <div class="form-group">
              <label for="blur-radius">模糊範圍</label>
              <input type="range" id="blur-radius" ng-model="config.blurRadius" min="1" max="20">
            </div>
          </div>
          <div class="col-sm-2">
            <div class="number">{{config.blurRadius}}px</div>
          </div>
        </div>
        <div class="row">
          <div class="col-sm-10">
            <div class="form-group">
              <label for="opacity">透明度</label>
              <input type="range" id="opacity" ng-model="config.opacity" min="0" max="1" step="0.01">
            </div>
          </div>
          <div class="col-sm-2">
            <div class="number">{{config.opacity}}</div>
          </div>
        </div>
        <div class="row">
          <div class="col-sm-12">
            <button type="button" class="btn btn-default" ng-class="{
              active: reveal
            }" ng-click="reveal = !reveal">真身模式</button>
          </div>
        </div>
      </div>
    </div>

  </body>

</html>
/* Put your css in here */

.demo-wrap {
  overflow: hidden;
}

.demo {
  position: relative;
  /* overflow: hidden; */
  width: 100%;
  height: 100px;
}
.demo .yt-progress {
  transform-origin: 100.1% 50%;
}

.reveal .demo .yt-progress dd,
.reveal .demo .yt-progress dt {
  background-color: white;
  opacity: 1 !important;
}

.yt-progress {
  position: absolute;
  top: 50%; right: 30px;
  
  width: 100%;
  height: 2px;
  background: #b91f1f;
  border-radius: 1px;
  transition: width 500ms ease-out, opacity 400ms linear;
}


.yt-progress dd, .yt-progress dt {
  position: absolute;
  top: 0;
  height: 2px;
  box-shadow: #b91f1f 1px 0 6px 1px;
  border-radius: 100%;
  
  opacity: .6;
}

.number {
  padding: 8px;
  text-align: center;
  font-size: 24px;
}
<div class="yt-progress">
  <dt ng-style="{
    'box-shadow': '#b91f1f 1px 0 '+ config.blurRadius +'px 1px',
    'right': tailRight +'px',
    'clip': tailClip,
    'width': tailWidth +'px',
    'opacity': config.opacity
  }"></dt>
  <dd ng-style="{
    'box-shadow': '#b91f1f 1px 0 '+ config.blurRadius +'px 1px',
    'right': headRight + 'px',
    'clip': headClip,
    'width': headWidth +'px',
    'opacity': config.opacity
  }"></dd>
</div>
angular.module('plunker')

.directive('ytProgress', function () {
  function clip(c) {
    var clipStr = [c.top, c.right, c.bottom, c.left].map(function (v) {
      return v + 'px';
    }).join(',')
    return 'rect(' + clipStr + ')';
  }
  
  return {
    restrict: 'EA',
    scope: {
      config: '='
    },
    replace: true,
    templateUrl: 'yt-progress.tmpl.html',
    link: function (scope, iElm, iAttrs) {
      scope.$watch('config', function (config) {
        scope.headWidth = config.width * (config.ratio / 100) * 2;
        scope.tailWidth = config.width * 2 - scope.headWidth;
        
        scope.headClip = clip({
          top: -config.blurRadius,
          right: scope.headWidth + Number(config.blurRadius),
          left: scope.headWidth / 2,
          bottom: config.blurRadius * (14 / 6)
        });
        
        scope.tailClip = clip({
          top: -config.blurRadius,
          left: 0 - config.blurRadius,
          right: scope.tailWidth / 2,
          bottom: config.blurRadius * (14 / 6)
        });
        
        scope.headRight = 0;
        scope.tailRight = -(scope.tailWidth - scope.headWidth) / 2;
      }, true);
    }
  };
});