I'm trying to pass a variable from a controller that controls my side menu drawer (based on https://github.com/driftyco/ionic-ion-drawer) to a directive of the content to be able to change opacity of content in proportion of how open is the side menu.
My first attempt was to do this getting with $scope.$watch the drawer.style.transport.translate3d using something like: How do I get the absolute value of translate3d? but without success so I change my way of doing to get a current variable used by the drawer controller.
the problem now is that looking the console watch is only fired one from 20 or 30 changes of the value outX. I've seen that in codepen is worst $watch never gets fired, but in my browser directly loaded from IntelliJ or my android device I see this on the log:
Starting drag
c_menu.js:166 Offset: 16
c_menu.js:227 48 16 32 -418
c_menu.js:227 49 16 33 -417
c_menu.js:227 50 16 34 -416
c_menu.js:227 51 16 35 -415
c_menu.js:227 52 16 36 -414
c_menu.js:227 54 16 38 -412
c_menu.js:227 55 16 39 -411
c_menu.js:227 56 16 40 -410
c_menu.js:227 57 16 41 -409
c_menu.js:227 58 16 42 -408
c_menu.js:227 59 16 43 -407
c_menu.js:227 61 16 45 -405
c_menu.js:227 62 16 46 -404
c_menu.js:227 63 16 47 -403
c_menu.js:227 64 16 48 -402
c_menu.js:227 65 16 49 -401
c_menu.js:227 66 16 50 -400
c_menu.js:227 68 16 52 -398
d_menu.js:62 -398
c_menu.js:227 67 16 51 -399
c_menu.js:227 68 16 52 -398
c_menu.js:227 69 16 53 -397
c_menu.js:227 70 16 54 -396
c_menu.js:227 71 16 55 -395
c_menu.js:227 72 16 56 -394
d_menu.js:62 -394
c_menu.js:227 73 16 57 -393
c_menu.js:227 75 16 59 -391
c_menu.js:227 76 16 60 -390
c_menu.js:227 77 16 61 -389
c_menu.js:227 78 16 62 -388
c_menu.js:227 79 16 63 -387
c_menu.js:227 80 16 64 -386
d_menu.js:62 -386
c_menu.js:227 82 16 66 -384
c_menu.js:227 83 16 67 -383
c_menu.js:227 84 16 68 -382
c_menu.js:227 85 16 69 -381
c_menu.js:227 86 16 70 -380
c_menu.js:227 87 16 71 -379
d_menu.js:62 -379
c_menu.js:227 87 16 71 -379
c_menu.js:227 86 16 70 -380
c_menu.js:227 85 16 69 -381
c_menu.js:227 84 16 68 -382
c_menu.js:227 83 16 67 -383
c_menu.js:227 81 16 65 -385
c_menu.js:227 80 16 64 -386
c_menu.js:227 79 16 63 -387
c_menu.js:227 78 16 62 -388
c_menu.js:227 77 16 61 -389
d_menu.js:62 -389
c_menu.js:227 76 16 60 -390
c_menu.js:227 74 16 58 -392
c_menu.js:227 75 16 59 -391
c_menu.js:227 76 16 60 -390
c_menu.js:227 77 16 61 -389
c_menu.js:227 78 16 62 -388
c_menu.js:227 79 16 63 -387
c_menu.js:227 80 16 64 -386
d_menu.js:62 -386
c_menu.js:191 End drag
A little version of what I'm trying to do can be found here: http://codepen.io/taquionbcn/pen/yYZmVY?editors=101 HTML
<link href="http://code.ionicframework.com/1.0.0/css/ionic.css" rel="stylesheet">
<script src="http://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
</head>
<body ng-app="myapp" >
<drawer side="left">
<ion-content>
<h2>Menu</h2>
<button ng-click="closeDrawer()">Close</button>
<ion-list>
<ion-item>Friends</ion-item>
<ion-item>Favorites</ion-item>
<ion-item>Search</ion-item>
</ion-list>
</ion-content>
</drawer>
<ion-pane>
<content>
<button ng-click="openDrawer()">Open</button>
</content>
</ion-pane>
</body>
</html>
AngularJS
var app = angular.module('myapp', ['ionic'])
//'use strict';
/**
* The ionic-contrib-frosted-glass is a fun frosted-glass effect
* that can be used in iOS apps to give an iOS 7 frosted-glass effect
* to any element.
*/
app.controller(
'drawerCtrl',
['$scope','$element', '$attrs', '$ionicGesture', '$document',
function($scope,$element, $attr, $ionicGesture, $document) {
var el = $element[0];
var dragging = false;
var startX, lastX, offsetX,newX;
$scope.outX = -1;
var side;
// How far to drag before triggering
var thresholdX = 15;
// How far from edge before triggering
var edgeX = 40;
var LEFT = 0;
var RIGHT = 1;
var isTargetDrag = false;
var width = $element[0].clientWidth;
var enableAnimation = function() {
$element.addClass('animate');
};
var disableAnimation = function() {
$element.removeClass('animate');
};
// Check if this is on target or not
var isTarget = function(el) {
while (el) {
if (el === $element[0]) {
return true;
}
el = el.parentNode;
}
};
var startDrag = function(e) {
disableAnimation();
dragging = true;
offsetX = lastX - startX;
console.log('Starting drag');
console.log('Offset:', offsetX);
};
var startTargetDrag = function(e) {
disableAnimation();
dragging = true;
isTargetDrag = true;
offsetX = lastX - startX;
console.log('Starting target drag');
console.log('Offset:', offsetX);
};
var doEndDrag = function(e) {
startX = null;
lastX = null;
offsetX = null;
isTargetDrag = false;
if (!dragging) {
return;
}
dragging = false;
console.log('End drag');
enableAnimation();
ionic.requestAnimationFrame(function() {
if ($scope.newX < (-width / 2)) {
el.style.transform = el.style.webkitTransform = 'translate3d(' + -width + 'px, 0, 0)';
} else {
el.style.transform = el.style.webkitTransform = 'translate3d(0px, 0, 0)';
}
});
};
var doDrag = function(e) {
if (e.defaultPrevented) {
return;
}
if (!lastX) {
startX = e.gesture.touches[0].pageX;
}
lastX = e.gesture.touches[0].pageX;
if (!dragging) {
// Dragged 15 pixels and finger is by edge
if (Math.abs(lastX - startX) > thresholdX) {
if (isTarget(e.target)) {
startTargetDrag(e);
} else if (startX < edgeX) {
startDrag(e);
}
}
} else {
//console.log(lastX, offsetX, lastX - offsetX);
newX = Math.min(0, (-width + (lastX - offsetX)));
$scope.outX =newX;
// console.log(lastX, offsetX, lastX - offsetX,newX);
ionic.requestAnimationFrame(function() {
el.style.transform = el.style.webkitTransform = 'translate3d(' + newX + 'px, 0, 0)';
});
}
if (dragging) {
e.gesture.srcEvent.preventDefault();
}
};
side = $attr.side == 'left' ? LEFT : RIGHT;
console.log(side);
$ionicGesture.on('drag', function(e) {
doDrag(e);
}, $document);
$ionicGesture.on('dragend', function(e) {
doEndDrag(e);
}, $document);
this.close = function() {
enableAnimation();
ionic.requestAnimationFrame(function() {
if (side === LEFT) {
el.style.transform = el.style.webkitTransform = 'translate3d(-100%, 0, 0)';
} else {
el.style.transform = el.style.webkitTransform = 'translate3d(100%, 0, 0)';
}
});
};
this.open = function() {
enableAnimation();
ionic.requestAnimationFrame(function() {
if (side === LEFT) {
el.style.transform = el.style.webkitTransform = 'translate3d(0%, 0, 0)';
} else {
el.style.transform = el.style.webkitTransform = 'translate3d(0%, 0, 0)';
}
});
};
}])
app.directive('drawer', ['$rootScope', '$ionicGesture', function($rootScope, $ionicGesture) {
return {
restrict: 'E',
controller: 'drawerCtrl',
link: function($scope, $element, $attr, ctrl) {
$element.addClass($attr.side);
$scope.openDrawer = function() {
console.log('open');
ctrl.open();
};
$scope.closeDrawer = function() {
console.log('close');
ctrl.close();
};
}
}
}]);
app.directive('drawerClose', ['$rootScope', function($rootScope) {
return {
restrict: 'A',
link: function($scope, $element) {
$element.bind('click', function() {
var drawerCtrl = $element.inheritedData('$drawerController');
drawerCtrl.close();
});
}
}
}]);
app.directive('content',[ function() {
return {
restrict: 'E',
//controller: 'contentCtrl',
scope: {
outX: '='
},
link: function ($scope, $element, $attr) {
console.log($scope);
console.log($element);
$element[0].style.opacity = 0.5;
$scope.$watch('outX',function(nv){
console.log($scope.outX);
//console.log($element);
//console.log($scope);
});
}
};
}]);
CSS
drawer {
display: block;
position: fixed;
width: 270px;
height: 100%;
z-index: 100;
background: #ffffff;
}
drawer.animate {
-webkit-transition: 0.4s all ease-in-out;
transition: 0.4s all ease-in-out;
}
drawer.left {
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
box-shadow: 1px 0px 10px rgba(0,0,0,0.3);
}
drawer.right {
right: 0;
top: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
box-shadow: -1px 0px 10px rgba(0,0,0,0.3);
}
EDIT:
After some time I've come back to this topic and know with more knowledge on ionic, angular and all this stuff I've made some approaches.
for the dark screen, because I will have multiple side menus, and windows I've decided to use at the body in parallel to the side menu and ion-nav-view:
<darkscreen class="darkscreen" id="iddarkscreen"></darkscreen>
with its directive:
menu.directive('darkscreen',function(){
return{
restrict: 'E',
link : function($scope,$element,$attr){
console.log(arguments)
},
controller: function($scope,$interval,operativeDB){
console.log(arguments);
var iddarkscreen = document.getElementById("iddarkscreen");
$scope.getdarkvalue = function(){
//console.log(JSON.stringify(operativeDB.getmov()));
return operativeDB.getdark();
};
$scope.$watch($scope.getdarkvalue,function(newVal){
if(newVal > 0) iddarkscreen.style.visibility = 'visible'; else iddarkscreen.style.visibility = 'hidden';
},true);
}
}
});
and css:
.darkscreen {
z-index: 50;
background-color: black;
position: absolute;
height: 100%;
width: 100%;
opacity: .7;
transition: opacity 300ms ease-in-out;
}
next step is to modify the z-index param from the getdarkvalue function to always be under the objective and mask the rest. and the last step is to make the opacity progressive