angular ng-class appending classes does not trigger css3 transition - angularjs

I have created custom modal directive in angular but it seems transition is not working and i can't figure out why.
Inside my directive isolated scope i have method toggleModal() which is switching modalState to true / false. So everything is basically working except animation
HTML:
<span class="glyphicon glyphicon-edit" ng-click="toggleModal()"></span>
<div class="annotation-panel"
ng-class="{'annotation-panel-active' : modalState == true, 'annotation-panel-inactive' : modalState == false}">
<div class="annotation-modal" ng-class="{'active':modalState == true, 'inactive':modalState == false}">
<button type="button" class="btn btn-default" ng-click="toggleModal()">Close</button>
</div>
</div>
CSS:
.annotation-panel{
display: none;
position: fixed;
top:0;
left:0;
z-index: 1000;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
}
.annotation-panel-active{
display: block!important;
}
.annotation-panel-inactive{
display: none!important;
}
.annotation-modal{
position: fixed;
z-index: 1001;
left:10vw;
top: 0;
width: 80vw;
height: auto;
overflow-y: scroll;
opacity: 0;
background-color: whitesmoke;
transition: all 0.5s linear;
}
.annotation-modal.active{
top: 10vh;
opacity: 1;
}
.annotation-modal.inactive{
top: 0;
opacity: 0;
}
So basically using ng-class im switching between two classes
.active and .inactive but it seems transition does not animate the change in the classes, i think i have some general mistake but can't find it. I don't use ngAnimate because i'm making module so i don't a lot of dependencies and that's why i'm making it custom with classes

You are hiding the annotation-panel with display:none instantly when the state changes to inactive, so the contained annotation-modal wont be visible.
The use of ng-animate here would be to only apply ng-hide (and thus, display:none) when the animation has finished.
Without that, you need to use a different method to hide the panel after the animation has finished. Here is one solution with moving the panel offscreen. Notice how the transition-delay in inactive state matches the animation length of the modal fadeout. Also, by only having the transition on the inactive state, when the panel becomes active, it moves instantly to the viewport.
.annotation-panel{
position: fixed;
top: -2000px;
left: 0;
z-index: 1000;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
}
.annotation-panel-active{
top: 0;
}
.annotation-panel-inactive{
transition-property: top;
transition-delay: 0.5s;
transition-duration: 0s;
}
.annotation-panel{
position: fixed;
top: -2000px;
left: 0;
z-index: 1000;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.7);
}
.annotation-panel-active{
top: 0;
}
.annotation-panel-inactive{
transition-property: top;
transition-delay: 0.5s;
transition-duration: 0s;
}
.annotation-modal{
position: fixed;
z-index: 1001;
left:10vw;
top: 0;
width: 80vw;
height: auto;
overflow-y: scroll;
opacity: 0;
background-color: whitesmoke;
transition: all 0.5s linear;
}
.annotation-modal.active{
top: 10vh;
opacity: 1;
}
.annotation-modal.inactive{
top: 0;
opacity: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<span class="glyphicon glyphicon-edit" ng-click="modalState =!modalState">click</span>
<div class="annotation-panel"
ng-class="{'annotation-panel-active' : modalState == true, 'annotation-panel-inactive' : modalState == false}">
<div class="annotation-modal" ng-class="{'active':modalState == true, 'inactive':modalState == false}"> helloo
<button type="button" class="btn btn-default" ng-click="modalState = false">Close</button>
</div>
</div>
</div>

You should go for ng-hide if you just have to make display none for the element
here are some animation css for that
//
//a working example can be found at the bottom of this page
//
.my-element.ng-hide-add, .my-element.ng-hide-remove {
/* this is required as of 1.3x to properly
apply all styling in a show/hide animation */
transition: 0s linear all;
}
.my-element.ng-hide-add-active,
.my-element.ng-hide-remove-active {
/* the transition is defined in the active class */
transition: 1s linear all;
}
.my-element.ng-hide-add { ... }
.my-element.ng-hide-add.ng-hide-add-active { ... }
.my-element.ng-hide-remove { ... }
.my-element.ng-hide-remove.ng-hide-remove-active { ... }
Link for more details animations

Related

I have tried several things but cannot get react-modal working correctly

I'm looking for a simple Modal component in my React project. I opted to go with https://www.npmjs.com/package/react-modal because it seemed popular.
But everything I've tried so far has the modal hugging the top-left of the parent DIV. Here's the basic code I've tried:
<main className={styles.main}>
<Modal
isOpen={isShowModal}
className={styles.modal}
overlayClassName={styles.overlay}
ariaHideApp={false}
contentLabel='abc def'
>
Here is some modal content!<br/>
Here is some modal content!<br/>
Here is some modal content!<br/>
Here is some modal content!<br/>
Here is some modal content!<br/>
</Modal>
</main>
.main {
height: $page-height;
background: $sea-lord-background;
padding: 20px 20px;
}
.modal {
// margin-top: 500px;
position: absolute;
// // height: 300px;
// // width: 500px;
top: '50%';
left: '50%';
right: 'auto';
bottom: 'auto';
margin-right: '-50%';
transform: 'translate(-50%, -50%)';
background-color: $gray;
opacity: 0.6;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: lime;
}
But everything I've tried, I can't get the basic modal centered vertically & horizontally. What am I doing wrong?

How to add animation on container changing its width realtime

I am making a form that expands when the user enters any character/key and gets back to its original width when there is no character left, for the plus point, I want to add animation to that expandable form so it gives a smooth look.
Here is the code and I want this action as follows
Not in React but I made an example in Vanilla JS hope it helps. I used CSS variables for changing width and making it smooth.
Instead of removing svg icons completely try scaling it down to 0 or changing it opacity to 0
const btns = Array.from(document.querySelectorAll('.btn'))
const input = document.querySelector('input')
btns.shift() // for leaving first button
input.addEventListener('input', (event) => {
btns.forEach((btn) => {
if (event.target.value.trim().length > 0) {
btn.classList.add('scale-0')
btn.parentElement.classList.add('width-50')
} else {
btn.classList.remove('scale-0')
if (btn.parentElement.classList.contains('width-50')) {
btn.parentElement.classList.remove('width-50')
}
}
})
})
#import 'https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css';
body {
display: grid;
place-items: center;
}
.row {
--column-gap: 1rem; /* 8px */
width: 100%;
display: flex;
max-width: 525px;
column-gap: var(--column-gap);
}
.row input {
flex-grow: 1;
border-radius: 100vmax;
padding: 0.75rem 1.25rem;
border: 1px solid #c1c1c1;
}
.container {
--column-gap: 0.5rem; /* 16px */
--btn-size: 3.125rem; /* 50px */
flex-shrink: 0;
display: inherit;
column-gap: var(--column-gap);
width: calc(var(--column-gap) * 3 + var(--btn-size) * 4);
transition: width 250ms ease;
}
.container.width-50 {
width: var(--btn-size);
}
.container .btn {
width: var(--btn-size);
border-radius: 50%;
aspect-ratio: 1/1;
border: 1px solid #c1c1c1;
transition: transform 250ms ease;
}
.container .btn.scale-0 {
transform: scale(0);
}
<div class="row">
<div class="container">
<button class="btn">1</button>
<button class="btn">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
</div>
<input type="text" />
</div>

Change the style of a single element within an ng-repeat

I have angular code that has a number of different time segments per week. They are all within an ng-repeat. I want to be able to change the colour of a time segment whenever the mouse is over that item. With my current code the colour gets changes for every item within the ng-repeat.
public onSegmentMouseOverLeave(changeSegmentColor : boolean) : void {
this.timeSegmentColor = changeSegmentColor;
}
.time-segment-grid {
position: absolute;
top: 0;
margin-top: 2px;
height: 35px;
border-radius: 5px;
cursor: pointer;
z-index: 1;
#gradient > .vertical(#1b9dd0, #0080b5);
}
.time-segment-grid-onmove {
position: absolute;
top: 0;
margin-top: 2px;
height: 35px;
border-radius: 5px;
cursor: pointer;
z-index: 1;
#gradient > .vertical(#f442d7, #0080b5);
}
<div>
<div ng-repeat="timeSegment in $ctrl.deal.deal_settings.dayparting.schedule[dayName] track by $index">
<span ng-class="$ctrl.daypartingTimeSegments.timeSegmentColor ? 'time-segment-grid' : 'time-segment-grid-onmove' "
ng-style="$ctrl.daypartingTimeSegments.timeSegmentGridStyle(timeSegment)"
ng-mousedown="$ctrl.daypartingTimeSegments.onSegmentDragStart($event, dayName, $index, 'dragFullContent')"
ng-mouseover="$ctrl.daypartingTimeSegments.onSegmentMouseOverLeave(false)"
ng-mouseleave="$ctrl.daypartingTimeSegments.onSegmentMouseOverLeave(true)">
</span>
</div>
</div>
enter image description here
For your HTML, I would do:
ng-mouseover="mouseOverOn = true"
ng-mouseleave="mouseOverOn = false"
ng-class="{hoverstyle: mouseOverOn}"
Which would correspond to the CSS class hoverstyle.
Right now, your code is evaluating an expression that has no correlation to the element within ng-repeat, which is why they are all highlighting.
If you need the other expressions, you can add to the expression:
ng-mouseover="mouseOverOn = true; $ctrl.daypartingTimeSegments.onSegmentMouseOverLeave(false)"
Why using code when CSS can support it =(
.time-segment-grid {
position: absolute;
top: 0;
margin-top: 2px;
height: 35px;
border-radius: 5px;
cursor: pointer;
z-index: 1;
#gradient > .vertical(#1b9dd0, #0080b5);
}
.time-segment-grid:hover {
#gradient > .vertical(#f442d7, #0080b5);
}

CSS Sliding views with ui-router

I am trying to achieve the same effect of sliding in/out views as found here:
http://dfsq.github.io/ngView-animation-effects/app/#/page/1
Ive created a plunker: http://plnkr.co/edit/ST49iozWWtYRYRdcGGQL?p=preview
But my entire ui-view completely disappears when i copy the CSS from the link above and think it could be down to the position: relative in my container
CSS:
*,
*:after,
*:before {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
html {
font-size: 62.5%;
min-height: 100%;
position: relative;
}
html body {
font-size: 140%;
line-height: 1.5;
margin: 0;
padding: 0 0;
margin-bottom: 60px;
}
.container {
max-width: 430px;
margin: 0 auto;
position: relative;
display: block;
float: none;
overflow: hidden;
}
.l-one-whole {
width: 100%;
}
form {
background: #f0f0f0;
height: 350px;
padding: 10px;
font-size: 1.4em;
}
CSS needed to add:
.slide {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.slide.ng-enter,
.slide.ng-leave {
-webkit-transition: all 1s ease;
transition: all 1s ease;
}
.slide.ng-enter {
left: 100%;
}
.slide.ng-enter-active {
left: 0;
}
.slide.ng-leave {
left: 0;
}
.slide.ng-leave-active {
left: -100%;
}
HTML:
<body ng-controller="MainCtrl">
<ul>
<li>view1
</li>
<li>view2
</li>
</ul>
<main class="l-one-whole">
<section class="container">
<article class="l-one-whole">
<div ui-view class="slide"></div>
</article>
</section>
</main>
</body>
JS:
var app = angular.module('plunker', ['ui.router', 'ngAnimate']);
app.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('view1', {
url: '/view1',
templateUrl: 'page1.html'
})
.state('view2', {
url: '/view2',
templateUrl: 'page2.html'
});
$urlRouterProvider.otherwise('/view1');
});
Any help appreciated.
I think this is what you are looking for: Plunkr
I added the following styles to make animations work:
/* Transition effects */
.l-one-whole {
position: relative;
overflow: hidden;
min-height: 400px;
}
.slide {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.slide.ng-enter,
.slide.ng-leave {
transition: all 1s ease;
}
.slide.ng-enter {
transform: translate(100%, 0);
}
.slide.ng-enter-active {
transform: translate(0, 0);
}
.slide.ng-leave {
transform: translate(0, 0);
}
.slide.ng-leave-active {
transform: translate(-100%, 0);
}
I used transform instead of left because AFAIK it enables browser to accelerate animation using GPU increasing performance.
I hope I am not missing anything.
Result: http://plnkr.co/edit/vhGSiA?p=preview
I have use Angular 1.3.15 instead of 1.2.9
Simplified HTML
<section class="container">
<div ui-view class="slide-left"></div>
</section>
and more CSS
.container {
overflow: hidden;
position: relative;
}
.slide-left.ng-enter, .slide-left.ng-leave {
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
transition: transform .7s ease-in-out;
}
.slide-left.ng-enter {
z-index: 101;
transform: translateX(100%);
}
.slide-left.ng-enter.ng-enter-active {
transform: translateX(0);
}
.slide-left.ng-leave {
z-index: 100;
transform: translateX(0);
}
.slide-left.ng-leave.ng-leave-active {
transform: translateX(-100%);
}
form { /* contents within ui-view */
position:absolute;
}
Change
<script src="https://raw.github.com/dlukez/ui-router/angular-1.2/release/angular-ui-router.js"></script>
to:
<script src="https://cdn.rawgit.com/dlukez/ui-router/angular-1.2/release/angular-ui-router.js"></script>
Updated plnkr
Detail explaination can be found here:
Link and execute external JavaScript file hosted on GitHub

angular google maps window close button drifting

Our application in using Onsen and angular-google-maps. As shown in the example here, the "x" in the Google Maps InfoWindow is slowly drifting each time the map is reloaded.
All windows on the map open with the "x" in the same, correct, location the first time. Closing the map page popPage() and opening the map pushPage() causes the "x" to drift up and to the right 8px. The following is generated? and placed in the DOM below the content I put in the <ui-gmap-window> tags.
<div style="width: 19.5px; height: 19.5px; overflow: hidden; position: absolute; opacity: 0.7; transform: translateZ(0px); right: 15px; top: 12px; z-index: 10000;">
<img src="http://maps.gstatic.com/mapfiles/api-3/images/mapcnt3.png" draggable="false" style="position: absolute; left: -3px; top: -504px; width: 88.5px; height: 738px; -webkit-user-select: none; border: 0px; padding: 0px; margin: 0px;">
</div>
Back and reopen:
<div style="width: 19.5px; height: 19.5px; overflow: hidden; position: absolute; opacity: 0.7; transform: translateZ(0px); right: 7px; top: 4px; z-index: 10000;">
<img src="http://maps.gstatic.com/mapfiles/api-3/images/mapcnt3.png" draggable="false" style="position: absolute; left: -3px; top: -504px; width: 88.5px; height: 738px; -webkit-user-select: none; border: 0px; padding: 0px; margin: 0px;">
</div>
How can I determine what is causing this drift?
Update 2015-01-22:
I currently have a workaround.
function fixInfoWindow(){
$timeout(function(){
$(".gm-style-iw").each(function(){
if(this.parentNode.style.visibility != "hidden" && this.nextSibling != null){
this.nextSibling.style.right = "10px";
this.nextSibling.style.top = "8px";
this.nextSibling.nextSibling.style.right = "3px";
this.nextSibling.nextSibling.style.top = "1px";
}
});
});
}
This moves the "x" and the hidden item that closes the window when pressed to the proper location. I call this function at the end of the functions that set each InfoWindow visible.
My example can also be reproduced in Chrome with device emulation turned on.
I still have not found the cause of the drift.

Resources