简体   繁体   English

使用Canvas和ForEach处理异步呼叫

[英]Handling Async Calls with Canvas and ForEach

I am trying to understand how I can utilize angular's $q library to display images which are based on a canvas drawing and then converted using .toDataURL() ; 我试图了解如何利用angular的$ q库显示基于画布绘图的图像,然后使用.toDataURL()进行转换;

Basically I want to: 基本上我想:

  1. Loop over a images ( $scope.targetImages ) 循环$scope.targetImages图像( $scope.targetImages
  2. Draw them on a canvas 画在画布上
  3. Convert them to images using .toDataURL() and store it in ( $scope.outputImages ); 使用.toDataURL()将它们转换为图像,并将其存储在( $scope.outputImages );中。
  4. Display the images using ng-repeat 使用ng-repeat显示图像

The problem is, that the function .toDataURL() can take some time before executed, thus resulting in a delayed call of step 4, and thus nothing being displayed. 问题在于,函数.toDataURL()在执行之前可能需要花费一些时间,从而导致步骤4的延迟调用,因此什么也不显示。

I have tried the following, but it still resolves before all the images are converted. 我尝试了以下方法,但是在转换所有图像之前仍可以解决。

As I have it now, when I call drawCanvas () for the second time, then the images are shown. 现在,当我第二次调用drawCanvas ()时,将显示图像。

    // 1
    $scope.targetImages= {}

    drawCanvas().then(function(data){
      console.log("done: " + new Date())
      console.log(data)
      $scope.outputImages = data;
      $scope.previewMode = false; // switch views, display canvas, remove preview
    });


    function drawCanvas() {

    var defer = $q.defer();

    var targetImages = {} 
    angular.forEach($scope.targetImages , function(imageObj, key) {

      var canvas = document.getElementById("canvas");
      var ctx = canvas.getContext("2d");
      var img = new Image();
      img.src = imageObj.nativeURL;
      img.onload = start

      // 2
      function start() {

        ctx.drawImage(img, 0, 0, img.width, img.height);

        outputImages[key] = {
          IID: key,
          dataURL: canvas.toDataURL()
        }

      } // start

    }); // for loop target images

    defer.resolve(outputImages);
    return defer.promise;

    } // draw canvas

And displayed as: 并显示为:

<img ng-show="!previewMode" ng-src="{{image.dataURL || ''}}" style="width: 100vw; max-width: 600px;">

First, define a function that draws an image to the canvas and returns a promise for the result: 首先,定义一个将图像绘制到画布上并返回结果承诺的函数:

function drawToCanvas(nativeURL) {
    return $q(function (resolve) {
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var img = new Image();

        img.src = nativeURL;
        img.onload = function () {
            ctx.drawImage(img, 0, 0, img.width, img.height);

            resolve(canvas.toDataURL());
        };
    });
}

The solution then becomes: 然后,解决方案变为:

$scope.targetImages = [];

function drawCanvas() {
    // pResults is an array of promises
    var pResults = $scope.targetImages.map(function (imageObj) {
        return drawToCanvas(imageObj.nativeURL);
    });

    return $q.all(pResults);
}

drawCanvas().then(function(data) {
    // data is an array of imageUrls
    console.log("done: " + new Date())
    console.log(data)
    $scope.outputImages = data;
    $scope.previewMode = false; 
    // switch views, display canvas, remove preview
});

To simplify, I have changed $scope.targetImages and $scope.outputImages to be arrays instead of objects, but it shouldn't be too hard to go back to using objects for them if that's what you need. 为简化起见,我已将$scope.targetImages$scope.outputImages更改为数组而不是对象,但是如果您需要的话,不难再回到为它们使用对象的角度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM