Here I have a Video that changes every few seconds with spinning animation + video getting small and big during the spinning.
But over time the timing gets out of order.
let degree = 720;
function rotateElement(){
let spin = `rotate(${degree}deg)`;
document.getElementById('myVideo').style.transform = spin;
document.getElementById('myVideo').style.transitionDuration = "1s";
degree += 720;
}
function smaller(){
document.getElementById('myVideo').style.maxWidth = "10px";
document.getElementById('myVideo').style.maxHeight = "10px";
document.getElementById('myVideo').style.transitionDuration = "1s";
}
function bigger(){
document.getElementById('myVideo').style.maxWidth = "30vw";
document.getElementById('myVideo').style.maxHeight = "19vw";
document.getElementById('myVideo').style.transitionDuration = "1s";
}
//setInterval(change, 5000);
window.onload = function () {
setInterval(change, 5000);
setInterval(rotateElement, 4900);
setInterval(smaller, 4850);
setInterval(bigger, 5050);
};
Not sure exactly what you want the animation to do with the rotate, but this is the basic idea of just doing it in CSS.
.test {
background-color: yellow;
/*animation: shrink 5s 3s ease infinite, rotate 50s steps(10, end) forwards infinite; */
animation: shrink 5s 3s ease infinite, rotate 50s forwards infinite;
transition: width 1s, height 1s;
overflow: hidden;
width: 30vw;
height: 19vh;
}
#keyframes shrink {
0%,
65%,
90%,
100% {
width: 30vw;
height: 19vh;
}
70% {
width: 14px;
height: 10px;
}
}
#keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
<img class="test" src="http://placekitten.com/200/100">
I'm trying to add an animation to an element when someone hover on it.
My thought is to add a class with keyframes and attach an mouseover event listener to it.
The reason I don't use CSS is because I want the animation to be finished even the mouse leave the element before the animation is finished. For example, the mouse is moved out of element when rotating on 180 degree (full animation is 360 degree)
But sadly it's not working and I don't know why...
const item = document.querySelector('#rotate');
item.addEventListener('mouseover',function(e) {
if(item) e.classList.add('rotate');
});
#div {
width: 120px;
height: 120px;
background-color: orange;
}
.rotate {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div id='rotate'></div>
You're already on the right path. You can listen for the animationend event on the div and remove the rotate class when the event is fired. I've corrected your example snippet below.
const item = document.querySelector('#rotate');
item.addEventListener('mouseover', function(e) {
if(item) item.classList.add('rotate');
});
item.addEventListener('animationend', function(e) {
if(item) item.classList.remove('rotate');
});
#rotate {
width: 120px;
height: 120px;
background-color: orange;
}
.rotate {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div id='rotate'></div>
I would say you were pretty close. firstly you must change #div to #rotate then add the class directly to the item then when animation is done remove the class so that it can run again
const item = document.querySelector('#rotate');
item.addEventListener('mouseover', function(e) {
item.classList.add('rotate');
});
item.addEventListener('animationend', function(e) {
item.classList.remove('rotate');
});
#rotate {
width: 120px;
height: 120px;
background-color: orange;
}
.rotate {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div id='rotate'></div>
Doesn't change your code too much.
e refers to the event which is incorrect use of it, you should use this to target the current element
use mouseenter will be better in this sitution when you want to trigger an animation when use hover it .
const item = document.querySelector('#rotate');
item.addEventListener('mouseenter',function(e) {
if(item) this.classList.add('rotate');
});
#rotate {
width: 120px;
height: 120px;
background-color: orange;
}
.rotate {
animation: rotating 1s ease 0s 1 normal forwards;
}
#keyframes rotating {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
<div id='rotate'></div>
I am working on solution
I have created a basic html banner where I want to keep image and text animations in sync.
Basically image animation is like scale logo for about 3 seconds, meanwhile logo is animated I want text for same in typing effect
I have created basic solution using css and javascript but it is not in sync
var typewriter = function(txt) {
var container = document.getElementById('typewriter'),
speed = 28,
i = 0,
wordsObj = txt.split(" ")
container.textContent = "";
runAllWords();
function runAllWords() {
if (i < wordsObj.length) {
var a = (i == 0) ? i : i - 1;
setTimeout(function() {
showWord(wordsObj[i], 0)
}, wordsObj[a].length * speed);
}
}
function showWord(word, countWord) {
if (countWord < word.length) {
setTimeout(function() {
showLetter(word, countWord)
}, speed);
} else {
container.textContent = container.textContent + " ";
i += 1;
runAllWords();
}
if (i === wordsObj.length) {
console.log('complete')
}
}
function showLetter(word, countWord) {
container.textContent = container.textContent + word[countWord];
showWord(word, countWord + 1);
}
}
var i = 0;
function myLoop() {
// create a loop function
var dataType = document.getElementById('typewriter').dataset.typewriter,
w = dataType.split(',')
setTimeout(function() { // call a 3s setTimeout when the loop is called
typewriter(w[i]); // your code here
i++; // increment the counter
if (i < w.length) { // if the counter < 10, call the loop function
myLoop(); // .. again which will trigger another
} // .. setTimeout()
}, 3000)
}
myLoop();
.addsp_320x50 {
width: 100%;
height: 50px;
position: relative;
}
.addsp_320x50_img {
position: absolute;
top: 1px;
left: 10px;
width: 48px;
height: 48px;
border: 0px solid #ccc;
border-radius: 50%;
}
.addsp_title_text {
position: absolute;
top: 5px;
left: 70px;
font-family: Open Sans;
font-weight: bold;
}
.addsp_title_desc {
position: absolute;
top: 20px;
left: 70px;
font-family: Open Sans;
color: #999;
}
.addsp_320x50_action button {
height: 27px;
background: #058562;
border-radius: 4px;
color: #fff;
border-color: #058562;
font-size: 12px;
font-weight: bold;
font-family: Open Sans;
border-style: solid;
position: absolute;
right: 10px;
top: 10px;
display: flex;
}
.adz_text_1 {}
.adz_text_2 {
animation: text2;
}
.adz_text_1,
.adz_text_2 {}
#keyframes text2 {
0%,
50%,
100% {
width: 0px;
}
60%,
90% {
width: 200px;
}
}
#keyframes text1 {
0%,
50%,
100% {
width: 0px;
}
10%,
40% {
width: 200px;
}
}
#media only screen and (min-width: 320px) {
.addsp_320x50_img {
width: 42px;
height: 42px;
top: 4px;
left: 5px;
}
.addsp_title_text {
top: 14px;
left: 56px;
font-size: 0.85rem;
}
.addsp_title_desc {
top: 25px;
left: 55px;
font-size: 0.8rem;
}
}
#media only screen and (min-width: 480px) {
.addsp_title_text {
top: 3px;
left: 55px;
font-size: 1.1rem;
}
.addsp_title_desc {
top: 28px;
left: 55px;
font-size: 0.8rem;
}
}
#media only screen and (min-width: 600px) {
.addsp_title_text {
top: 3px;
left: 70px;
font-size: 1.1rem;
}
.addsp_title_desc {
top: 28px;
left: 70px;
font-size: 0.8rem;
}
}
#media only screen and (min-width: 800px) {
.addsp_title_text {
top: 3px;
left: 70px;
font-size: 1.1rem;
}
.addsp_title_desc {
top: 28px;
left: 70px;
font-size: 0.8rem;
}
}
.addsp_320x50_img:nth-child(1) {
animation-name: scale;
animation-duration: 3s;
animation-timing-function: linear;
animation-delay: 1s;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
opacity: 0;
}
.addsp_320x50_img:nth-child(2) {
animation-name: scale;
animation-duration: 3s;
animation-timing-function: linear;
animation-delay: 4s;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
opacity: 0;
}
.addsp_320x50_img:nth-child(3) {
animation-name: scale;
animation-duration: 3s;
animation-timing-function: linear;
animation-delay: 7s;
animation-iteration-count: infinite;
animation-fill-mode: forwards;
opacity: 0;
}
#keyframes scale {
0% {
transform: scale(1);
opacity: 1
}
20% {
transform: scale(1.2);
opacity: 1
}
40% {
transform: scale(1);
opacity: 1
}
60% {
transform: scale(1.2);
opacity: 1
}
80% {
transform: scale(1);
opacity: 1
}
90% {
transform: translateY(-100px);
opacity: 0;
}
100% {
opacity: 0;
}
}
.blinking-cursor {
color: #2E3D48;
-webkit-animation: 1s blink step-end infinite;
-moz-animation: 1s blink step-end infinite;
-ms-animation: 1s blink step-end infinite;
-o-animation: 1s blink step-end infinite;
animation: 1s blink step-end infinite;
}
#keyframes "blink" {
from,
to {
color: transparent;
}
50% {
color: black;
}
}
#-moz-keyframes blink {
from,
to {
color: transparent;
}
50% {
color: black;
}
}
#-webkit-keyframes "blink" {
from,
to {
color: transparent;
}
50% {
color: black;
}
}
#-ms-keyframes "blink" {
from,
to {
color: transparent;
}
50% {
color: black;
}
}
#-o-keyframes "blink" {
from,
to {
color: transparent;
}
50% {
color: black;
}
}
<div class="addsp_320x50">
<img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
<img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
<img src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="addsp_320x50_img">
<div class="addsp_title_text">
<span class="adz_text_1 typewriter" id="typewriter" data-typewriter="Web Strategy,
UX Testing,
Content Management System,
Web Design,
Research and Analytics,
Information Architecture,
Strategic Consulting,Maintenance and Support"></span><span class="blinking-cursor">|</span>
</div>
<div class="addsp_320x50_action">
<button>DOWNLOAD</button></div>
</div>
Mathematically speaking, sinking means adjusting frequency and phase. I'll demonstrate each separately. Note that what I'm gonna explain is the concept and you can implement it in your codes using Javascript, css, etc
Frequency
You can't sink two animations unless the longer duration is a factor
of shorter duration.
For example in your codes, blinking has a duration of 1s. So your image scaling duration and Also the whole duration must be a selection of either 1s, 2s, 3s, ... or 1/2s, 1/3s, ...
For better understanding let me make a simple example. Assume two images want to be animated.
<img src="1.png" id="img1">
<img src="1.png" style="margin-left: 50px;" id="img2">
Consider two different animations for each one
#keyframes k1
{
25%
{
transform: rotate(-4deg);
}
50%
{
transform: rotate(0deg);
}
75%
{
transform: rotate(3deg);
}
100%
{
transform: rotate(0deg);
}
}
#keyframes k2
{
50%
{
transform: scale(1.2);
}
100%
{
transform: scale(1);
}
}
So since k2 is simpler, I'll first assign it to img2 with duration of 0.7s
#img2
{
animation: k2 0.7s linear infinite;
}
And based on what was explained, I will assign animation k1 to img1 with a duration of 1.4s. (NOT 1.3s NOT 1.5s VERY IMPORTANT!)
#img1
{
animation: k1 1.4s linear infinite;
}
If you run this code you'll see they are sink! To feel the concept better, change the duration of k1 to 0.9s. Now it feels like they are doing their thing separately!
Note
I set k1 to 1.4s (0.7s × 2) because k1 seems to be a combination of one go forward and come back and using 2x feels they are dancing together with the same harmony!
Phase
In css, phase is showed by animation-delay. Modifying frequencies (duration) is enough to sink two animations but if two animation begin at the same time it will feel better! So to illustrate set a delay for img1 of 0.2s. They are still sink but it doesn't feel nice! Now change the delay to 0.7s. Now it's beautiful again! (Maybe even more beautiful)
Back to your code
Your images scale with duration of 1.2s (40% of 3s) and your text blinking duration is 1s and as you can see they are not factor of each other so you can't sink!
I think you might be looking for the animation iteration event and the animation start event.
Instead of just using the myLoop function to call itself, try using these listeners to call it instead.
The end of your js file would look like:
var i = 0;
function myLoop() {
var dataType = document.getElementById("typewriter").dataset.typewriter,
w = dataType.split(",");
if (i < w.length -1 ) {
typewriter(w[i]);
}
i++;
}
var imageElems = Array.from(document.querySelectorAll('.addsp_320x50_img'));
imageElems.forEach(elem=>{
elem.addEventListener('animationstart',myLoop);
});
Where ".addsp_320x50_img" is just whatever common selector you give to all the images.
If you control the animation with the same JavaScript loop as the typewriter script, it won't lose sync. I rewrote the typewriter script to do this in the snippet below.
startTypewriter() Exaplaination
First, all the messages from the are collected converted into an array.
typewriter.getAttribute('data-typewriter').split(',');
Then the CSS icon animation is started. Because JavaScript intervals wait for their duration before executing their code, so the first message is typed by calling type() before the interval is created.
icon.classList.add('icon-animation');
type(typewriter, messages[0].trim(), animationDuration - pauseDuration);
The interval is now started, running every 3 seconds by default. The first thing that happens is the animation is reset in case it got out of sync somehow.
icon.classList.remove('icon-animation');
window.setTimeout(function() {
icon.classList.add('icon-animation');
}, 25);
Next, the message is typed by calling type(). Before it ends, a check is run so see if it's on the last array element. If so, it will start over.
if (i == messages.length) i = 0;
type() Exaplaination
At the start, the timePerCharacter value is calculated. The message is split to an array and the typewriter output is cleared
var timePerCharacter = duration / message.length;
var message = message.split('');
typewriter.innerHTML = '';
A loop is created, running every timePerCharacter. The character is outputted to the typewriter output.
typewriter.innerHTML += message[i];
Once all the characters are outputted, the loop is cleared
if (i == message.length) clearInterval(typeLoop);
Snippent
var animationDuration = 3000;
var pauseDuration = 2000;
startTypewriter();
function startTypewriter() {
var typewriter = document.getElementById('typewriter');
var icon = document.getElementById('icon');
var messages = typewriter.getAttribute('data-typewriter').split(',');
icon.classList.add('icon-animation');
type(typewriter, messages[0].trim(), animationDuration - pauseDuration);
var i = 1;
window.setInterval(function() {
icon.classList.remove('icon-animation');
window.setTimeout(function() {
icon.classList.add('icon-animation');
}, 25);
type(typewriter, messages[i].trim(), animationDuration - pauseDuration);
i++;
if (i == messages.length) i = 0;
}, animationDuration);
}
function type(typewriter, message, duration) {
var timePerCharacter = duration / message.length;
var message = message.split('');
typewriter.innerHTML = '';
var i = 0;
var typeLoop = window.setInterval(function() {
typewriter.innerHTML += message[i];
i++;
if (i == message.length) clearInterval(typeLoop);
}, timePerCharacter);
}
#keyframes icon {
20% {
transform: scale(0.9);
}
40% {
transform: scale(1);
}
60% {
transform: scale(0.9);
}
80% {
transform: scale(1);
}
100% {
transform: translateY(-200%);
}
}
.icon {
border-radius: 100%;
}
.icon-animation {
animation: icon 3s;
}
#keyframes cursor {
50% {
color: transparent;
}
}
.blinking-cursor {
animation: cursor 1s steps(1) infinite;
}
<img id="icon" src="https://de7yjjf51n4cm.cloudfront.net/banners/amazonprime_newicon.jpg" class="icon">
<span id="typewriter" data-typewriter="
Web Strategy,
UX Testing,
Content Management System,
Web Design,
Research and Analytics,
Information Architecture,
Strategic Consulting,
Maintenance and Support
">
</span>
<span class="blinking-cursor">|</span>
Every 5s new content added to page(div). After 15s page start scrolling down with css animation property.
What I want is that if there is content it should scroll down till the end.
Here is the example code in snippet. In this example code animation duration is 100 seconds. It's not allowed to make it 0 or -1. Also this time will be spent between top:0% and top:-170%. I like this speed ( 270%/100s ).
100s should be forever and speed should stay the same(270%/100s).
setInterval(function() {
$("#list").append("<div id='block'>Content HERE!</div>");
}, 1000);
#list
{
position: absolute;
top: 100%;
-webkit-animation: scroll 100s linear infinite;
-moz-animation: scroll 100s linear infinite;
-ms-animation: scroll 100s linear infinite;
-o-animation: scroll 100s linear infinite;
animation: scroll 100s linear infinite;
}
/* animation */
#-webkit-keyframes scroll {
0% { top: 100%; }
100% { top: -170%; }
}
#-moz-keyframes scroll {
0% { top: 100%; }
100% { top: -170%; }
}
#-ms-keyframes scroll {
0% { top: 100%; }
100% { top: -170%; }
}
#-o-keyframes scroll {
0% { top: 100%; }
100% { top: -170%; }
}
#keyframes scroll {
0% { top: 100%; }
100% { top: -170%; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="list">
</div>
Try
$(window).on("error", function(e) {
console.log(e);
clearInterval(s);
$("#list").stop(true, true)
});
$.fx.interval = 0;
var i = 0
, listScroll = function listScroll(elem, idx) {
var block = elem.find("[data-index=" + idx + "]");
block.animate({
top: "-=" + (elem.height())
}, (1000 * 100), "linear", function() {
console.log(this, idx);
listScroll($(this).parent(), idx)
});
}
, s = setInterval(function() {
var el = $("<div />", {
"data-index": i,
"html": "Content HERE!",
});
$.when($("#list").append(el), i)
.promise().done([
listScroll
, function() {
++i;
}
])
}, 1000);
#list {
position: absolute;
top: 100%;
height: calc(100% - 1%);
}
#list div {
position: relative;
padding: 6px;
height: 36px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js">
</script>
<div id="list">
</div>
When I add the .shown class to my #overlay I would like the opacity to fade in for 2secs, then immediately reverse and fade out for 2 seconds, creating a sort of "flashing" effect.
I tried just removing the class but that doesn't show any animation at all. This is my sample markup/CSS:
HTML:
<div id="outer">
This is some text
<div id="overlay"></div>
</div>
CSS:
#overlay {
...
opacity: 0;
transition: opacity 2s ease-in-out;
}
#overlay.shown {
opacity: 0.3;
}
Attemped JS:
// Wait 2 seconds from page load...
setTimeout(function() {
// Add shown class to trigger animation
document.getElementById("overlay").classList.add("shown");
// Want to remove the class and hoped this would reverse the animation...
// it doesn't
document.getElementById("overlay").classList.remove("shown");
}, 2000);
jsFiddle
use css animation with keyframes
#keyframes myFlash
{
0% {opacity:0;}
50% {opacity:0.3;}
100% {opacity:0;}
}
#-webkit-keyframes myFlash /* Safari and Chrome */
{
0% {opacity:0;}
50% {opacity:0.3;}
100% {opacity:0;}
}
#overlay {
...
opacity: 0;
}
#overlay.shown {
animation:myFlash 2s;
-webkit-animation:myFlash 2s; /* Safari and Chrome */
}
It looks like you could use a second timeout after the first animation completes..
// Wait 2 seconds from page load...
setTimeout(function() {
// Animate Forward
document.getElementById("overlay").classList.add("shown");
setTimeout(function(){
// Animate Back
document.getElementById("overlay").classList.remove("shown");
},2000);
}, 2000);
There are lots of changes i have done to achieve your out put please check following code
Your css
#outer {
width: 100px;
height: 100px;
position: relative;
}
#overlay {
top: 0;
left: 0;
position: absolute;
width: 100%;
height: 100%;
background: #336699;
opacity: 0;
transition: opacity 2s ease-in-out;
}
#overlay.shown {
display: block;
opacity: 0.5;
}
Your js
setTimeout(function() {
$("#overlay").addClass("shown");
var def = $('#overlay').promise();
def.done(
function () {
$('body').stop().delay(5000).queue(function(){
$("#overlay").removeClass("shown");
});
});
}, 2000);
There was no delay between first and second so how it will show animation which you have done
Please check working demo.....Demo