使用 Canvas 和 ForEach 处理异步调用
Handling Async Calls with Canvas and ForEach
我想了解如何利用 angular 的 $q 库来显示基于 canvas 绘图然后使用 .toDataURL()
;[= 转换的图像18=]
基本上我想:
- 循环图像 (
$scope.targetImages
)
- 将它们画在 canvas
上
- 使用
.toDataURL()
将它们转换为图像并将其存储在 ($scope.outputImages
);
- 使用 ng-repeat 显示图像
问题是,函数 .toDataURL() 在执行之前可能需要一些时间,因此导致第 4 步的延迟调用,因此没有任何显示。
我尝试了以下方法,但在所有图像转换之前它仍然解决了。
就像我现在这样,当我第二次调用 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
并显示为:
<img ng-show="!previewMode" ng-src="{{image.dataURL || ''}}" style="width: 100vw; max-width: 600px;">
首先,定义一个将图像绘制到 canvas 和 returns 结果承诺的函数:
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());
};
});
}
那么解就变成了:
$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
});
为简化起见,我已将 $scope.targetImages
和 $scope.outputImages
更改为数组而不是对象,但如果您需要的话,返回为它们使用对象应该不会太难.
我想了解如何利用 angular 的 $q 库来显示基于 canvas 绘图然后使用 .toDataURL()
;[= 转换的图像18=]
基本上我想:
- 循环图像 (
$scope.targetImages
) - 将它们画在 canvas 上
- 使用
.toDataURL()
将它们转换为图像并将其存储在 ($scope.outputImages
); - 使用 ng-repeat 显示图像
问题是,函数 .toDataURL() 在执行之前可能需要一些时间,因此导致第 4 步的延迟调用,因此没有任何显示。
我尝试了以下方法,但在所有图像转换之前它仍然解决了。
就像我现在这样,当我第二次调用 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
并显示为:
<img ng-show="!previewMode" ng-src="{{image.dataURL || ''}}" style="width: 100vw; max-width: 600px;">
首先,定义一个将图像绘制到 canvas 和 returns 结果承诺的函数:
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());
};
});
}
那么解就变成了:
$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
});
为简化起见,我已将 $scope.targetImages
和 $scope.outputImages
更改为数组而不是对象,但如果您需要的话,返回为它们使用对象应该不会太难.