Punctuation loading "animation", javascript? - javascript

I'm looking for a good way to display some punctuation loading "animation".
What I want is something like this:
This will display at second 1: "Waiting for your input."
This will display at second 2: "Waiting for your input.."
This will display at second 3: "Waiting for your input..."
This will display at second 4: "Waiting for your input...."
This will display at second 5: "Waiting for your input."
This will display at second 6: "Waiting for your input.."
This will display at second 7: "Waiting for your input..."
This will display at second 8: "Waiting for your input...."
And so on.
I started by surrounding the dots in spans and thought I could loop through them with jquery and display one more, one more, one more, then reset to 1. But the code got very clumsy, so I wonder how you would do this?

Pure CSS solution
Demo: jsfiddle.net/feklee/D59P9
HTML:
Waiting<span class="dots"><span>.</span><span>.</span><span>.</span></span> for more.
CSS:
#keyframes dots-1 { from { opacity: 0; } 25% { opacity: 1; } }
#keyframes dots-2 { from { opacity: 0; } 50% { opacity: 1; } }
#keyframes dots-3 { from { opacity: 0; } 75% { opacity: 1; } }
#-webkit-keyframes dots-1 { from { opacity: 0; } 25% { opacity: 1; } }
#-webkit-keyframes dots-2 { from { opacity: 0; } 50% { opacity: 1; } }
#-webkit-keyframes dots-3 { from { opacity: 0; } 75% { opacity: 1; } }
.dots span {
animation: dots-1 1s infinite steps(1);
-webkit-animation: dots-1 1s infinite steps(1);
}
.dots span:first-child + span {
animation-name: dots-2;
-webkit-animation-name: dots-2;
}
.dots span:first-child + span + span {
animation-name: dots-3;
-webkit-animation-name: dots-3;
}
WebKit-only alternative
Advantage: No nested tags. This means that the ellipsis could be put as content
into an ::after pseudo element.
Demo: jsfiddle.net/feklee/vFT7W
HTML:
Waiting<span>...</span> for more.
CSS:
body {
font-family: 'Roboto', sans-serif;
font-size: 50px;
}
#-webkit-keyframes dots {
0% { background-position: 0px; }
100% { background-position: 50px; }
}
span {
background: linear-gradient(to right, white 50%, black 50%);
color: transparent;
-webkit-background-clip: text;
-webkit-animation: dots 1s infinite steps(4);
padding-right: 40px;
margin-right: -40px;
}

The trick to making a string of dots is to make a sparse Array and then join all the elements with the desired character.
var count = 0;
setInterval(function(){
count++;
var dots = new Array(count % 10).join('.');
document.getElementById('loadingtext').innerHTML = "Waiting for your input." + dots;
}, 1000);
Here is a Live demo.

This can be very easy:
HTML
<span class="dots"></span>
JQuery
setInterval(function() {
var th = $('.dots');
if(th.text().length < 5){
th.text(th.text()+".");
}else{
th.text("");
}
}, 500);
Demo

Now sure how the code got out of hand, you could just do:
setInterval(function () {
var span = $("#text-loader").children("span:eq(0)");
var ellipsis = span.html();
ellipsis = ellipsis + ".";
if (ellipsis.length > 5) {
ellipsis = ".";
}
span.html(ellipsis);
}, 1000);
<div id="text-loader">
This will display at second 1: "Waiting for your input<span>.</span>
</div>
And as for the 1, you can swap that out with the number of periods.

try this function: i'v put an example here http://jsfiddle.net/XFd39/
var i=0;
function f() {
if(i<=4)
$('#a').append(".");
i++;
if(i==4){
$('#a').html("");
i=0;
}
setTimeout(f,500);
}
f();

Here is a pretty simple variant: http://jsfiddle.net/psycketom/FusdC/
Read the comments below to understand what everything is doing there.
var span = $('.dots'); // take the element where you have the maximum count of dots
var text = span.text(); // cahce it's text value
// we set up a function here, so we can loop it all the time
var loading = function()
{
$({
count : 1 // we start at one dot
}).animate({
count : text.length // together forming all of it
}, {
duration : 1000, // make the animation complete in one second
step : function() {
span.text( text.substring(0, Math.round(this.count)) ); // on each step, change the text accordingly to current iteration
},
complete : function() {
loading(); // once complete, start all over again
}
});
};
loading(); // start it up for the first time
Here you also gain the advantage of using easing if you wish, easily changing total duration and bunch of other benefits in case you're good with jQuery.

Dude, unless you want to display this animation forever you will need a way to stop the animation, or?
Don't even think about global variables, this is JavaScript and it's got closures for that :)
<p>please wait<span id="wait"></span></p>
<input type="submit" id="start" value="start">
<input type="submit" id="stop" value="stop">
<script type="text/javascript">
$(document).ready(function() {
var animator = function($el) {
var dotCount = 1;
var started = true;
return {
"start" : function step() {
dotCount = (dotCount + 1) % 10;
$el.text(new Array(dotCount).join('.'));
if (started) {
setTimeout(step, 100);
}
},
"stop" : function() {
started = false;
}
}
};
var animatedWait = animator($("#wait"));
$("#start").click(animatedWait.start);
$("#stop").click(animatedWait.stop);
});
</script>

Here is a modified version that will turn off the dots after a time.
var count = 0;
var dots = setInterval(function(){
count++;
document.getElementById('loadingtext').innerHTML = "Waiting for your input." + new Array(count % 5).join('.');
if (count == 10){ // show two iterations of the array.
clearInterval(dots); // stop the dots.
}
}, 100); // sets the speed
http://jsfiddle.net/Ty4gt/331/

Related

javascript onclick css fade in each time, not just 1st time

How can I have text fade in on each click and not just the first time using css transition and JavaScript?
Here is what I have so far
<style>
#data {
transition: .7s;
}
</style>
<h1 id="data"></h1>
click 1
document.getElementById('data').style.opacity = 0;
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 1;
document.getElementById('data').innerHTML = 'test';
}
document.getElementById('clicker').addEventListener('click', go);
It can also be done using Element.animate():
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, 700).onfinish = () => dataElement.style.opacity = 1
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
EDIT:
In the above snippet onfinish event handler was used to maintain the final opacity value since it was being set back to 0 after the animation ends. But I found that this can also be achieved by setting fill: 'forwards' in the keyframe options:
const dataElement = document.getElementById('data')
dataElement.style.opacity = 0
function go(event) {
event.preventDefault()
dataElement.animate({
opacity: [0, 1]
}, {
duration: 700,
fill: 'forwards'
})
}
document.getElementById('clicker').addEventListener('click', go)
<h1 class="fade-in" id="data">test</h1>
click 1
Also you might want to check browser compatibility before implementing those approaches
And if you want a safer approach you may use css animations:
const data = document.getElementById('data')
data.style.opacity = 0
const clicker = document.getElementById('clicker')
clicker.addEventListener('click', () => {
data.classList.remove('fade-in')
data.offsetWidth // required to trigger a reflow and restart the animation
data.classList.add('fade-in')
})
.fade-in {
animation-name: fadein-animation;
animation-duration: 700ms;
animation-fill-mode: forwards;
}
#keyframes fadein-animation {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<h1 id="data">test</h1>
click 1
setTimeout might work for you. On click set it invisible immediately and use setTimeout to have a delay then show it again.
document.getElementById('data').style.opacity = 0;
document.getElementById('data').innerHTML = 'test';
function go(event){
event.preventDefault();
document.getElementById('data').style.opacity = 0;
setTimeout(() => {
document.getElementById('data').style.opacity = 1;
}, 1000);
}
document.getElementById('clicker').addEventListener('click', go);
#data {
transition: .7s;
}
<h1 id="data"></h1>
click 1
<h1 id="data" style="opacity:0"> </h1>
<button type="button" id="clicker">Fade In</button>
<script>
var data = document.getElementById('data');
function fadeIn(){
data.innerHTML = 'Data entered successfully.';
data.animate({opacity:[0,1]},{duration:400,fill:'forwards'});
}
document.getElementById('clicker').addEventListener('click',fadeIn);
</script>

How to play one css anmation before chaging innerHTML and another one after it?

What I need is this: when I click the button I want the old text to slowly disappear, then I want the new one to slowly appear.
But the disappear animation never gets played. Here's my code:
css
.quote-container {
opacity: 0;
}
.appear {
opacity: 0;
animation: fadeIn 1200ms ease-in forwards;
}
.disappear {
opacity: 1;
animation: fadeOut 1200ms ease-in;
}
#keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
javascript
let pickARandomQuote = () => {
index = Math.floor(Math.random() * quotes.length);
currentQuote = quotes[index].quote;
currentAuthor = quotes[index].author;
console.log(currentQuote + " \n" + currentAuthor);
let quoteContainer = document.getElementById("quote-container");
quoteContainer.classList.add("disappear");
void quoteContainer.offsetWidth;
quoteContainer.classList.remove("disappear");
void quoteContainer.offsetWidth;
quoteContainer.classList.remove("appear");
document.getElementById("text").innerHTML = currentQuote;
document.getElementById("author").innerHTML = "- " + currentAuthor;
void quoteContainer.offsetWidth;
quoteContainer.classList.add("appear");
return {
quote: currentQuote,
author: currentAuthor
};
};
document.addEventListener("DOMContentLoaded", pickARandomQuote);
let button = document.getElementById("new-quote");
if (button) {
button.addEventListener("click", pickARandomQuote);
}
It seems like the animation on the screen happens independently from the code, so "disappear" animation doesn't have enough time to get played. I tried "setTimeout", but it didn't help though.
You need to wait till disappear animation ends before executing appear.
One of the approaches is setTimeout function.
Example:
let pickARandomQuote = function() {
index = Math.floor(Math.random() * quotes.length);
currentQuote = quotes[index].quote;
currentAuthor = quotes[index].author;
let quoteContainer = document.getElementById("quote-container");
quoteContainer.classList.remove("appear");
quoteContainer.classList.add("disappear");
setTimeout(function () {
document.getElementById("text").innerHTML = currentQuote;
document.getElementById("author").innerHTML = "- " + currentAuthor;
quoteContainer.classList.remove("disappear");
quoteContainer.classList.add("appear");
}, this.duration)
};
document.addEventListener("DOMContentLoaded", { handleEvent: pickARandomQuote, duration: 0 });
let button = document.getElementById("new-quote");
if (button) {
button.addEventListener("click", { handleEvent: pickARandomQuote, duration: 1200 });
}
However, if you can use jQuery, the following Q&A may work for you.
Jquery replacewith fade/animate

how to loop through an object with an interval time to change a css property

i am trying to loop through a javascript object to change background-image to other images every 3 seconds.
i know i will be using setInterval, a for-loop to go through the object and jQuery to access the css and change the background. but i am not sure about how to use all that together
HTML
<div class="example"></div>
CSS
.example {
height: 600px;
background-image: url(path/pic01.jpeg); }
JS
var header = {
pic01 : 'url(path/pic02.jpeg)',
pic02 : 'url(path/pic03.jpeg)',
pic03 : 'url(path/pic04.jpeg)',
pic04 : 'url(path/pic05.jpeg)'}
i tried:
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
clearInterval(i);
}
}, 3000);
and something like this. but i can't seem to get it done
for (var key in header) {
if (header.hasOwnProperty(key)) {
console.log(header[key]);
})
}
Why not use CSS?
html, body {
position: relative;
padding: 0;
margin: 0;
}
html, body, .example {
width: 100%;
height: 100%;
}
.example {
background-color: #333;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
animation-name: gallery;
animation-duration: 12s;
animation-timing-function: steps(1, start);
animation-iteration-count: infinite;
}
#keyframes gallery {
0%, 100% {
background-image: url(https://placebear.com/145/201)
}
25% {
background-image: url(https://placebear.com/395/205)
}
50% {
background-image: url(https://placebear.com/150/200)
}
75% {
background-image: url(https://placebear.com/145/300)
}
}
<div class="example"></div>
First, use an array for the header images, that makes it a little easier. Below are two functions that will either loop infinite, starting from 0 index once the array's length is reached, the other one will loop the array once until all elements have been shown once. (You'll need to adjust it to your needs instead of writing the text to the div...)
var header = [
'url(path/pic02.jpeg)',
'url(path/pic03.jpeg)',
'url(path/pic04.jpeg)',
'url(path/pic05.jpeg)'
];
var i = 0;
function loopInfinite(arr) {
document.getElementById('foo').innerHTML = arr[i];
i++;
if (i === arr.length) i = 0;
setTimeout(() => {
loopInfinite(arr);
}, 500);
}
function loopOnce(arr) {
document.getElementById('foo').innerHTML = arr[i];
i++;
if (i < arr.length) {
setTimeout(() => {
loopOnce(arr);
}, 500);
}
}
loopInfinite(header);
<div id="foo"></div>
In this codeblock:
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
clearInterval(i);
}
}, 3000);
You have not included your background-updating code. Something like this might be what you are looking for:
var imageNumber = 0;
var counter = 0;
var i = setInterval(function(){
counter++;
if(counter === 5) {
// your background-updating code
$('.example').css('background-image',headers['pic0' + imageNumber]);
imageNumber++;
if (imageNumber > headers.length) {
imageNumber = 0;
}
clearInterval(i);
}
}, 3000);

How to make casino-like increment of a letter?

I need to convert (when the user does something):
adcb
to (the next letter of every letter):
bedc
Currently I am just going with javascript and overwrite the character.
Remember the Pkmn Game Corner?
Wouldn't it be cool if we could simulate that movement of the character (in the pic, change from 7 to Pikachu)?
PS - I have no idea on how to approach this...
This can be achieved with CSS animations to move the letter around, updating the letter when it is not visible.
jsfiddle
HTML:
<div id="reels">
<div>A</div>
<div>L</div>
<div>E</div>
<div>X</div>
</div>
<button id="slide">Slide</button>
CSS:
#reels > div {
width: 20px;
height:30px;
overflow:hidden;
padding:3px;
display:inline-block;
}
#reels > div.reel-change {
animation: slideReel 1s 1;
}
#keyframes slideReel {
0% {
transform: translateY(0);
}
49% {
transform: translateY(-30px);
}
50% {
transform: translateY(30px);
}
100 % {
transform: translateY(0px);
}
}
#reels {
margin-bottom:10px;
}
JavaScript:
$(function() {
$('#slide').click(function() {
var delay = 0;
$('#reels').children().each(function() {
var reel = this;
setTimeout(function() {
$(reel).toggleClass("reel-change");
}, delay);
setTimeout(function() {
changeLetter(reel);
}, delay + 500);
setTimeout(function() {
$(reel).toggleClass("reel-change");
}, delay + 1000);
delay += 500;
});
});
});
function changeLetter(el) {
el.innerHTML = incrementChar(el.innerHTML);
}
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
function incrementChar(c) {
var index = alphabet.indexOf(c);
return alphabet[index + 1] || alphabet[0];
}
Edit: Seeing as it's a good reason for doing it based on your above comments, I made it a bit prettier!!
https://jsfiddle.net/bigalreturns/ctuujz3j/2/
For the record, this is what you can do...
var strMsg = 'abcdef';
var tmpStr = '';
function nextLetter(letter) {
var charCode = letter.charCodeAt(0);
return String.fromCharCode((charCode - 96) % 26 + 97)
}
for(var i=0; i < strMsg.length; i++) {
tmpStr += nextLetter(strMsg[i]);
}
console.log(tmpStr); // bcdefg

How to fade in and out one by one using css animation and angular?

Consider the following plunker
I have a list of tile that I want to fade in one by one using ng-repeat however the animation fade the entire tile set all together.
Here is my CSS
.fade-up {
animation: fadeUpIn 5s ease-in-out;
}
.fade-in {
animation: fadeUpOut 5s ease-in-out;
}
#keyframes fadeUpIn {
0% {
opacity: 0;
transform: translate3d(0, 100%, 0);
}
100% {
opacity: 1;
transform: none;
}
}
Here is my template:
<div ng-controller="baseController as bCtrl">
<button ng-click="bCtrl.toggleStuff()">
Toggle
</button>
<div ng-repeat="group in bCtrl.groupList">
<div class="tile-style"
ng-repeat="tile in group"
ng-class="{'fade-up': bCtrl.display, 'fade-in': !bCtrl.display}">
{{tile}}
</div>
</div>
</div>
Here is my JS
function toggleStuff() {
self.display = !self.display;
}
Is there a way to fade in the tiles individually?
u want it animate one by one, an easy way is to set them to display one by one, custom ng-animate might cost more
u may need to record timeouts and clear when change happen during loop
for (var i = 0; i < 10; i++) {
(function(a) {
setTimeout(function() {
console.log(a); //0,1,2...
//$scope.list[a].display = false;
//$scope.$apply()
}, i * 1000);
})(i)
}
As the other answer suggests, you could do this adding timeouts.
I have applied the solution in your plunker.
http://plnkr.co/edit/RV6E20IP5VLrMDKkOr4G?p=preview
for (var i = 1; i < 26; i++) {
tile = { val: i , display: false };
if (i % 4 == 0){
tempList.push(tile);
self.groupList.push(tempList);
tempList = []
} else {
tempList.push(tile);
}
(function(index, tile) {
$timeout(function() {
tile.display = true;
}, i * 400);
})(i, tile);
}

Categories