Random image slideshow, image transition fade in/out? - css

I am using this script for a random image slideshow, trying to display sponsor images. The script works fine, I'm trying to create a fade in and/or fade out effect to it.
The script:
<script>
var delay=4000
var curindex=0
var randomimages=new Array()
randomimages[0]="https://cdn4.sportngin.com/attachments/photo/5aed-137970385/cambria_large.jpg"
randomimages[1]="https://cdn1.sportngin.com/attachments/photo/acab-137970605/9Round_large.png"
randomimages[2]="https://cdn2.sportngin.com/attachments/photo/a12b-137971067/qdoba_large.jpg"
randomimages[3]="https://cdn1.sportngin.com/attachments/photo/fcf5-137974579/chipotle_large.jpg"
randomimages[4]="https://cdn3.sportngin.com/attachments/photo/3397-137974001/countryinn_large.jpg"
var preload=new Array()
for (n=0;n<randomimages.length;n++)
{
preload[n]=new Image()
preload[n].src=randomimages[n]
}
document.write('<img class="fade-in" name="defaultimage" height="294" width="294" style="display:block; margin-left:auto; margin-right:auto;" src="'+randomimages[Math.floor(Math.random()*(randomimages.length))]+'">')
function rotateimage()
{
if (curindex==(tempindex=Math.floor(Math.random()*(randomimages.length)))){
curindex=curindex==0? 1 : curindex-1
}
else
curindex=tempindex
document.images.defaultimage.src=randomimages[curindex]
}
setInterval("rotateimage()",delay)
</script>
The script itself works fine.
This is the CSS I've tried for the image transition:
.fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 4s;
}
#keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
When the page loads the fade in works on the first image, but none of the subsequent ones JSFiddle. I'm hoping someone could steer me in the right direction.

Here a solution, add notes inside:
var delay=4000
var curindex=0
var randomimages=new Array()
randomimages[0]="https://cdn4.sportngin.com/attachments/photo/5aed-137970385/cambria_large.jpg"
randomimages[1]="https://cdn1.sportngin.com/attachments/photo/acab-137970605/9Round_large.png"
randomimages[2]="https://cdn2.sportngin.com/attachments/photo/a12b-137971067/qdoba_large.jpg"
randomimages[3]="https://cdn1.sportngin.com/attachments/photo/fcf5-137974579/chipotle_large.jpg"
randomimages[4]="https://cdn3.sportngin.com/attachments/photo/3397-137974001/countryinn_large.jpg"
var preload=new Array()
for (n=0;n<randomimages.length;n++)
{
preload[n]=new Image()
preload[n].src=randomimages[n]
}
//document.write('<img class="fade-in" name="defaultimage" height="294" width="294" style="display:block; margin-left:auto; margin-right:auto;" src="'+randomimages[Math.floor(Math.random()*(randomimages.length))]+'">')
// place the image on container:
document.querySelector('figure').innerHTML = '<img class="fade-in" name="defaultimage" height="294" width="294" style="display:block; margin-left:auto; margin-right:auto;" src="'+randomimages[Math.floor(Math.random()*(randomimages.length))]+'">';
function rotateimage()
{
document.querySelector('figure').innerHTML = ''; // clear image from container
if (curindex==(tempindex=Math.floor(Math.random()*(randomimages.length)))){
curindex=curindex==0? 1 : curindex-1
}
else
curindex=tempindex
// document.images.defaultimage.src=randomimages[curindex]
// place image with different source on the container
document.querySelector('figure').innerHTML = '<img class="fade-in" name="defaultimage" height="294" width="294" style="display:block; margin-left:auto; margin-right:auto;" src="'+randomimages[curindex]+'">';
}
setInterval("rotateimage()",delay)
.fade-in {
opacity: 1;
animation-name: fadeInOpacity;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 4s;
}
#keyframes fadeInOpacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<figure></figure>
Additional important notes:
The key here is to create the element so the class will work. Now you are just changing src attribute so the class doesn't change (you can inspect that on browser dev tools).
On your code you use document.write. I change it to .innerHTML - both consider to be BAD practices on production. You should create and append nodes instead. I use it here cause it fast.

Related

How to skip to a specific time in css-animations by seconds?

is there any way to skip to specific time in css animation?
for example: if we have a div moving from left to right in 10 seconds, user change time to 5 and animation jumps to second 5 and continues playing.
Changing animation-delay will do exactly that.
When you change it to negative values, it will jump forward.
const selectElement = document.querySelector('.number');
selectElement.addEventListener('change', (event) => {
const result = document.querySelector('.some-div');
result.style.animationDelay = `${event.target.value}s`;
});
.some-div {
width: 100px;
height: 100px;
background-color: red;
animation-name: example;
animation-duration: 20s;
animation-delay: 0;
}
#keyframes example {
from {
transform: translateX(0px);
}
to {
transform: translateX(400px);
}
}
<div class="some-div"></div>
<input type="number" class="number" />
<br/>
change the value in the input

CSS End a keyframe looping animation and have it animate back to start

I have a looping animation that rotates a square. When I remove the class that enables the animation, the square instantly goes back to the starting position.
I need to be able to animate the square back to the starting position on a JS event.
Here is a codepen.
I have tried adding a transform to the element, and switching to another keyframe animation but neither worked.
html:
<div class="container">
<div class="animate rotating"></div>
</div>
css:
.container{
position: absolute;
width: 100%;
height: 100%;
background-color: #333;
}
.animate{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
transform: all 2s ease;
}
#keyframes rotating {
0%{transform: rotate(30deg);}
50%{transform: rotate(-30deg);}
100%{transform: rotate(30deg);}
}
.rotating {
animation: rotating 6s ease-in-out infinite forwards;
animation-delay: -2s;
}
jquery:
$('.animate').click(function(){
$(this).removeClass('rotating');
});
There is a little problem with your code:
transform: all 2s ease;
You mistyped transition, however I'm pretty sure this approach isn't going to work. If you're willing to accomplish this using jQuery you can get current rotation and apply to your element:
function getRotationDegrees(obj) {
var matrix = obj.css("-webkit-transform") ||
obj.css("-moz-transform") ||
obj.css("-ms-transform") ||
obj.css("-o-transform") ||
obj.css("transform");
if(matrix !== 'none') {
var values = matrix.split('(')[1].split(')')[0].split(',');
var a = values[0];
var b = values[1];
var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
} else { var angle = 0; }
return (angle < 0) ? angle + 360 : angle;
}
$('.animate').click(function(){
var el = $(this);
var elRotate = getRotationDegrees(el);
el.css('transform',`rotate(${elRotate}deg)`);
el.removeClass('rotating');
// set new transform here
});
This will freeze your element rotation, you can set your desired rotation at the end and transition will be applied.

Angular: Hightlight animation on table rows

Situation
I have a table with devices and their statuses. When I click on a specific button the rows that have the offline status need to have a highlight for a couple of seconds and then return back to normal.
What I have so far
<tr id="deviceRow" class="user-item" *ngFor="let device of group.devices" (click)="$event.stopPropagation()" [class.highlightOn]="this.offlineHighlight == true && device.onlineState == 'Offline'">
When I click on the button the offlineHighlight boolean becomes true and it adds the highlightOn class which is this.
.highlightOn {
background-color: rgb(255, 68, 65);
-webkit-animation: fade-out 3s ease-out both;
animation: fade-out 3s ease-out both;
}
#-webkit-keyframes fade-out {
0% {
background-color: rgba(255,51,47,1);
}
100% {
background-color: transparent;
}
}
#keyframes fade-out {
0% {
background-color: rgba(255,51,47,1);
}
100% {
background-color: transparent;
}
}
This adds the 'highlight' animation.
After the animation is completed I set the offlineHighlught boolean to false again in the button code.
showOfflineDevices() {
this.offlineHighlight = true;
this.tabIndex = 1;
setTimeout(function(){
this.offlineHighlight = false;
}, 3000);
}
It all works fine until the animation has completed. Standard the table rows have different background colors for each odd even row. When the animation is complete all the rows that had the highlightOn class have a white background color as you can see here.
TL:DR The background color of the table rows need to go back to normal after the animation is completed. The even rows are also white now, which need to be grey.
It's because you set background-color to transparent on fade-out, you can simply use transitions like this (just add and remove class with additional styles, don't override existing styles on fade-out):
setInterval(() => {
$(".color").addClass("selected");
setTimeout(() => {
$(".color").removeClass("selected")
}, 2500);
}, 5000);
div {
transition: background-color .5s ease;
}
div:nth-child(odd) {
background-color: lightgray;
}
div:nth-child(even) {
background-color: gray;
}
.selected {
background-color: green !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>1</div>
<div class="color">2</div>
<div class="color">3</div>
<div>4</div>
<div>5</div>

Queued CSS animations using delay or keyframes that can be interrupted smoothly

First, a fiddle: http://jsfiddle.net/AATLz/
The essence here is that there's a set of animations queued using -webkit-transition-delay. First element 0.4s, second 0.8s, third 1.4s, etc. They're queued last to first by default, and first to last when the parent has the 'expanded' class (toggled with that button).
This means that the animation when '.expanded' is added brings the boxes out one by one, and in reverse when the class is removed.
That's dandy. The problems start to arise when the class is toggled mid-animation. If you toggle, say, after the second box has animated, there's a delay before they start animating back, because a couple delay timers are being waited out.
Delays are obviously a bit clunky here.
The two alternatives I have in mind are 1) CSS keyframe animations, which I'm not entirely sure of how to activate on multiple elements in succession, and 2), JS controlled timing - using something like jQuery Transit. I'm not sure which would be more capable/graceful or if I'm missing another option.
Any input would be awesome!
jsfiddle: http://jsfiddle.net/Bushwazi/fZwTT/
Changed it up a bit. Control the timing with js. Animations with css.
CSS:
* {
margin:0;
padding:0;
}
#container {
background: orange;
height: 100px;
position: relative;
width: 100px;
}
.box {
height: 100px;
left: 0;
position: absolute;
top: 0;
width: 100px;
-webkit-transition:all 0.5s ease-in-out 0s;
-moz-transition:all 0.5s ease-in-out 0s;
-o-transition:all 0.5s ease-in-out 0s;
transition:all 0.5s ease-in-out 0s;
-webkit-transform: translate3d(0,0,0);
}
.box-1 {
background: red;
}
.box-2 {
background: green;
}
.box-3 {
background: yellow;
}
.box-4 {
background: blue;
}
.box-1 .box-1 {
left:100px;
}
.box-2 .box-2 {
left:200px;
}
.box-3 .box-3 {
left:300px;
}
.box-4 .box-4 {
left:400px;
}
HTML:
<div id="container" class="box-0" data-status="default" data-box="0">
<div class="box box-1"></div>
<div class="box box-2"></div>
<div class="box box-3"></div>
<div class="box box-4"></div>
</div>
<button id="ToggleAnim">Toggle</button>
JS:
(function(){
var testies = {
to: 0,
init: function(){
$button = $('#ToggleAnim');
$anim_elm = $('#container');
$(function(){
testies.el();
});
},
el: function(){ // el ==> event listeners
$button.on('click', testies.toggleBoxes);
},
toggleBoxes: function(evt){
var status = $anim_elm.attr('data-status'),
pos = $anim_elm.attr('data-box');
window.clearTimeout(testies.to);
// if default ==> build
// if killing ==> build
// if building ==> kill
// if done ==> kill
if(status == 'build' || status == 'done'){
testies.kill();
} else {
testies.build();
}
evt.preventDefault();
},
build: function(){
bpos = $anim_elm.attr('data-box');
if(bpos < 4){
bpos++;
$anim_elm.attr('data-status', "build").attr('data-box', bpos).addClass('box-' + bpos);
testies.to = window.setTimeout(testies.build, 500);
}
if(bpos == 4)$anim_elm.attr('data-status', "done");
console.log('BUILD: ' + bpos);
},
kill: function(){
kpos = $anim_elm.attr('data-box');
if(kpos > 0){
db = kpos - 1;
$anim_elm.attr('data-status', "kill").attr('data-box', db).removeClass('box-' + kpos);
testies.to = window.setTimeout(testies.kill, 500);
}
console.log('KILL: ' + kpos);
if(kpos == 0)$anim_elm.attr('data-status', "default")
}
}
testies.init();
})();

How to make a CSS3 animation reusable?

Without JQuery.
I have the following code but it will only work on one click. It will not be able to be used twice:
#-moz-keyframes lulse {
0%{
-moz-transform:scale(1);
}
20%{
-moz-transform:scale(1.5);
}
100% {
-moz-transform:scale(1);
}
}
.pinto {
-moz-animation-name: lulse;
-moz-animation-duration: .2s;
-moz-animation-iteration-count: 1;
-moz-animation-timing-function: linear;
-moz-animation-direction: normal;
}
Javascript:
onclick="changeClass(this.id);
function changeClass(a)
{
document.getElementById(a).className += "pinto";
}
Hmm, on the surface it looks like you should be able to remove the class at the beginning of your click handler if it exists. Specifically:
function changeClass(a) {
var elementA = document.getElementById(a);
var regEx = new RegExp('(\\s|^)pinto(\\s|$)');
elementA.className = elementA.className.replace(regEx,' ');
elementA.className += " pinto";
}
This will remove the class and reapply it, which should restart the effect.

Resources