我对AngularJS和Javascript还是很陌生,但是我设法将一个自定义的camera指令放到一起,以我想要的方式工作。它使我可以从可用的照相机列表中选择照相机,拍摄快照,显示所拍摄的照片并具有用于保存照片或关闭照片的按钮。问题是,当我将路由添加到应用程序时,单击按钮将不再发生任何事情。所以我的问题是,与应用程序一起使用路由时,如何使该指令像以前一样工作?
这是指令:
app.directive('camera', function () {
return {
template: '\
<div ng-show="showVideo">\
<div class="select">\
<label for="videoSource">Video source: </label><select id="videoSource"></select>\
</div>\
<video id="video" width="640" height="480" autoplay></video>\
<button id="snap">Snap Photo</button>\
</div>\
<div ng-show="showSnap">\
<canvas id="canvas" width="640" height="480"></canvas>\
<button id="save">Save Photo</button>\
<button id="cancel">Cancel</button>\
</div>',
link: function ($scope) {
$scope.showVideo = true;
$scope.showSnap = false;
var videoElement = document.querySelector('video');
var videoSelect = document.querySelector('select#videoSource');
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
function gotSources(sourceInfos) {
for (var i = 0; i !== sourceInfos.length; ++i) {
var sourceInfo = sourceInfos[i];
var option = document.createElement('option');
option.value = sourceInfo.id;
if (sourceInfo.kind === 'video') {
option.text = sourceInfo.label || 'camera ' + (videoSelect.length + 1);
videoSelect.appendChild(option);
} else {
console.log('Some other kind of source: ', sourceInfo);
}
}
}
if (typeof MediaStreamTrack === 'undefined') {
alert('This browser does not support MediaStreamTrack.\n\nTry Chrome Canary.');
} else {
MediaStreamTrack.getSources(gotSources);
}
function successCallback(stream) {
window.stream = stream; // make stream available to console
videoElement.src = window.URL.createObjectURL(stream);
videoElement.play();
}
function errorCallback(error){
console.log('navigator.getUserMedia error: ', error);
}
function start(){
if (!!window.stream) {
videoElement.src = null;
window.stream.stop();
}
var videoSource = videoSelect.value;
var constraints = {
audio: false,
video: {
optional: [{sourceId: videoSource}]
}
};
navigator.getUserMedia(constraints, successCallback, errorCallback);
}
videoSelect.onchange = start;
start();
// Take snapshot example
// Put event listeners into place
window.addEventListener("DOMContentLoaded", function() {
// Grab elements, create settings, etc.
var canvas = document.getElementById("canvas"),
context = canvas.getContext("2d"),
video = document.getElementById("video"),
videoObj = { "video": true },
errBack = function(error) {
console.log("Video capture error: ", error.code);
};
// Trigger photo take
document.getElementById("snap").addEventListener("click", function() {
$scope.$apply(function () {
context.drawImage(video, 0, 0, 640, 480);
$scope.showVideo = false;
$scope.showSnap = true;
});
});
// Save photo
document.getElementById("save").addEventListener("click", function() {
$scope.$apply(function () {
var image = new Image();
image.src = canvas.toDataURL("image/jpg");
$scope.image = image.src;
console.log($scope.image);
$scope.showVideo = true;
$scope.showSnap = false;
//return image;
});
});
document.getElementById("cancel").addEventListener("click", function() {
$scope.$apply(function () {
$scope.showVideo = true;
$scope.showSnap = false;
});
});
}, false);
}
};
});
这是我的app.js:
var app = angular.module('cameraApp', ['ngRoute'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider .when('/', {
controller: 'CameraController',
templateUrl: 'views/app.html'
})
.when('/login', {
controller: 'LoginController',
templateUrl: 'views/login.html'
})
.otherwise({redirectTo: '/login'});
}]);
app.controller('MainController', function($scope, $window) {
console.log($window);
console.log($scope);
});
app.controller('LoginController', function($scope) {
});
app.controller('CameraController', function($scope) {
});
这是我的index.html:
<!DOCTYPE html>
<html lang="en" ng-app="cameraApp">
<head>
<meta charset="utf-8">
<title>AngularCameraApp</title>
<!--<link rel="stylesheet" href="style.css">-->
</head>
<body ng-controller="MainController">
<ul>
<li><a href="#/login">Login</a></li>
<li><a href="#/">App</a></li>
</ul>
<div ng-view></div>
<script src="js/lib/angular.min.js"></script>
<script src="js/lib/angular-route.min.js"></script>
<script src="js/app.js"></script>
<script src="js/directives.js"></script>
</body>
非常感谢您提供任何帮助!
我终于做到了。我需要在答案中提出三点:解决方案,问题,错误/建议。我先提出解决方案,然后再编辑以添加其他部分。请在更新后重新阅读我的答案。
解决方案
首先,您可以看到这个工作的柱塞
我将您的点击函数移动到$ scope变量中,如下所示:
$scope.snap = function() {
console.log("coucou");
var canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
context.drawImage(video, 0, 0, 640, 480);
$scope.showVideo = false;
$scope.showSnap = true;
}
// Save photo
$scope.save = function() {
var image = new Image();
image.src = canvas.toDataURL("image/jpg");
$scope.image = image.src;
console.log($scope.image);
$scope.showVideo = true;
$scope.showSnap = false;
}
$scope.cancel = function() {
$scope.showVideo = true;
$scope.showSnap = false;
}
在window.addEventListener(“ DOMContentLoaded”,function(){})之外
我在元素上添加了一些ng-click,以将其绑定到函数。
<button ng-click="save()">Save Photo</button>
这就是全部。
问题
现在的问题是,为什么仅在使用路由后才出现此错误?
您必须知道使用
window.addEventListener("DOMContentLoaded", function(){})
在AngularJS中不是一个好主意。
Angular将使用div加载第一页:index.html(在我的朋克中)
<ng-view></ng-view>
html文件完全加载后,上面的功能将启动。但是该页面实际上并没有完全构建。您的DOM实际上已完全加载,但是angular将使用其路由系统将app.html(在我的插件中)添加到ng-view元素中。
当window.addEventListener(“ DOMContentLoaded”,function(){})首次运行时,这三个按钮不存在。因此,没有添加clicks事件。
错误/建议
我看到了许多不应在angularJS中完成的事情。我会告诉你什么,以及应该如何做。
1-操作DOM
在angular中,您不需要从javascript处理DOM。如果要这样做,请记住,使用本机angular指令可以满足您的所有需求。
在角度上,您应该看不到:
document.getElementById("snap").addEventListener("click",
window.addEventListener("DOMContentLoaded",
videoSelect.appendChild(option);
document.createElement('option');
相反,您应该看到这种指令:
//To launch a function on a click/change/focus/blur etc...
<div ng-click="myfunction()"></div>
<input ng-model="myvar" ng-change="function()">
etc...
您可以在此简短的角度教程中找到所有需求
希望对您有帮助。
2-指令
指令的目的是向元素添加行为。在您的用例中,如果您不重复使用组件,那么重用指令是一个不错的选择,用它来制作指令并不是很有用。还请记住,自定义指令是虚假的朋友。大多数时候,您不需要他们以干净的方式做您想做的事情。
3-应用
在angular中,您只想尽可能地避免$ apply()。在某些情况下,它确实可以杀死性能,并且您90%的时间不需要它。
4-一种做自己想要的事的干净方法
我真的很想向您展示如何在插件中工作,但是要使您的指令适应整洁的方式,这需要太多的工作。这样,您应该将很多东西放到CameraService中(获取媒体流,启动它,停止它的功能等等),并且只需要将一些绑定绑定到您的控制器和HTML中就可以得到相同的结果。
另一种干净的方法是使用容器指令和一些指令在每个元素上添加所需的行为。但这需要对angularJS有一定的了解
希望对您有所帮助。如果您有任何问题,请随时提出。
编辑:回答评论中的问题
我将此添加到指令中。你可以看到它在这里工作
$scope.$on('$locationChangeStart', function(event) {
if (!!window.stream) {
videoElement.src = null;
window.stream.stop();
}
});
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句