Changing css animation in javascript - javascript

I have a blinking red box in my html it uses css animations. I want to to be able to change it from blinking red and white to green and white. I know this can be done on id elements by using getElementbyId but how would get access to the green aminated box in the css.
The red box looks like this:
#-webkit-keyframes 'noConnection'
{
1% { background-color: red; }
33% { background: white; }
66% { background: red; }
100% { background: white; }
}
The green is this:
#-webkit-keyframes 'Connection'
{
1% { background-color: green; }
33% { background: white; }
66% { background: green; }
100% { background: white; }
}
The animate looks like this:
#animate {
height: 15px;
width: 15px;
}
.cssanimations #animate {
-webkit-animation-direction: normal;
-webkit-animation-duration: 5s;
-webkit-animation-iteration-count: infinite;
-webkit-animation-name: Connection;
-webkit-animation-timing-function: ease;
and I think I have to change the attribute -webkit-animation-name: from javascript to do this but I dont know how to get a handle on it to change it.
Or would I be better off creating a duplicate #animate and renaming it using the getElementById?

Here is a simple web page that demonstrates how to use Javascript to modify a CSS animation. It contains a simple div, and a little Javascript causes the div to move randomly around the page.
In your specific case, you just need to touch up the line that calls "insertRule" to insert your new blinking rule.
<html><head><style></style></head>
<body>
<div id="mymovingdiv">
<h1>Moving Div</h1>
<p>And some little text too</p>
</div>
<script>
function animatedMove(id, xStart, yStart, xEnd, yEnd, secs)
{
// Remove any CSS rules inserted by a previous call to this method
let rulename = `AnimMove${id}`;
let ss = document.styleSheets; // all stylesheets
for (let i = 0; i < ss.length; ++i) { // for each stylesheet...
for (let j = ss[i].cssRules.length - 1; j > 0; j--) { // for each rule...
if (ss[i].cssRules[j].name === rulename) { // does the name match?
ss[i].deleteRule(j);
}
}
}
// Insert a CSS rule for this animation
document.styleSheets[0].insertRule(`#keyframes ${rulename} { 0% { left: ${xStart}px; top: ${yStart}px; } 100% { left: ${xEnd}px; top: ${yEnd}px } }`);
// Remove any CSS rules inserted by a previous call to this method
for (let i = 0; i < ss.length; ++i) { // for each stylesheet...
for (let j = ss[i].cssRules.length - 1; j > 0; j--) { // for each rule...
if (ss[i].cssRules[j].name === rulename) { // does the name match?
ss[i].deleteRule(j);
}
}
}
// Insert a CSS rule for this animation
document.styleSheets[0].insertRule(`#keyframes ${rulename} { 0% { left: ${xStart}px; top: ${yStart}px; } 100% { left: ${xEnd}px; top: ${yEnd}px } }`);
// assign the animation to our element
let el = document.getElementById(id);
el.style.position = 'absolute';
el.style.animation = `${rulename} ${secs}s`;
// Make the element stay where the animation ends
el.style.left = `${xEnd}px`;
el.style.top = `${yEnd}px`;
// Re-clone the element, to reset the animation
el.parentNode.replaceChild(el.cloneNode(true), el);
}
let x = 0;
let y = 0;
function randomMove()
{
let newX = Math.floor(Math.random() * 800);
let newY = Math.floor(Math.random() * 600);
animatedMove('mymovingdiv', x, y, newX, newY, 1);
x = newX;
y = newY;
}
setInterval(randomMove, 1000);
</script>
</body>
</html>

The easiest way to do this is to created two classes in CSS and then toggle between the two.
So something like:
.connection {
animation: 'Connection' 5s ease infinite
}
.no-connection {
animation 'noConnection' 5s ease infinite
}
And then use Javascript to toggle between the two
function toggleConnectionStatus(){
var element = document.getElementById('animate');
if(/* connection is active */) element.className = 'connection';
else element.className = 'no-connection'
}

Related

Softly Transition HTML Images with Javascript

I am trying to use JS to switch images, the code does what it is supposed to and switches the images, however, I want a fade out-fade in effect to the image transition. I tried to declare a CSS Transition for opacity and change the opacity first, which didn't work, then I tried to change the opacity with plain JS, however that didn't work either, what would be the best way to achieve this?
My Poorly Designed Image Change Code:
image = [
"image_1.png",
"image_2.png",
"image_3.jpeg"
];
updateImg = async() => {
console.log("Pulling Image Change")
var img = document.getElementById("img-pan");
console.log(`Got ${img} with current src ${img.src}`)
var exi_bool = false;
for(i = 0; i < image.length - 1; i++) {
if(img.src.endsWith(image[i])) { exi_bool = true; console.log(`Found current src to == image[${i}]`) ;break; }
}
if(!exi_bool) {
img.src = image[0];
}else {
if(i < image.length - 1) { i++ }else { i = 0 }
img.src = image[i];
}
}
If I understood well, before you replace the image add a class that define the opacity to 0.3 for example.
document.getElementById("MyElement").classList.add('MyClass');
when the image change you remove the class.
document.getElementById("MyElement").classList.remove('MyClass');
Note that your image has to be set on css as opacity: 1 and transition x seconds.
Will use css style animation, just change class name, is simple to use and build.
but when css animation start to change css property,no way could change same property but other css animation.
let imgArray = [
'https://fakeimg.pl/100x100/f00',
'https://fakeimg.pl/100x100/0f0',
'https://fakeimg.pl/100x100/00f'
];
let img = document.getElementsByTagName('img')[0];
//only two function
async function fadeOut(element) {
element.className = 'fade-out';
}
async function fadeIn(element) {
element.className = 'fade-in';
}
//
let i = 0;
function loop() {
img.src = imgArray[i % 3];
i++;
fadeIn(img).then(res => {
setTimeout(() => {
fadeOut(img).then(res => {
setTimeout(() => {
loop();
}, 1000);
})
}, 1000);
})
}
loop();
img {
position: relative;
left: 0; /* or use transform */
opacity: 1;
transition: 1s;
width: 100px;
display: block;
margin: auto;
}
.fade-in {
animation: fade-in 1s;
}
#keyframes fade-in {
0% {
left: 100px; /* or use transform */
opacity: 0;
}
100% {
left: 0; /* or use transform */
opacity: 1;
}
}
.fade-out {
animation: fade-out 1s both;
}
#keyframes fade-out {
0% {
left: 0; /* or use transform */
opacity: 1;
}
100% {
left: -100px; /* or use transform */
opacity: 0;
}
}
<img src="https://fakeimg.pl/100x100/#f00">

Setting timeout function based on animation delay

I need to set my .screens to be display: none until the point when its animation starts. Each one has a separate animation-delay so what I hope to achieve is that a function will check how long the animation delay is and that will then determine the length of the setTimeout function.
Example:
If .screens has an animation delay of 3 seconds, then after 3 seconds I want display to change from none to block.
Code of the function I have written so far is below:
var screens = document.getElementsByClassName('screen');
for (var i=0;i<screens.length;i++){
if (screens[i].style.animationDelay >=0){
setTimeout(function(){
this.style.display = "block";
}, this.style.animationDelay);
}
}
You can try this. (You can skip the first part, it is there just to generate screens with random animationDelay)
const generateScreens = () => {
for (let i = 0; i < 5; i++) {
let el = document.createElement('div');
el.className = 'screen';
el.style.animationDelay = Math.floor(Math.random() * 5) + 's';
document.body.appendChild(el);
}
}
generateScreens();
// code that you have asked for starts here
const screens = document.getElementsByClassName('screen');
[...screens].forEach(item => {
const delay = item.style.animationDelay.slice(0, item.style.animationDelay.length - 1);
setTimeout(() => {
item.style.display = 'block';
}, delay * 1000);
});
div.screen {
width: 40px;
height: 40px;
background: red;
border: 1px solid black;
display: none;
}
Since you cannot animate the state/value from none to block of the display property, you can instead do it with the visibility: hidden / visibility: visible pair, and of course you could also do it with the opacity: 0 / opacity: 1:
.screen {
visibility: hidden;
animation: animate forwards;
}
.screen:first-child {animation-delay: 1s}
.screen:nth-child(2) {animation-delay: 2s}
.screen:nth-child(3) {animation-delay: 3s}
#keyframes animate {
to {visibility: visible}
}
<div class="screen">1</div>
<div class="screen">2</div>
<div class="screen">3</div>
Then you can just target the .screen elements with the :nth-child or :nth-of-type selectors.

How to convert a jQuery fade effect in CSS?

I have the following code which is going to fade some images but I am interested if there is a way to handle this in CSS.
$("#top").stop(true, true).delay(0).fadeTo(fadeTime * 100, 0);
$("#back").stop(true, true).delay(0).fadeTo(fadeTime * 100, 1, function () {
if (curLoop < loops) {
if (curImg < imgNo) {
prevImg = curImg
curImg++
} else {
prevImg = imgNo
curImg = 1;
curLoop++console.log("LOOP");
}
document.getElementById("back").style.opacity = 0;
document.getElementById("top").style.opacity = 1;
document.getElementById("back").src = "frames/frame_" + curImg + ".jpg";
document.getElementById("top").src = "frames/frame_" + prevImg + ".jpg";
} else {
console.log("STOPPED");
window.clearInterval(myVarSTD);
}
if (!initialized) {
myVarSTD = setInterval(function () {
startAnimation()
}, delay * 1000);
initialized = true;
}
});
You can't loop through image sources in a pure CSS animation but the below fade effect is possible with CSS3 animations. Here the front and back images are absolutely positioned and using opacity animation they are faded in and out in an infinite loop. I have used 2 div with background-image but you could do the same for img element also.
Refer inline comments within the snippet for more explanation of the animation's CSS code.
.front,
.back {
position: absolute; /* absolute positioning puts them one on top of other */
height: 200px;
width: 200px;
animation: fade-in-out 10s linear infinite; /* first is animation keyframe's name, second is the duration of the animation, third is timing function and fourth is iteration count */
}
.front {
background-image: url(http://lorempixel.com/200/200/nature/1);
}
.back {
background-image: url(http://lorempixel.com/200/200/nature/2);
z-index: -1; /* keeps the element behind the front */
animation-delay: 5s; /* delay is equal to half the animation duration because the back has to fade-in once the front has faded-out at 50% */
}
#keyframes fade-in-out { /* animation settings */
0%, 100% {
opacity: 1; /* at start and end, the image is visible */
}
50% {
opacity: 0; /* at the mid point of the animation, the image is invisible */
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class='front'></div>
<div class='back'></div>
Yes, it is. Your code capture some elements using getElementById as back and top.
You can use the following code to change CSS properties of those elements:
$('#back').css({'opacity':'1'});
Implemented in your code:
$("#top").stop(true, true).delay(0).fadeTo(fadeTime*100, 0);
$("#back").stop(true, true).delay(0).fadeTo(fadeTime*100, 1, function(){
if(curLoop<loops){
if(curImg<imgNo){
prevImg = curImg
curImg++
}else{
prevImg = imgNo
curImg = 1;
curLoop++
console.log("LOOP");
}
$('#back').css({'opacity':'0'});
$('#top').css({'opacity':'1'});
document.getElementById("back").src = "frames/frame_"+curImg+".jpg";
document.getElementById("top").src = "frames/frame_"+prevImg+".jpg";
}else{
console.log("STOPPED");
window.clearInterval(myVarSTD);
}
if(!initialized){
myVarSTD = setInterval(function(){startAnimation()},delay*1000);
initialized = true;
}
});
jQuery Transit is an awesome plugin which mimics jQuery's animation functions but in CSS. You get a much higher framerate using CSS too!

How can I add a pulse animation to a div in an array of divs, in Javascript?

I have an array of divs that I create programmatically, like so:
// Create grid of pads dynamically, 16x16 in size
var padIdCount = 0;
for (var i = 0; i < 16; i++) {
for (var j = 0; j < 16; j++) {
var newPad = document.createElement("div");
WinJS.Utilities.addClass(newPad, "pad");
WinJS.Utilities.addClass(newPad, "row" + i);
WinJS.Utilities.addClass(newPad, "col" + j);
newPad.id = "pad" + padIdCount;
document.getElementById("padContainer").appendChild(newPad);
padIdCount++;
}
// Add a single line break after 16 pads
var newLineBreak = document.createElement("br");
document.getElementById("padContainer").appendChild(newLineBreak);
}
Pads are dark grey, but if a user taps on a pad it becomes an "active pad"
// Assign handler to pads, to toggle activation on click
var pads = document.querySelectorAll(".pad");
for (var padCount = 0; padCount < pads.length; padCount++) {
pads[padCount].addEventListener("click", togglePadActivation, false);
}
function togglePadActivation(e) {
// Get id of pad in question
var padId = e.target.id;
// Change pad from active to inactive and vice versa
var clickedPad = document.getElementById(padId);
WinJS.Utilities.toggleClass(clickedPad, "activePad");
}
Styles
/* dark grey */
.pad {
height: 40px;
width: 40px;
margin: 1px;
padding: 0px;
background-color: #363636;
display: inline-table;
}
/* dark orange */
.activePad {
background-color: orangered;
opacity: 0.6;
}
.playingPad {
background-color: orangered;
opacity: 0.6;
/* workaround for pulse bug */
animation: pulselightonanimation 3.2s ease-out;
animation-iteration-count: infinite;
}
#keyframes pulselightonanimation {
0% {opacity: 1.0;}
50% {opacity: 0.8;}
100% {opacity: 0.6;}
}
Now that setup is complete, and event handlers are hooked up, the user can click a button that starts looping through all active pads (row 1 first, simultaneously, then row 2 simultaneously, and so on). To achieve this, I implemented a setTimeout.
// Run this method every 200ms
function playActiveNotes(rowCount) {
timer = setTimeout(function () {
// Reset after the last row, because we are looping indefinitely
if (rowCount === 16) {
rowCount = 0;
}
// Select all pads from the same row at once
var currentRow = ".row" + rowCount;
var currentRowPads = document.querySelectorAll(currentRow);
// Cycle through each pad, animate and play it if active
for (var padCount = 0; padCount < currentRowPads.length; padCount++) {
// If the pad is active play the note
if (WinJS.Utilities.hasClass(currentRowPads[padCount], "activePad")) {
// Show the pulse animation
WinJS.Utilities.addClass(currentRowPads[padCount], "playingPad");
// TODO: Play short mp3 file here
// Remove the animation class. This is where it fails
//currentRowPads[padCount].addEventListener("animationend", callback(currentRowPads[padCount]), false);
//currentRowPads[padCount].addEventListener("transitionend", callback(currentRowPads[padCount]), false);
// If I use a nested setTimeout, this removeClass code never gets called. If I comment it out, I don't see the pulse, i.e. add + remove happens too quickly
//setTimeout(function () {
if (padCount < 16)
WinJS.Utilities.removeClass(currentRowPads[padCount], "playingPad");
//}, 1000);
}
}
// Go to the next row
rowCount++;
// Then call self to setup a recursive loop.
playActiveNotes(rowCount);
}, 200);
}
function callback(element) {
element.classList.remove('playingPad');
}
When the active pad is being played (I play a short mp3 file), I want it to pulse, i.e. become bright orange quickly (but not instantaneously), then fade back to the original dark orange. How can I achieve this? I tried using a playing pad class with css animation, and removing the class on transitionend/animation end, but that didn't work.
Use of WinJS is allowed in addition to Javascript, but no JQuery.
I think if somehow you can get a CSS animation going, that that would still be the best solution.
However, this is an alternative solution, using CSS transitions:
/* dark grey */
.pad {
height: 40px;
width: 40px;
margin: 1px;
padding: 0px;
background-color: #363636;
display: inline-table;
}
/* dark orange */
.activePad {
background-color: #B2371B;
transition: background-color .5s;
-webkit-transition: background-color .5s;
}
/* bright orange */
.brightPad {
background-color: #FFFFFF;
transition: background-color .1s;
-webkit-transition: background-color .1s;
}
This should make it so that if you add the .brightPad class to a pad, that it goes quickly to bright orange (in .1s). As soon as you remove that class and set .activePad again, it should go slowly back to dark orange (.5s). You will have to set the .brightPad right on touch, and then remove it again using a timeout of 100ms or more.
Here is a quick JSFiddle: http://jsfiddle.net/R5VjH/1/
(sorry, used white instead of picking a nice bright orange)

Array slide show not working smoothly with javascript

Written some javascript (very new to this) to center the div and make it full screen adjusting as the window does, that works fine but now I have added some script I found online to transition from one image to another using an array. They seem to be contradicting each other messing up the animation, the biggest problem is when I resize the window. Here is my jsfiddle so you can see for yourself. Thanks in advance.
http://jsfiddle.net/xPZ3W/
function getWidth() {
var w = window.innerWidth;
x = document.getElementById("wrapper");
x.style.transition = "0s linear 0s";
x.style.width= w +"px";
}
function moveHorizontal() {
var w = window.innerWidth;
x = document.getElementById("wss");
x.style.transition = "0s linear 0s";
x.style.left= w / 2 -720 +"px" ;
}
function moveVertical() {
var h = window.innerHeight;
x = document.getElementById("wss");
x.style.transition = "0s linear 0s";
x.style.top= h / 2 -450 +"px" ;
}
var i = 0;
var wss_array = ['http://cdn.shopify.com/s/files/1/0259/8515/t/14/assets/slideshow_3.jpg? 48482','http://cdn.shopify.com/s/files/1/0259/8515/t/14/assets/slideshow_5.jpg?48482'];
var wss_elem;
function wssNext(){
i++;
wss_elem.style.opacity = 0;
if(i > (wss_array.length - 1)){
i = 0;
}
setTimeout('wssSlide()',1000);
}
function wssSlide(){
wss_elem = document.getElementById("wss")
wss_elem.innerHTML = '<img src="'+wss_array[i]+'">';
wss.style.transition = "0.5s linear 0s";
wss_elem.style.opacity = 1;
setTimeout('wssNext()',3000);
}
So I whipped up this JSFiddle from scratch, and I hope it helps out. Pure CSS transitions from class to class using your array URLs to switch among the pictures.
Basically this just advances the "active" class to the next one everytime it's called, provided the first picture is set to "active" class.
var pics = document.getElementById('slideshow').children,
active = 0;
function slideshow() {
for (var i = 0; i < pics.length; i++) {
if (i == active && pics[i].className == "active") {
console.log(i, active, (active + 1) % pics.length);
active = (active + 1) % pics.length;
}
pics[i].className = "";
}
pics[active].className = "active";
setTimeout(slideshow, 2000);
}
setTimeout(slideshow, 2000);
And here's the CSS, which absolutely positions the container, and hides all its children unless it has the active class, to which it will transition smoothly.
#slideshow {
position: absolute;
top: 20%;
bottom: 20%;
left: 20%;
right: 20%;
}
#slideshow img {
position: absolute;
max-height: 100%;
max-width: 100%;
opacity: 0;
transition: opacity 1s linear;
}
#slideshow .active {
opacity: 1;
}

Categories