I've been playing around with the animation aspect in AngularJS, and I just can't seem to get the kind of functionality I need:
.box.ng-hide-add {-webkit-animation: fadeOutLeftBig 0.4s;}
.box.ng-hide-remove {-webkit-animation: fadeInRightBig 0.4s;}
.box.ng-show-add{-webkit-animation: fadeInRightBig 0.4s;}
Ideally, when the user hits the 'Next' button, the current box should exit to the left, while the box next in line eases in from the right, creating that slideshow/carousel effect.
But right now it's all from the same side.
Is this even possible? I feel like I'm getting close, but I could just be thinking about it the wrong way. What am I overlooking or forgetting?
Code snippet:
(function(){
var app = angular.module("theapp", ['ngAnimate']);
var controller = function($scope){
$scope.currentPage = 1;
};
app.controller("controller", controller);
}());
.box.ng-hide-add {
-webkit-animation: fadeOutLeftBig 0.4s;
}
.box.ng-hide-remove {
-webkit-animation: fadeInRightBig 0.4s;
}
.box.ng-show-add {
-webkit-animation: fadeInRightBig 0.4s;
}
.box {
height:100px;
width:100px;
}
.red {background-color:red;}
.blue {background-color:blue;}
.purple {background-color:purple;}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.0/animate.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-animate.min.js"></script>
<body ng-app="theapp">
<div ng-controller="controller">
<div style="height:100px; margin-left:300px;">
<div ng-show="currentPage==1" class="box red">
content
</div>
<div ng-show="currentPage==2" class="box blue">
content
</div>
<div ng-show="currentPage==3" class="box purple">
content
</div>
</div>
<button ng-click="currentPage=currentPage-1">Previous</button>
<button ng-click="currentPage=currentPage+1">Next</button>
</div>
</body>
(fiddle: http://jsfiddle.net/poppypoop/Ldyvy062/3/)
Any help is appreciated!
The code below does what you want, see comments in code for explanation, hope this is helpful.
I changed to ng-if, instead of ng-show, to be able to use ng-enter, ng-leave in CSS
(function () {
var app = angular.module("theapp", ['ngAnimate']);
var controller = function ($scope, $timeout) {
$scope.currentPage = 1;
$scope.numberOfPages = 3;
$scope.changePage = function (action) {
if (action === '+') {
$scope.direction = 'toRight';
$timeout(function () { // timeout to allow direction class to update before changing currentPage
$scope.currentPage = $scope.currentPage < $scope.numberOfPages ? $scope.currentPage + 1 : 1;
}, 0)
} else if (action === '-') {
$scope.direction = 'toLeft';
$timeout(function () { // timeout to allow direction class to update before changing currentPage
$scope.currentPage = $scope.currentPage > 1 ? $scope.currentPage - 1 : $scope.numberOfPages;
}, 0)
}
}
};
app.controller("controller", controller);
}());
.toRight .box.ng-enter {
-webkit-animation: fadeInRightBig 0.7s;
}
.toLeft .box.ng-enter {
-webkit-animation: fadeInLeftBig 0.7s;
}
.toRight .box.ng-leave {
-webkit-animation: fadeOutLeftBig 0.7s;
}
.toLeft .box.ng-leave {
-webkit-animation: fadeOutRightBig 0.7s;
}
.box {
height: 100px;
width: 100px;
position:absolute; /*This is to avoid animations to overlap, causing a weird behavior*/
}
.red {background-color:red;}
.blue {background-color:blue;}
.purple {background-color:purple;}
<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.0/animate.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular-animate.min.js"></script>
<body ng-app="theapp">
<div ng-controller="controller">
<div style="height:100px; margin-left:300px;" class="{{direction}}"><!--Added angular variable in class to determite direction-->
<div ng-if="currentPage==1" class="box red">
content
</div>
<div ng-if="currentPage==2" class="box blue">
content
</div>
<div ng-if="currentPage==3" class="box purple">
content
</div>
</div>
<button ng-click="changePage('-')">Previous</button>
<button ng-click="changePage('+')">Next</button>
</div>
</body>
Related
Below is the code for the magic cursor effect. But I'm struggling to get the same effect in Angular.
$(document).ready(function(){
var coordinateX=0;
var coordinateY=0;
var bottomCursor=document.querySelector('.circle-cursor-bottom');
var topCursor=document.querySelector('.circle-cursor-top');
function displayCursor(e){
document.addEventListener('mousemove',e=>{
coordinateX=e.clientX;
coordinateY=e.clientY
});
function animCursor(){
topCursor.style.transform=`translate(${coordinateX}px, ${coordinateY}px)`;
bottomCursor.style.transform=`translate(${coordinateX}px, ${coordinateY}px)`;
requestAnimationFrame(animCursor)};
requestAnimationFrame(animCursor)};
displayCursor();
});
.circle-cursor {
position:fixed;
pointer-events:none;
width:1.4376rem;
height:1.4376rem;
margin:-0.630rem 0 0 -0.630px;
top:0;
left:0;
border-radius:50%;
}
.circle-cursor-inner {
width:100%;
height:100%;
border-radius:50%;
display:block;
}
.circle-cursor-top {
background-color:#22d4b5;
transition:transform 0.06s cubic-bezier(.12,.12,.25,.92),opacity 1s ease;
z-index:9999;
}
.circle-cursor-bottom {
background:#6edddf;
transition:transform 0.26s cubic-bezier(.12,.12,.25,.92),opacity 1s ease;
z-index:9998;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="custom-cursor-holder">
<div class="circle-cursor circle-cursor-top">
<span class="circle-cursor-inner"></span>
</div>
<div class="circle-cursor circle-cursor-bottom"></div>
</div>
This is the code I tried. But not able to replicate with precision. Any Idea/Best way to implement would be helpful.
<div class="custom-cursor-holder">
<div #top class="circle-cursor circle-cursor-top">
<span class="circle-cursor-inner"></span>
</div>
<div #bottom class="circle-cursor circle-cursor-bottom"></div>
</div>
export class AppComponent{
coordinateX = 0;
coordinateY = 0;
#ViewChild('top') top!: ElementRef;
#ViewChild('bottom') bottom!: ElementRef;
/**
*
*/
constructor(private renderer: Renderer2) {
}
#HostListener('mouseover', ['$event'])
onOver(event: MouseEvent): void {
this.coordinateX = event.clientX;
this.coordinateY = event.clientY;
this.renderer.setStyle(this.top.nativeElement, 'transform', 'translate('+ this.coordinateX +'px, '+ this.coordinateY +'px)');
}
}
from this SO
Using fromEvent(document,'mousemove') and throttleTime rxjs/operator
#ViewChild('top') top!: ElementRef;
#ViewChild('bottom') bottom!: ElementRef;
constructor() {}
ngOnInit()
{
this.subscription=fromEvent(document,'mousemove').pipe(throttleTime(50,asyncScheduler,{ leading:true,trailing: true })).subscribe((e:any)=>{
const coordinateX=e.clientX;
const coordinateY=e.clientY;
this.top.nativeElement.style.transform=
`translate(${coordinateX}px, ${coordinateY}px)`;
this.bottom.nativeElement.style.transform=
`translate(${coordinateX}px, ${coordinateY}px)`;
})
}
ngOnDestroy()
{
this.subscription.unsubscribe()
}
a stackbltiz
NOTE: it's neccesary use throttleTime to give a breath to Angular
I have a progress element. That element looks like the following:
<div class="container">
<div id="progress-bar">
<progress id="myProgressBar" class="progress" style="background-color:orange;" value="0" max="100"></progress>
</div>
<br>
<button id="animateButton" class="btn btn-secondary">Animate</button>
</div>
When a user clicks the "animate" button, I want to fill the progress bar with an orange bar to 75%. The animation should take .5 seconds (half a second).
As shown in this Bootply, I'm stuck getting the animation to work. I tried using setInterval, however, the animation was really jerky. Plus, I couldn't get the bar to be orange. It was always green.
Is there a way to animate the value of a progress element for a smooth animation?
In webkit browsers you can use a pseudo class to add a transition and color:
$('#animateButton').on('click', function() {
$('#myProgressBar').val(75);
});
progress[value]::-webkit-progress-value {
transition: width 0.5s;
background: orange;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="progress-bar">
<progress id="myProgressBar" class="progress" style="background-color:orange;" value="0" max="100"></progress>
</div>
<br>
<button id="animateButton" class="btn btn-secondary">Animate</button>
</div>
If you need wider browser support, you can iterate the value 'till you get to the target value to animate the bar. However, you can't change the color.
function animateProgress($progressBar, val, currentVal) {
currentVal = currentVal || 0;
var step = val * 16 / 500;
function animate(currentVal) {
currentVal += step;
$progressBar.val(currentVal);
currentVal < val && requestAnimationFrame(function() {
animate(currentVal);
});
}
animate(currentVal);
}
$('#animateButton').on('click', function() {
animateProgress($('#myProgressBar'), 75);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div id="progress-bar">
<progress id="myProgressBar" class="progress" style="background-color:orange;" value="0" max="100"></progress>
</div>
<br>
<button id="animateButton" class="btn btn-secondary">Animate</button>
</div>
Here's how it can be done using smooth CSS3 animation : no need for jQuery or even JS animation at all.
var progressBar = document.getElementById("progress-bar")
document.getElementById("animateButton").onclick= function(){
progressBar.style.width = "75%"
progressBar.style["background-color"] = "orange"
}
.container {
height: 30px;
}
.container #progress-bar {
background-color: #008000;
height: 100%;
width: 10%;
-webkit-transition: all 0.5s ease-in-out;
transition: all 0.5s ease-in-out;
}
<div class="container">
<div id="progress-bar"></div>
</div>
<br>
<button id="animateButton" class="btn btn-secondary">Animate</button>
Here's an example
document.getElementById("animateButton").onclick= function(){
document.getElementById("progress-bar").style.backgroundColor = "orange";
document.getElementById("progress-bar").style.width = "75%";
}
#progressHolder{
background:grey;
height:20px;
width:300px;
}
#progress-bar{
background:grey;
height:20px;
width:0px;
transition:background-color 0.5s, width 0.5s;
}
<div class="container">
<div id="progressHolder">
<div id="progress-bar">
</div>
</div>
<br>
<button id="animateButton" class="btn btn-secondary">Animate</button>
</div>
You can use JQuery animation and set the time interval as "slow", "fast", or in milliseconds.
$("#progress-bar").click(function(){
$("#myProgressBar").animate({width: "100px"},slow);
});
I have a bootstrap based website which is divided into different sections. In a section called features I have three images which I want to rotate when a user navigates to it or scroll downs to that section and also when the user hover overs it. I know how to rotate the images on hover but unable to think of a way to do it when a user scrolls down to that section.
The html section code:-
<section id="features">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2 class="section-heading dark">Features</h2>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="bg1.png" class="feature-size">
</div>
</div>
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="bg2.png" class="feature-size">
</div>
</div>
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="bg3.png" class="feature-size">
</div>
</div>
</div>
</div>
</section>
The css for rotating images on hover:-
<style type="text/css">
img {
transition: all 0.5s ease-in-out 0s;
}
img:hover {
cursor: default;
transform: rotate(360deg);
transition: all 0.5s ease-in-out 0s;
}
</style>
Whenever a user goes to that section the images will rotate once and also on hovering over the image. Please provide a way to do it with css or plain javascript. I don't want to use any javascript plugins like jquery. Any help is highly appreciated.
You can use Waypoint js : http://imakewebthings.com/waypoints/
var waypoint = new Waypoint({
element: document.getElementById('waypoint'),
handler: function(direction) {
console.log('Scrolled to waypoint!')
}
})
Add a class on reaching the point during the scroll.
Using JQuery plugin Appear can make this a lot easier.
function toggleHover() {
$(".feature-size").each(function() {
$(this).toggleClass("hovered")
});
}
$('#features').appear(function() {
setTimeout(function() {
toggleHover();
setTimeout(toggleHover, 1000); //to revert the animation
}, 1500);
});
and add this css rule.
img.hovered {
cursor: default;
transform: rotate(360deg);
transition: all 0.5s ease-in-out 0s;
}
Feel free to change the timeout seconds, as i cannot predict the timings you may want without hands on
Here is the one with JavaScript, but you need to make some tweaks according to the requirements.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
div{height: 100vh;}
</style>
</head>
<body>
<div>
<script>
</script>
</div>
<div>
<script>
</script>
</div>
<div id="foo" style="background-color:red;">
<script>
</script>
</div>
<script>
function getPosition(el) {
var xPos = 0;
var yPos = 0;
while (el) {
if (el.tagName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft);
yPos += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: xPos,
y: yPos
};
}
// deal with the page getting resized or scrolled
window.addEventListener("scroll", checkPosition, false);
window.addEventListener("resize", checkPosition, false);
function checkPosition() {
console.log(getPosition(myElement));
console.log(position);
if((getPosition(myElement)).y < 10 && (getPosition(myElement)).y > -10){
alert("Here");
}
}
var myElement = document.querySelector("#foo");
var position = getPosition(myElement);
</script>
</body>
</html>
You could do it with :target pseudo-class (MDN)
Something like this with your given code:
a {
display: block;
/* Just for demonstration */
height: 100vh;
}
img {
transition: all 0.5s ease-in-out 0s;
}
:target img {
cursor: pointer;
transform: rotate(360deg);
}
:target img:hover {
transform: rotate(720deg);
}
Link to section
<section id="features">
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h2 class="section-heading dark">Features</h2>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="http://fillmurray.com/300/300" class="feature-size">
</div>
</div>
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="http://fillmurray.com/300/300" class="feature-size">
</div>
</div>
<div class="col-lg-4 text-center">
<div class="feature-box">
<img src="http://fillmurray.com/300/300" class="feature-size">
</div>
</div>
</div>
</div>
</section>
I have used a JavaScript for loop to change the className property of a group of DIV's that have same class.
I'm trying to change of appearance of each div by the changing the className property so that the CSS transition activates and effects the each DIV.
The problem is that the transition ONLY affects the first DIV.
Here is my HTML code:
<body onload="init()">
<div id="menu">
<div class="accor hide" id="chosen">
od
</div>
<ul>
<li>To</li>
<li>Pr</li>
<li>La</li>
</ul>
<div class="accor hide">
En
</div>
<ul>
<li>fa</li>
<li>Co</li>
<li>Co</li>
</ul>
<div class="accor hide">
Sp
</div>
</div>
</body>
Here is my CSS:
.accor + ul {
max-height: 500px;
overflow: hidden;
transition: max-height 0.5s ease
}
.hide + ul {
max-height: 0px;
overflow: hidden;
transition: max-height 0.5s ease
}
Here is my JavaScript:
function init() {
var chosen = document.getElementById("chosen");
chosen.onclick = toggleDivs;
}
function toggleDivs() {
hideDivs = document.getElementsByClassName("accor hide");
for(var i = 0; i <= hideDivs.length; i++) {
hideDivs[i].className = 'accor';
}
}
When I click the DIV with the id of "chosen" I want to make all the DIV's with the class "accor" slide down like like jQuery's $.fn.slideDown(...);.
If I change the JavaScript a little bit the transition will effect the first two DIV's.
Here is my changed JavaScript:
hideDivs = document.getElementsByClassName('accor hide');
hideDivs[0].className = 'accor';
hideDivs = document.getElementsByClassName('accor hide');
hideDivs[0].className = 'accor';
I think this is because when I used the for loop (above) i was initially set to 0 and i did not increment so the transition only effected the first DIV.
pugazh have other fix so i want to post hear for diversity.
function toggleDivs() {
var menu = document.getElementsByClassName('accor')
for (var i = 0; i <= menu.length; i++)
menu[i].classList.toggle('hide');
};
I replaced hideDivs[i].className = 'accor'; with hideDivs[0].className = 'accor';
I did this because each time you execute toggleDivs(); the class hide is removed from the element, you want to toggle the DIV's not always hide them.
window.addEventListener("load", init, false);
function init() {
var chosen = document.getElementById("chosen");
chosen.onclick = toggleDivs;
}
function toggleDivs() {
hideDivs = document.getElementsByClassName("accor hide");
for(var i = 0; i <= hideDivs.length; i++) {
hideDivs[0].className = 'accor';
}
}
.accor + ul {
max-height: 500px;
overflow: hidden;
transition: max-height 0.5s ease
}
.hide + ul {
max-height: 0px;
overflow: hidden;
transition: max-height 0.5s ease
}
<body onload="init()">
<div id="menu">
<div class="accor hide" id="chosen">
od
</div>
<ul>
<li>To</li>
<li>Pr</li>
<li>La</li>
</ul>
<div class="accor hide">
En
</div>
<ul>
<li>fa</li>
<li>Co</li>
<li>Co</li>
</ul>
<div class="accor hide">
Sp
</div>
</div>
</body>
I have the following lines of code in my web page - demo/example.
HTML:
<button class="wrong-answer" onclick="showResult(this)">42</button>
<button class="right-answer" onclick="showResult(this)">43</button>
<p id="answer" class="answer-display-hidden">answer</p>
<div class="incorrect">
<span>Incorrect:</span>
<p>0</p>
</div>
<div class="correct">
<span>Correct:</span>
<p>0</p>
</div>
CSS:
.answer-display-visible {
visibility: visible;
opacity: 1;
transition: opacity 1s linear;
}
.answer-display-hidden {
visibility: hidden;
opacity: 0;
transition: visibility 0s 1s, opacity 1s linear;
}
.incorrect, .correct {float: left; padding-right: 20px}
JS:
var incorrectCalls = 0;
var correctCalls = 0;
function showResult(b) {
var res = document.getElementById('answer');
if (b.classList.contains('right-answer')) {
res.innerHTML = '<span class="right">right</span>';
correctCalls++;
var cor = $('.correct > p:first');
cor[0].innerHTML = correctCalls;
}
else {
res.innerHTML = '<span class="wrong">wrong</span>';
incorrectCalls++;
var incor = $('.incorrect > p:first');
incor[0].innerHTML = incorrectCalls;
}
res.classList.remove("answer-display-hidden");
res.classList.add("answer-display-visible");
setTimeout(function() {
res.classList.add("answer-display-hidden");
}, 2000);
}
How can I de-activate the right-answer counter during the fade-in and wait effect on the text, and then re-activate afterwards? This is so that the user can't manipulate the counter (click on the button quickly before the text is displayed).
You can use setTimeout function when button clicked.
Live Demo
Code Block:
function showResult(b) {
.
.
.
$(".right-answer").prop("disabled", true);
$(".wrong-answer").prop("disabled", true);
setTimeout(function() {
$(".right-answer").prop("disabled", false);
$(".wrong-answer").prop("disabled", false);
}, 2600);
}
This is my solution
WORKING DEMO
Removed CSS code and following is the jQuery code.
$(document).ready(function(){
$(".wrong-answer").click(function(){
$(".right-answer").attr("disabled","disabled");
$("#answer").text("WRONG").fadeIn(5000,function(){
$(this).fadeOut(5000,function(){
$(".right-answer").removeAttr("disabled");
});
})
});
});