Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
265 views
in Technique[技术] by (71.8m points)

javascript - updating a {{ variable }} in my directive template

I don't think I am understanding how to set a {{ variable }} in my directive template correctly. The only way I can manage to update it is by calling $scope.$apply() and all I am trying to do is update my current-time text for a video player.

You can find my fiddle here using $scope.$apply() http://jsfiddle.net/ntdyp4oe/

This is currently my directive and I am wondering if I can update {{ currentTime }} without having to use $scope.$apply()

angular.module('canvas-video',[]).directive('canvasVideo', function($compile)
{
  return {
    restrict: 'E',
    replace:true,
    template:['',
      '<div id="canvas-video">',
        '<canvas id="canvas" ng-click="togglePlayback()" width="{{ width }}" height="{{ height }}"></canvas>',
        '<video src="{{ src }}" id="player"></video>',
        '<div id="controls">',
          '<div class="transport"><input id="slider" type="range" min="0" max="100" value="0" step="1"></div>',
          '<span class="current-time">{{ currentTime }}</span> | <span class="total-time">{{ totalTime }}</span>',
        '</div>',
      '</div>'
    ].join(''),
    scope: {
      src: '=',
      width: '=',
      height: '=',
      autoplay: '=?'
    },
    compile: function(element, attributes)
    {
      return {
        pre: function(scope, element, attributes)
        {
          if (!attributes.autoplay) attributes.autoplay = true;
          scope.currentTime = '00:00:00';
          scope.totalTime   = '00:00:00';
        },
        post: function(scope, element, attributes)
        {

        }
      }
    },
    controller: function($scope, $element, $attrs)
    {
      var canvas      = angular.element('canvas')[0];
      var ctx         = canvas.getContext('2d');
      var player      = angular.element('video')[0];
      player.autoplay = ($attrs.autoplay == 'false') ? 0 : 1;

      $scope.togglePlayback = function()
      {
        (player.paused) ? player.play() : player.pause();
      };

      $scope.renderPlayer = function()
      {
        var $this = this;
        $attrs.width = player.videoWidth;
        $attrs.height = player.videoHeight;
        canvas.setAttribute('width', $attrs.width);
        canvas.setAttribute('height', $attrs.height);
        $scope.totalTime = $scope.timecode(player.duration);

        (function loop()
        {
          if (!$this.paused && !$this.ended)
          {
            ctx.drawImage($this, 0,0, $attrs.width, $attrs.height);
            window.requestAnimationFrame(loop);
          }
        })();
      };

      //-- here is the function calling $apply a bunch and
      //-- wont update without it
      $scope.renderTime = function()
      {
        $scope.$apply(function()
        {
          $scope.currentTime = $scope.timecode(player.currentTime);
        });
      };

      $scope.timecode = function(seconds)
      {
        var minutes          = Math.floor(seconds/60);
        var remainingSec     = seconds % 60;
        var remainingMinutes = minutes % 60;
        var hours            = Math.floor(minutes/60);
        var floatSeconds     = Math.floor((remainingSec - Math.floor(remainingSec)) * 100);
        remainingSec         = Math.floor(remainingSec);
        return $scope.getTwoDigits(hours) + ":" + $scope.getTwoDigits(remainingMinutes) + ":" + $scope.getTwoDigits(remainingSec);
      };

      $scope.getTwoDigits = function(number)
      {
        return (number < 10) ? "0" + number : number;
      };

      player.addEventListener('timeupdate', $scope.renderTime);
      player.addEventListener('play', $scope.renderPlayer);
    }
  }
});
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You do need to use $apply() for events that change the scope that are outside of angular core in order to let angular know to run a view digest

For events managed by core directives such as ng-click , $apply() is called internally.

Your DOM listeners are not within such a directive. You can also use $timeout to avoid collisions with digest in progress errors occurring.

$timeout will defer calling $apply itself internally if digests are in progress


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...