2013-10-19 34 views
32

Ho un problema con un esempio molto semplice con AngularJS e le direttive. Voglio creare una direttiva che mostri un'immagine della webcam con webrtc. Il mio codice mostrano il flusso perfettamente, ma se si aggiunge un timeout (ad esempio per aggiornare una tela) il $ timeout non funzionano questo è il codice:

wtffDirectives.directive('scannerGun',function($timeout){ 
    return { 
     restrict: 'E', 
     template: '<div>' + 
      '<video ng-hide="videoStatus"></video>' + 
      '<canvas id="canvas-source"></canvas>' +    
      '</div>', 
     replace: true, 
     transclude: true, 
     scope: false, 
     link: function postLink($scope, element){ 
      $scope.canvasStatus = true; 
      $scope.videoStatus = false; 

      width = element.width = 320; 
      height = element.height = 0; 

      /* this method draw the webcam image into a canvas */ 
      var drawVideoCanvas = function(){ 
       sourceContext.drawImage(vid,0,0, vid.width, vid.height); 
      }; 

      /* start the timeout that take a screenshot and draw the source canvas */ 
      var update = function(){ 
       var timeout = $timeout(function(){ 
       console.log("pass"); //the console log show only one "pass" 
       //drawVideoCanvas(); 
       }, 2000); 
      }; 

      /* this work perfectly and reproduct into the video tag the webcam */ 
      var onSuccess = function onSuccess(stream) { 
       // Firefox supports a src object 
       if (navigator.mozGetUserMedia) { 
       vid.mozSrcObject = stream; 
       } else { 
       var vendorURL = window.URL || window.webkitURL; 
       vid.src = vendorURL.createObjectURL(stream); 
       } 
       /* Start playing the video to show the stream from the webcam*/ 
       vid.play(); 
       update(); 
      }; 

      var onFailure = function onFailure(err) { 

       if (console && console.log) { 
       console.log('The following error occured: ', err); 
       } 
       return; 
      }; 

      var vid = element.find('video')[0]; 
      var sourceCanvas = element.find('canvas')[0]; 
      var sourceContext = sourceCanvas.getContext('2d'); 

      height = (vid.videoHeight/((vid.videoWidth/width))) || 250; 
      vid.setAttribute('width', width); 
      vid.setAttribute('height', height); 

      navigator.getMedia (
       // ask only for video 
       { 
       video: true, 
       audio: false 
       }, 
       onSuccess, 
       onFailure 
      ); 
     } 
     } 
    }); 

Qual è il problema? perché il timeout $ non funziona in queste condizioni? e finalmente avere una soluzione?

di ringraziamento in anticipo

risposta

14

Nel codice tuo commento dice 'mostrare un solo 'passare''. Timeout esegue solo una volta, dopo il ritardo specificato.

Forse si desidera impostareInterval (se si è pre-angolare 1.2)/$ intervallo (nuovo a 1.2) che imposta una chiamata ricorrente. Ecco la versione setInterval:

var timeout = setInterval(function(){ 
    // do stuff 
    $scope.$apply(); 
}, 2000); 

ho incluso $ applicare a ricordare che dal momento che si tratta di un jQuery esterna chiamata è necessario indicare angolare per aggiornare il DOM (se si apportano modifiche appropriate). ($ Timeout essendo una versione angolare aggiorna automaticamente il DOM)

+0

Ufff dispiace perdere tempo .... questo è corretto !!! buona giornata – cingusoft

+2

Se stai usando la versione RC (1.2.x), considera l'uso di '$ interval' invece di' setInterval' e '$ scope. $ Apply'. '$ interval' si prenderà cura del refresh del DOM per te. –

5

Non sono sicuro se ho ottenuto il vostro dubbio qui, ma $timeout è più o meno la stessa cosa di funzione javascript pianura setTimeout, e si suppone eseguito solo una volta, al contrario come setInterval.

Se si utilizza Angular 1.2.0, modificare il servizio $timeout per $interval. Se altrimenti si è in versione 1.0, si può rendere ricorsivo:

var timeout; 
var update = function() { 
    // clear previous interval 
    timeout && timeout(); 
    timeout = $timeout(function() { 
    // drawSomething(...); 
    update(); 
    }, 2000); 
} 
+0

Ciao @CaioToON, questo è quello che ho fatto e ora funziona come un fascino. Ho confuso $ timeout con $ intervallo. – cingusoft

+0

'$ timeout' e' setTimeout' di javascript ha una differenza - '$ timeout' viene eseguito all'interno del ciclo' $ digest' (non è necessario chiamare la funzione '$ apply' per applicare le modifiche nel modello). E naturalmente '$ timeout' si tradurrà in una promessa. –

+0

Timeout ha anche una proprietà interessante, se impostata senza intervallo di timeout, funge da ritardo per attendere che il DOM abbia eseguito il rendering. –

74

è possibile iniettare le dipendenze alla direttiva, come in altri moduli:

.directive('myDirective', ['$timeout', function($timeout) { 
    return { 
     ... 
     link: function($scope, element){ 
      //use $timeout 
     } 
    }; 
}]); 
+3

Per chiunque copi, non è necessario il '=' –