The delelement code is working fine but I want to delete the element after the css animation is finished for "delorean", then I need the animation to start again every time the button is clicked, how can I use my "delelement" code to achieve this? thanks.
function touchDelorean(event) {
event.preventDefault();
if (showDelorean == true) {
delorean();
}
}
function delorean() {
var image = document.createElement("img");
image.id = "delorean";
image.src = "Images/delorean/" + where + ".png";
document.getElementById("deloreanContainer").appendChild(image);
// delelement("deloreanContainer");
}
function delelement(elem) {
var element = document.getElementById(elem);
while (element.firstChild) { element.removeChild(element.firstChild); }
}
CSS
#delorean {
position: absolute;
top: 0%;
left: 0%;
width: 29%;
height: 9.8%;
opacity: 1.0;
-webkit-animation: delorean_anim 10s linear;
-webkit-animation-direction: normal, horizontal ;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 0);
}
#-webkit-keyframes delorean_anim {
0% { -webkit-transform: translate(-24vw, 0vw) scale(0.6, 0.6) rotate(0deg) }
20% { -webkit-transform: translate(137vw, 36vw) scale(3.5, 3.5) rotate(0deg) }
100% { -webkit-transform: translate(137vw, 36vw) scale(3.5, 3.5) rotate(0deg)}
}
Use setTimeout() and do a time equal or greater to that of your CSS Transition time... so if:
transition: all 3s ease;
then...
function delorean() {
var image = document.createElement("img");
image.id = "delorean";
image.src = "Images/delorean/" + where + ".png";
document.getElementById("deloreanContainer").appendChild(image);
setTimeout( function { delelement("deloreanContainer"); }, 3000 );
}
function delelement(elem) {
var element = document.getElementById(elem);
while (element.firstChild) { element.removeChild(element.firstChild); }
}
On the element that runs the animation, given that it is image you can add an eventlistener..
// Chrome, Safari and Opera
image.addEventListener('webkitAnimationEnd', function() {
image.remove()
});
// Standard syntax
image.addEventListener('animationend', function() {
image.remove()
});
If you're dealing with a css transition and not a css animation then you're looking for transitionend. These events can however be unreliable sometimes so if you know the length of the animation, you're better off with setTimeout as suggested above.
In react.js the infamous CSSTransitionGroup component had many problems due to the transition event not fireing as expected. They "solved" the problem by requiring specifying transition timeout values for the component..
Related
Tread sofly, I've just started and couldn't find a similar problem... at least what I think would be the solution ;)
So I've got a robot written in HTML and CSS and I want to animate its lips on click. The idea is to make it like a kiss shape, so I need to scale it to a tiny size(1) and then put it back to normal (2). For now I don't really know how to do it. I tried just changing the width and height size but it didn't work. My guess is I need to do something with the transfort scaleX and scaleY but no idea what and how.
This is what I've already got:
var lips = document.getElementById("lips");
lips.addEventListener("click", kiss);
function kiss(e) {
var partRobo = e.target;
var sizeX= 1;
var sizeY= 1;
var id = setInterval(action, 20);
function action() {
partRobo.style.transform = scale(sizeX, sizeY);
sizeX-0.1;
sizeY-0.1;
if (sizeX === 0 && sizeY=== 0) {
clearInterval(id);
}
}
}
There are many ways to do this, and here is one of them
document.querySelector("div").addEventListener("click", function () {
this.style.transform = "scale(1.2)";
setTimeout(()=>{
this.style.transform = "scale(1)";
},500)
});
div {
width: 100px;
height: 100px;
background-color: red;
transition: cubic-bezier(0, 2.28, 0.95, 0.69) 0.5s;
}
<div></div>
You can use a CSS animation, JS would be needed only for triggering the animation. Of course you can change the duration, easing function and other params of the animation.
#lips {
height: 50px;
width: 100px;
background: red;
cursor: pointer;
}
.kiss {
animation: kiss 4s;
}
#keyframes kiss {
from {
transform: scale(0);
}
to {
transform: scale(1);
}
}
<div id="lips" onclick="this.classList.add('kiss')"></div>
I would make a css rule along the lines of
.lips-kiss {
transform: scale(0.6);
}
and then in the function kiss, apply and remove the class. So your code would look like,
var lips = document.getElementById("lips");
lips.addEventListener("click", kiss);
function kiss() {
lips.classList.add('lips-kiss');
setTimeout(() => {
lips.classList.remove('lips-kiss');
}, 20);
}
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">
At the moment I am developing a site where when you click, an image is added to the page.
Is it possible for the code to still work but for it too not effect images further down the page?
I've tried to change so it doesn't link to "img" tag but this doesn't seem to work. First time working with JS so very new to it all.
Js looks like this at the moment
const images = [
"benjones_con4.jpg",
"ben_jones_ts2.jpg",
"benjones_con3.jpg"
]
let i = 0
function placeImage(x, y) {
const nextImage = images[i]
const img = document.createElement("img")
img.setAttribute("src", nextImage)
img.style.left = x + "px"
img.style.top = y + "px"
document.body.appendChild(img)
i = i + 1
if (i >=images.length) {
i = 0
}
}
document.addEventListener("click", function (event) {
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
document.addEventListener("touchend", function (event){
event.preventDefault()
placeImage(event.pageX, event.pageY)
})
img {
position: absolute;
transform: translate(-50%, -50%) scale(0.5);
animation: fadein 0.5s;
}
#keyframes fadein {
0% {opacity: 0;}
100% {opacity: 1;}
}
As I understand from the latest comment, if you don't want that loaded img conflict with other "img" tags on your page, you need add some meaningful class for created img element.
And define styles for loaded image separately.
function placeImage(x, y) {
const nextImage = images[i]
const img = document.createElement("img")
// here adding class for created img tag
img.classList.add('external-loaded-img')
...
}
// instead of global img, define for class
.external-loaded-img {
position: absolute;
transform: translate(-50%, -50%) scale(0.5);
animation: fadein 0.5s;
}
#keyframes fadein {
0% {opacity: 0;}
100% {opacity: 1;}
}
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!
I'm creating a small website that tells a story by using css and sprite animation.
The problem I'm encountering is that I do not know how to change the keyframes once I have set them in the css files expecially while I try to make it compatible with all of the browsers.
Here is what I have,
the main part of the css:
#ManSprite{
overflow:hidden;
width:200px;
height:200px;
position:absolute;
top:280px;
left:140px;
background-image: url("http://imageshack.com/a/img571/1710/2r1h.png");
z-index:99;
animation: play .4s steps(2) infinite;
-webkit-animation: play .4s steps(2) infinite;
-moz-animation: play .4s steps(2) infinite;
-ms-animation: play .4s steps(2) infinite;
-o-animation: play .4s steps(2) infinite;
}
#keyframes play {
from { background-position: -200px; }
to { background-position: -600px; }
}
#-webkit-keyframes play {
from { background-position: -200px; }
to { background-position: -600px; }
}
#-moz-keyframes play {
from { background-position: -200px; }
to { background-position: -600px; }
}
#-ms-keyframes play {
from { background-position: -200px; }
to { background-position: -600px; }
}
#-o-keyframes play {
from { background-position: -200px; }
to { background-position: -600px; }
}
Then in my javascript I would like to change the background position for every keyframe but I'm not sure how to change it. I've tried the following but it does not work.
var StoryPart = 0;
var fromArray = new Array("0px", "-200px", "-800px", "-1400px", "-2200px", "-3200px");
var toArray = new Array("0px", "-600px", "-1400px", "-2200px", "-3230px", "-4000px");
var stepsArray = new Array(0, 2, 3, 4, 5, 4);
function nextBtn() {
StoryPart++;
startChange();
}
// begin the new animation process
function startChange() {
// remove the old animation from our object
document.getElementById('ManSprite').style.webkitAnimationName = "none";
document.getElementById('ManSprite').style.animationName = "none";
document.getElementById('ManSprite').style.msAnimationName = "none";
document.getElementById('ManSprite').style.oAnimationName = "none";
document.getElementById('ManSprite').style.mozAnimationName ="none";
// call the change method, which will update the keyframe animation
setTimeout(function () { change("play", fromArray[StoryPart], toArray[StoryPart]); }, 0);
}
// search the CSSOM for a specific -webkit-keyframe rule
function findKeyframesRule(rule) {
// gather all stylesheets into an array
var ss = document.styleSheets;
// loop through the stylesheets
for (var i = 0; i < ss.length; ++i) {
// loop through all the rules
for (var j = 0; j < ss[i].cssRules.length; ++j) {
// find the -webkit-keyframe rule whose name matches our passed over parameter and return that rule
if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule
|| ss[i].cssRules[j].type == window.CSSRule.KEYFRAMES_RULE && ss[i].cssRules[j].name == rule
)
return ss[i].cssRules[j];
}
}
// rule not found
return null;
}
// remove old keyframes and add new ones
function change(anim, fromValue, toValue) {
// find our -webkit-keyframe rule
var keyframes = findKeyframesRule(anim);
// remove the existing 0% and 100% rules
keyframes.deleteRule("0%");
keyframes.deleteRule("100%");
// create new 0% and 100% rules with random numbers
keyframes.insertRule("0% {background-position: " + fromValue + ";}");
keyframes.insertRule("100% {background-position: " + toValue + ";}");
// assign the animation to our element (which will cause the animation to run)
document.getElementById('ManSprite').style.webkitAnimationName = anim;
document.getElementById('ManSprite').style.animationName = anim;
document.getElementById('ManSprite').style.msAnimationName = anim;
document.getElementById('ManSprite').style.oAnimationName = anim;
document.getElementById('ManSprite').style.mozAnimationName = anim;
}
For some reason in Chrome, it doesn't find any cssRule inside the findKeyframesRule method, but in firefox it does. Firefox crashes, however, on this line
keyframes.insertRule("0% {background-position: " + fromValue + ";}");
which confuses me because it was able to use deleteRule well.
Anyone ever work with these?