diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a59651..17b3386 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
-
-## v0.1.0 (2013-11-10)
+
+## v0.2.0 (2013-11-12)
+
+
+#### Features
+
+* **GruntFile:** add concated and uglified version ([92fecaed](https://github.com/angular-adaptive/adaptive-motion/commit/92fecaed4f0365b8987a0a848921447081bdc349))
+* **conventional-changelog:** adds grunt-conventional-changelog ([432cf774](https://github.com/angular-adaptive/adaptive-motion/commit/432cf7742466b7152250869b930b9627e1e53661))
+
+
+#### Breaking Changes
+
+* src/adaptive-motion.js is now renamed into src/angular-adaptive-motion.js
+ ([92fecaed](https://github.com/angular-adaptive/adaptive-motion/commit/92fecaed4f0365b8987a0a848921447081bdc349))
diff --git a/Gruntfile.js b/Gruntfile.js
index 6872031..124bb6e 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -1,42 +1,70 @@
module.exports = function (grunt) {
- require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
+ require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
- // Default task.
- grunt.registerTask('default', ['karma', 'jshint']);
+ // Default task.
+ grunt.registerTask('default', ['karma', 'jshint']);
+ grunt.registerTask('build', ['karma', 'jshint', 'concat', 'uglify']);
- var karmaConfig = function(configFile, customOptions) {
- var options = { configFile: configFile, keepalive: true };
- var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
- return grunt.util._.extend(options, customOptions, travisOptions);
- };
+ var karmaConfig = function(configFile, customOptions) {
+ var options = { configFile: configFile, keepalive: true };
+ var travisOptions = process.env.TRAVIS && { browsers: ['Firefox'], reporters: 'dots' };
+ return grunt.util._.extend(options, customOptions, travisOptions);
+ };
- // Project configuration.
- grunt.initConfig({
- karma: {
- unit: {
- options: karmaConfig('test/test.conf.js')
- }
- },
- jshint:{
- files:['src/**/*.js', 'test/**/*.js'],
- options: {
- curly:true,
- eqeqeq:true,
- immed:true,
- latedef:true,
- newcap:true,
- noarg:true,
- sub:true,
- boss:true,
- eqnull:true,
- devel:true,
- globals:{}
- }
- },
- changelog: {
- options: {
- dest: 'CHANGELOG.md'
- }
- }
- });
-}
+ // Project configuration.
+ grunt.initConfig({
+ pkg: grunt.file.readJSON('bower.json'),
+ meta: {
+ banner: '/*!\n' +
+ ' * <%= pkg.name %> v<%= pkg.version %>\n' +
+ ' * The MIT License\n' +
+ ' * Copyright (c) 2013 Jan Antala\n' +
+ ' */'
+ },
+ uglify: {
+ options: {
+ preserveComments: 'some'
+ },
+ dist: {
+ src: '<%= pkg.name %>.js',
+ dest: '<%= pkg.name %>.min.js'
+ }
+ },
+ concat: {
+ options: {
+ process: true,
+ banner: '<%= meta.banner %>\n\n'
+ },
+ dist: {
+ src: 'src/<%= pkg.name %>.js',
+ dest: '<%= pkg.name %>.js'
+ }
+ },
+ karma: {
+ unit: {
+ options: karmaConfig('test/test.conf.js')
+ }
+ },
+ jshint:{
+ files:['src/**/*.js', 'test/**/*.js'],
+ options: {
+ curly:true,
+ eqeqeq:true,
+ immed:true,
+ latedef:true,
+ newcap:true,
+ noarg:true,
+ sub:true,
+ boss:true,
+ eqnull:true,
+ devel:true,
+ globals:{}
+ }
+ },
+ changelog: {
+ options: {
+ dest: 'CHANGELOG.md'
+ }
+ },
+ });
+};
diff --git a/README.md b/README.md
index 1190b17..60bc0ab 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# adaptive-motion v0.1.0 [![Build Status](https://travis-ci.org/angular-adaptive/adaptive-motion.png?branch=master)](https://travis-ci.org/angular-adaptive/adaptive-motion)
+# adaptive-motion v0.2.0 [![Build Status](https://travis-ci.org/angular-adaptive/adaptive-motion.png?branch=master)](https://travis-ci.org/angular-adaptive/adaptive-motion)
This module allows you to control an AngularJS app using web camera.
@@ -25,8 +25,8 @@ To your `bower.json` file. Then run
This will copy the angular-adaptive-motion files into your `bower_components` folder, along with its dependencies. Load the script files in your application:
-
-
+
+
Add the **adaptive.motion** module as a dependency to your application module:
diff --git a/src/adaptive-motion.js b/angular-adaptive-motion.js
similarity index 99%
rename from src/adaptive-motion.js
rename to angular-adaptive-motion.js
index 5da1ba0..db6bd2c 100644
--- a/src/adaptive-motion.js
+++ b/angular-adaptive-motion.js
@@ -1,7 +1,7 @@
-/**
- * angular-adaptive-motion v0.1.0
+/*!
+ * angular-adaptive-motion v0.2.0
* The MIT License
- * Copyright (c) 2013 Jan Antala http://janantala.com
+ * Copyright (c) 2013 Jan Antala
*/
(function () {
diff --git a/angular-adaptive-motion.min.js b/angular-adaptive-motion.min.js
new file mode 100644
index 0000000..8933b57
--- /dev/null
+++ b/angular-adaptive-motion.min.js
@@ -0,0 +1,6 @@
+/*!
+ * angular-adaptive-motion v0.2.0
+ * The MIT License
+ * Copyright (c) 2013 Jan Antala
+ */
+!function(){"use strict";var a=angular.module("adaptive.motion",[]);!function(){for(var a=0,b=["webkit","moz"],c=0;cb?6:0);break;case b:d=(c-a)/i+2;break;case c:d=(a-b)/i+4}d/=6}return[d,e,h]};a.provider("$motion",[function(){var a,c=document.createElement("video");c.setAttribute("autoplay","true"),c.setAttribute("width","300");var d=document.createElement("canvas"),e=d.getContext("2d");this.treshold={rgb:150,move:2,bright:300},this.hsvFilter={huemin:0,huemax:.1,satmin:0,satmax:1,valmin:.4,valmax:1},this.setTreshold=function(a){angular.extend(this.treshold,a)},this.setHsvFilter=function(a){angular.extend(this.hsvFilter,a)},this.$get=function(f){var g,h,i,j=this.treshold,k=this.hsvFilter,l=5,m=0,n=0,o={x:0,y:0,d:0},p=function(){if(window.URL=window.URL||window.webkitURL,navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia,!navigator.getUserMedia)throw f.$broadcast("adaptive.motion:onError","getUserMedia() is not supported in your browser"),new Error("getUserMedia() is not supported in your browser");navigator.getUserMedia({audio:!1,video:!0},function(b){f.$broadcast("adaptive.motion:onStart"),h=b,c.src=window.URL.createObjectURL(b),c.addEventListener("play",function(){a=window.requestAnimationFrame(r)})},function(){throw f.$broadcast("adaptive.motion:onError","Access denied!"),new Error("Access denied!")})},q=function(){window.cancelAnimationFrame(a),h&&h.stop(),h=void 0,f.$broadcast("adaptive.motion:onStop")},r=function(){d.width!==c.videoWidth&&(m=Math.floor(c.videoWidth/l),n=Math.floor(c.videoHeight/l),d.width=m,d.height=n);try{e.drawImage(c,0,0,m,n),g=e.getImageData(0,0,m,n),f.$broadcast("adaptive.motion:videoData",g);var b=s(g);i=t(b),a=window.requestAnimationFrame(r)}catch(h){if("NScontextERRORcontextNOTcontextAVAILABLE"!==h.name)throw h;a=window.requestAnimationFrame(r)}},s=function(a){for(var c=e.getImageData(0,0,m,n),d=c.width*c.height,g=4*d,h=0,i=0;n>i;i++)for(var j=0;m>j;j++){g=j+i*m;var l=a.data[h],o=a.data[h+1],p=a.data[h+2],q=a.data[h+3],r=b(l,o,p);(r[0]>k.huemin&&r[0].59&&r[0]<1)&&r[1]>k.satmin&&r[1]k.valmin&&r[2]0;){var k=Math.abs(a.data[h]-i.data[h])+Math.abs(a.data[h+1]-i.data[h+1])+Math.abs(a.data[h+2]-i.data[h+2]);k>j.rgb?(b.data[h]=0,b.data[h+1]=0,b.data[h+2]=0,b.data[h+3]=255,g+=1,c+=h/4%m,d+=Math.floor(h/4/b.height)):(b.data[h]=255,b.data[h+1]=255,b.data[h+2]=255,b.data[h+3]=255)}if(g){f.$broadcast("adaptive.motion:edgeData",b);var l={x:c/g,y:d/g,d:g};x(l)}return a},u=function(a){o={x:a.x,y:a.y,d:a.d}},v=0,w=0,x=function(a){v=.9*v+.1*a.d;var b=a.d-v,c=b>j.bright;switch(w){case 0:c&&(w=1,u(a));break;case 2:c||(w=0);break;case 1:var d=a.x-o.x,e=a.y-o.y,g=Math.abs(e)j.move&&f.$broadcast("adaptive.motion:onSwipeLeft"):h&&(e>j.move?f.$broadcast("adaptive.motion:onSwipeDown"):e<-j.move&&f.$broadcast("adaptive.motion:onSwipeUp")),w=2}},y=function(a){f.$on("adaptive.motion:onStart",function(b,c){a(c)})},z=function(a){f.$on("adaptive.motion:onStop",function(b,c){a(c)})},A=function(a){f.$on("adaptive.motion:onError",function(b,c){a(c)})},B=function(a){f.$on("adaptive.motion:onSwipeLeft",function(b,c){a(c)})},C=function(a){f.$on("adaptive.motion:onSwipeRight",function(b,c){a(c)})},D=function(a){f.$on("adaptive.motion:onSwipeUp",function(b,c){a(c)})},E=function(a){f.$on("adaptive.motion:onSwipeDown",function(b,c){a(c)})};return{start:function(){p()},stop:function(){q()},onStart:function(a){y(a)},onStop:function(a){z(a)},onError:function(a){A(a)},onSwipeLeft:function(a){B(a)},onSwipeRight:function(a){C(a)},onSwipeUp:function(a){D(a)},onSwipeDown:function(a){E(a)}}}}]),a.directive("adaptiveMotion",["$rootScope",function(a){return{restrict:"A",link:function(b,c,d){var e=c[0],f=e.getContext("2d");"video"===d.adaptiveMotion?a.$on("adaptive.motion:videoData",function(a,b){f.putImageData(b,0,0)}):"skin"===d.adaptiveMotion?a.$on("adaptive.motion:skinData",function(a,b){f.putImageData(b,0,0)}):a.$on("adaptive.motion:edgeData",function(a,b){f.putImageData(b,0,0)})}}}])}();
\ No newline at end of file
diff --git a/bower.json b/bower.json
index d24cd6c..e00e1e2 100644
--- a/bower.json
+++ b/bower.json
@@ -1,11 +1,20 @@
{
"name": "angular-adaptive-motion",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "This module allows you to control an angular app using your body.",
"author": "https://github.com/angular-adaptive/adaptive-motion/graphs/contributors",
"license": "MIT",
+ "keywords": [
+ "angular",
+ "adaptive",
+ "motion"
+ ],
"homepage": "http://angular-adaptive.github.io",
- "main": "./src/adaptive-motion.js",
+ "main": "./src/angular-adaptive-motion.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular-adaptive/adaptive-motion.git"
+ },
"ignore": [
"**/.*",
"node_modules",
diff --git a/package.json b/package.json
index d8a1d7e..4afa90e 100644
--- a/package.json
+++ b/package.json
@@ -1,22 +1,29 @@
{
"name": "angular-adaptive-motion",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "This module allows you to control an angular app using your body.",
"author": "https://github.com/angular-adaptive/adaptive-motion/graphs/contributors",
"license": "MIT",
+ "keywords": [
+ "angular",
+ "adaptive",
+ "motion"
+ ],
"homepage": "http://angular-adaptive.github.io",
- "main": "./src/adaptive-motion.js",
+ "main": "./src/angular-adaptive-motion.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/angular-adaptive/adaptive-motion.git"
+ },
"dependencies": {},
"devDependencies": {
"grunt": "~0.4.1",
"grunt-karma": "*",
"grunt-contrib-jshint": "~0.2.0",
"grunt-conventional-changelog": "~1.0.0",
+ "grunt-contrib-uglify": "~0.2.2",
+ "grunt-contrib-concat": "~0.3.0",
"matchdep": "~0.3.0"
},
- "scripts": {},
- "repository": {
- "type": "git",
- "url": "git://github.com/angular-adaptive/adaptive-motion.git"
- }
+ "scripts": {}
}
diff --git a/src/angular-adaptive-motion.js b/src/angular-adaptive-motion.js
new file mode 100644
index 0000000..8ea019d
--- /dev/null
+++ b/src/angular-adaptive-motion.js
@@ -0,0 +1,446 @@
+(function () {
+'use strict';
+
+var adaptive = angular.module('adaptive.motion', []);
+
+// RequestAnimationFrame fallback
+(function() {
+ var lastTime = 0;
+ var vendors = ['webkit', 'moz'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelAnimationFrame =
+ window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame) {
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+ }
+
+ if (!window.cancelAnimationFrame) {
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+ }
+}());
+
+/**
+ * Converts rgb into hsv
+ * @param {Integer} r
+ * @param {Integer} g
+ * @param {Integer} b
+ * @return {Array}
+ */
+var rgb2Hsv = function(r, g, b){
+
+ r = r/255;
+ g = g/255;
+ b = b/255;
+
+ var max = Math.max(r, g, b);
+ var min = Math.min(r, g, b);
+
+ var h, s, v = max;
+
+ var d = max - min;
+
+ s = max === 0 ? 0 : d / max;
+
+ if (max === min){
+ h = 0; // achromatic
+ }
+ else{
+ switch(max){
+ case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+ case g: h = (b - r) / d + 2; break;
+ case b: h = (r - g) / d + 4; break;
+ }
+ h /= 6;
+ }
+
+ return [h, s, v];
+};
+
+adaptive.provider('$motion', [function() {
+
+ var requestId;
+ var video = document.createElement('video');
+ video.setAttribute('autoplay', 'true');
+ video.setAttribute('width', '300');
+ var canvas = document.createElement('canvas');
+ var context = canvas.getContext('2d');
+
+ this.treshold = {
+ 'rgb': 150,
+ 'move': 2,
+ 'bright': 300
+ };
+
+ this.hsvFilter = {
+ 'huemin': 0.0,
+ 'huemax': 0.1,
+ 'satmin': 0.0,
+ 'satmax': 1.0,
+ 'valmin': 0.4,
+ 'valmax': 1.0
+ };
+
+ this.setTreshold = function(treshold) {
+ angular.extend(this.treshold, treshold);
+ };
+
+ this.setHsvFilter = function(hsvFilter) {
+ angular.extend(this.hsvFilter, hsvFilter);
+ };
+
+ this.$get = function($rootScope) {
+
+ var treshold = this.treshold;
+ var hsvFilter = this.hsvFilter;
+
+ var compression = 5;
+ var width = 0;
+ var height = 0;
+
+ var draw;
+ var localMediaStream;
+
+ var lastDraw;
+ var lastDown = {
+ x: 0,
+ y: 0,
+ d: 0
+ };
+
+ var start = function(){
+
+ window.URL = window.URL || window.webkitURL;
+ navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
+
+ if (navigator.getUserMedia) {
+ navigator.getUserMedia({audio: false, video: true},
+ function(stream){
+ $rootScope.$broadcast('adaptive.motion:onStart');
+ localMediaStream = stream;
+ video.src = window.URL.createObjectURL(stream);
+ video.addEventListener('play', function() {
+ requestId = window.requestAnimationFrame(redraw);
+ });
+ },
+ function(){
+ $rootScope.$broadcast('adaptive.motion:onError', 'Access denied!');
+ throw new Error('Access denied!');
+ }
+ );
+ }
+ else {
+ $rootScope.$broadcast('adaptive.motion:onError', 'getUserMedia() is not supported in your browser');
+ throw new Error('getUserMedia() is not supported in your browser');
+ }
+ };
+
+ var stop = function(){
+ window.cancelAnimationFrame(requestId);
+ if (localMediaStream) {
+ localMediaStream.stop();
+ }
+ localMediaStream = undefined;
+ $rootScope.$broadcast('adaptive.motion:onStop');
+ };
+
+ var redraw = function() {
+ if (canvas.width !== video.videoWidth){
+ width = Math.floor(video.videoWidth / compression);
+ height = Math.floor(video.videoHeight / compression);
+ canvas.width = width;
+ canvas.height = height;
+ }
+
+ try {
+ context.drawImage(video,0,0,width,height);
+ draw = context.getImageData(0, 0, width, height);
+ $rootScope.$broadcast('adaptive.motion:videoData', draw);
+ var skinFilter = filterSkin(draw);
+ lastDraw = getMovements(skinFilter);
+
+ requestId = window.requestAnimationFrame(redraw);
+ }
+ catch (e) {
+ if (e.name === 'NScontextERRORcontextNOTcontextAVAILABLE') {
+ requestId = window.requestAnimationFrame(redraw);
+ }
+ else {
+ throw e;
+ }
+ }
+ };
+
+ /**
+ * Filters skin from video image data
+ * @param {ImageData} video
+ * @return {ImageData}
+ */
+ var filterSkin = function(video){
+
+ var skinFilter = context.getImageData(0,0,width,height);
+ var totalPixels = skinFilter.width * skinFilter.height;
+ var index = totalPixels * 4;
+
+ var pix = 0;
+ for (var y=0; y 0.59 && hsv[0] < 1.0)
+ //Skin Range on HSV values
+ if(((hsv[0] > hsvFilter.huemin && hsv[0] < hsvFilter.huemax)||(hsv[0] > 0.59 && hsv[0] < 1.0))&&(hsv[1] > hsvFilter.satmin && hsv[1] < hsvFilter.satmax)&&(hsv[2] > hsvFilter.valmin && hsv[2] < hsvFilter.valmax)){
+ skinFilter[pix] = r;
+ skinFilter[pix+1] = g;
+ skinFilter[pix+2] = b;
+ skinFilter[pix+3] = a;
+ }
+ else{
+ skinFilter.data[pix] = 255;
+ skinFilter.data[pix+1] = 255;
+ skinFilter.data[pix+2] = 255;
+ skinFilter.data[pix+3] = 255;
+ }
+
+ pix = index * 4;
+ }
+ }
+ $rootScope.$broadcast('adaptive.motion:skinData', skinFilter);
+ return skinFilter;
+ };
+
+ /**
+ * Gets movement data
+ * @param {ImageData} draw
+ * @return {ImageData}
+ */
+ var getMovements = function(draw){
+ var edge = context.createImageData(width, height);
+ var totalx = 0;
+ var totaly = 0;
+ var changed = 0;
+ var pix = edge.width * edge.height * 4;
+
+ if (lastDraw){
+
+ while ((pix -= 4) > 0) {
+ var rgbaDelta = Math.abs(draw.data[pix] - lastDraw.data[pix]) +
+ Math.abs(draw.data[pix+1] - lastDraw.data[pix+1]) +
+ Math.abs(draw.data[pix+2] - lastDraw.data[pix+2]);
+
+ if (rgbaDelta > treshold.rgb){
+ edge.data[pix] = 0;
+ edge.data[pix+1] = 0;
+ edge.data[pix+2] = 0;
+ edge.data[pix+3] = 255;
+ changed += 1;
+ totalx += (pix/4) % width;
+ totaly += Math.floor((pix/4) / edge.height);
+ }
+ else {
+ edge.data[pix] = 255;
+ edge.data[pix+1] = 255;
+ edge.data[pix+2] = 255;
+ edge.data[pix+3] = 255;
+ }
+ }
+ }
+
+ if (changed){
+ $rootScope.$broadcast('adaptive.motion:edgeData', edge);
+
+ var down = {
+ x: totalx / changed,
+ y: totaly / changed,
+ d: changed
+ };
+ recognizeGesture(down);
+ }
+
+ return draw;
+ };
+
+ /**
+ * Sets last down
+ * @param {Object} down
+ */
+ var setLastDown = function(down){
+ lastDown = {
+ x: down.x,
+ y: down.y,
+ d: down.d
+ };
+ };
+
+ var avg = 0;
+ var state = 0; //States: 0 waiting for gesture, 1 waiting for next move after gesture, 2 waiting for gesture to end
+
+ /**
+ * Recognizes gesture
+ * @param {Object} down
+ */
+ var recognizeGesture = function(down){
+ avg = 0.9 * avg + 0.1 * down.d;
+ var davg = down.d - avg;
+ var foundGesture = davg > treshold.bright;
+
+ switch (state){
+ case 0:
+ if (foundGesture){ //Found a gesture, waiting for next move
+ state = 1;
+ setLastDown(down);
+ }
+ break;
+ case 2: //Wait for gesture to end
+ if (!foundGesture){ //Gesture ended
+ state = 0;
+ }
+ break;
+ case 1: //Got next move, do something based on direction
+ var dx = down.x - lastDown.x;
+ var dy = down.y - lastDown.y;
+ var dirx = Math.abs(dy) < Math.abs(dx) - treshold.move;
+ var diry = Math.abs(dx) < Math.abs(dy) - treshold.move;
+ // console.log(dx, dy, dirx);
+
+ if (dirx) {
+ if (dx < - treshold.move){
+ $rootScope.$broadcast('adaptive.motion:onSwipeRight');
+ }
+ else if (dx > treshold.move){
+ $rootScope.$broadcast('adaptive.motion:onSwipeLeft');
+ }
+ }
+ else if (diry) {
+ if (dy > treshold.move){
+ $rootScope.$broadcast('adaptive.motion:onSwipeDown');
+ }
+ else if (dy < - treshold.move){
+ $rootScope.$broadcast('adaptive.motion:onSwipeUp');
+ }
+ }
+
+ state = 2;
+ break;
+ }
+ };
+
+ var onStart = function(cb){
+ $rootScope.$on('adaptive.motion:onStart', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onStop = function(cb){
+ $rootScope.$on('adaptive.motion:onStop', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onError = function(cb){
+ $rootScope.$on('adaptive.motion:onError', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onSwipeLeft = function(cb){
+ $rootScope.$on('adaptive.motion:onSwipeLeft', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onSwipeRight = function(cb){
+ $rootScope.$on('adaptive.motion:onSwipeRight', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onSwipeUp = function(cb){
+ $rootScope.$on('adaptive.motion:onSwipeUp', function(e, data){
+ cb(data);
+ });
+ };
+
+ var onSwipeDown = function(cb){
+ $rootScope.$on('adaptive.motion:onSwipeDown', function(e, data){
+ cb(data);
+ });
+ };
+
+ return {
+ start: function(){
+ start();
+ },
+ stop: function(){
+ stop();
+ },
+ onStart: function(cb){
+ onStart(cb);
+ },
+ onStop: function(cb){
+ onStop(cb);
+ },
+ onError: function(cb){
+ onError(cb);
+ },
+ onSwipeLeft: function(cb){
+ onSwipeLeft(cb);
+ },
+ onSwipeRight: function(cb){
+ onSwipeRight(cb);
+ },
+ onSwipeUp: function(cb){
+ onSwipeUp(cb);
+ },
+ onSwipeDown: function(cb){
+ onSwipeDown(cb);
+ }
+ };
+ };
+}]);
+
+adaptive.directive('adaptiveMotion', ['$rootScope', function ($rootScope) {
+ return {
+ restrict: 'A',
+ link: function postLink(scope, element, attrs) {
+ var canvas = element[0];
+ var context = canvas.getContext('2d');
+
+ if (attrs['adaptiveMotion'] === 'video'){
+ $rootScope.$on('adaptive.motion:videoData', function(e, data){
+ context.putImageData(data, 0, 0);
+ });
+ }
+ else if (attrs['adaptiveMotion'] === 'skin'){
+ $rootScope.$on('adaptive.motion:skinData', function(e, data){
+ context.putImageData(data, 0, 0);
+ });
+ }
+ else {
+ $rootScope.$on('adaptive.motion:edgeData', function(e, data){
+ context.putImageData(data, 0, 0);
+ });
+ }
+ }
+ };
+}]);
+
+})();
\ No newline at end of file
diff --git a/test/test.conf.js b/test/test.conf.js
index 6734b50..c4cb038 100644
--- a/test/test.conf.js
+++ b/test/test.conf.js
@@ -4,7 +4,7 @@ module.exports = function(config) {
files: [
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
- 'src/adaptive-motion.js',
+ 'src/angular-adaptive-motion.js',
'test/*.spec.js'
],
frameworks: ['jasmine'],