我有一系列需要以同步顺序执行的功能。其中一个功能是使用用户手机上的Cordova Camera库获取图片。另一个函数接受图像源并将其绘制在DOM中。
我使用Angular promises和$ q库来处理同步执行。但是,它似乎以某种方式导致在按顺序执行函数时不更新DOM,即使图像已成功捕获并且我有url(ImageData)。
为了测试,我添加了一个函数,该函数使用从手机捕获图像时保存的URL在DOM上绘制图像。这确实有效。因此,使用我的Angular Promise并处理它一定存在问题。
我该如何解决这个问题?
控制器($ q注入)
var sGetImage = function() {
var imageSrcOutput = "";
$scope.imageDataSrc = null;
try {
imageSrcOutput = CloakService.getImageData()
.then(function(imageData) {
//$scope.imageData = imageData;
$scope.imageDataSrc = "data:image/jpeg;base64," + imageData;
//$scope.imgURI = $scope.imageDataSrc;
return "data:image/jpeg;base64," + imageData;
});
// catch any errors with a struddle image
} catch (error) {
window.alert("No Image Picked. Drawing Struddle");
imageSrcOutput = "img/struddle.jpg";
$scope.imageDataSrc = imageSrcOutput;
}
return imageSrcOutput;
}
var sDrawImage = function(imageSrc) {
var deferred = $q.defer();
deferred.resolve(imageSrc)
window.alert("drawing image now with: " + imageSrc)
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imageSrc;
img.onload = ctx.drawImage(img, 0, 0);
return deferred.promise;
}
//执行周期(在控制器中)
sInit() // works fine
.then( sGetImage ) // image loaded in imageSrcOutput and $scope.imageDataSrc succesfully
.then( sDrawImage ) // here is the problem, it does not draw the images (tried both imageSrcOutput and $scope.imageDataSrc)
.then( sAddBanner )
.catch(function(error) {
window.alert("Catch Error: " + error)
})
服务($ cordovaCamera注入)
var getImageData = function() {
var deferred = $q.defer();
var options = getOptions('CAMERA');
var imageDataOutput = $cordovaCamera.getPicture(options).then(function(imageData) {
// window.alert(imageData)
deferred.resolve(imageData)
return imageData; //todo:check
}, function(error) {
deferred.reject(error)
window.alert(error)
});
function getOptions(source) {
var options = {
quality: 75,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: true
};
return options;
}
return deferred.promise;
//return imageDataOutput;
}
app.js
'use strict';
angular.module('myApp', [
'ionic',
'myApp.config',
'myApp.controllers',
'myApp.decorators',
'myApp.directives',
'myApp.filters',
'myApp.routes',
'myApp.services',
'angular-loading-bar',
'ngCordova' // the library to handle the picture
])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
})
答案 0 :(得分:1)
这是问题所在:
img.onload=ctx.drawImage(img, 0, 0);
onload
处理程序需要是一个函数。您正在立即执行ctx.drawImage()
。
试试这个:
img.onload = function () { ctx.drawImage(img, 0, 0); };
仅供参考,您在$q.defer()
(以及其他地方)使用sDrawImage
所做的事情是不必要的。如果您想将imageSrc
传递给下一步,您可以这样做:
var sDrawImage = function(imageSrc) {
window.alert("drawing image now with: " + imageSrc)
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = imageSrc;
return $q(function (resolve) {
img.onload = function () {
ctx.drawImage(img, 0, 0);
resolve(imageSrc);
};
});
};
每当你想到使用$q.defer()
时,你应该问自己“我真的需要这个吗?”。 99.5%的时间,答案应该是“不”。