Moving an image Javascript - javascript

My JS page
const catImage=document.querySelector('img')
let catImageLeft=catImage.style.left='0px'
function catwalk() {
let position= 0
setInterval(frame,50)
function frame() {
position+=10
catImage.style.left=position+'px'
if (position==1080) {
return catwalk()
}
if (position==540) {
setTimeout(catImage.src='https://media1.tenor.com/images/2de63e950fb254920054f9bd081e8157/tenor.gif',1000)
}
}
}
As you can see, it keeps on moving after replacing the image. And also if i would like the image to start over again, it stutters.
any suggestions.

Try this!
const catImage = document.querySelector('img');
const catWalkimg = 'https://i.imgur.com/Akh489w.gif';
const catDancImg = 'https://media2.giphy.com/media/3mXcJgVhPxWZa/giphy.gif';
catwalk();
function catwalk() {
let position = 0;
setInterval(function() {
position = position > 700 ? 0 : position;
if (position == 350) {
if (catImage.src != catDancImg) {
catImage.src = catDancImg;
setTimeout(() => {
catImage.src = catWalkimg;
position += 10;
}, 2000);
}
} else {
catImage.style.left = position + 'px';
position += 10;
}
}, 50);
}
img {width: 160px}
<img style="position:absolute;" src="https://i.imgur.com/Akh489w.gif" />

Related

React video player progress bar for multiple videos behaves strange

I am creating a react application where I am using three videos with custom progress bar for each one to be displayed at screen. I am facing a problem with progress bar update for all the three videos. When one video is fully played it's progress works fine but as soon as second video start playing, It also updates the bar width together (video1 and video2). I am using "timeupdate" event for updating the video progress bar.
`
import * as React from 'react';
import './style.css';
export default function App() {
var v3 = `http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4`;
var v2 = `http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4`;
var v1 = `http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4`;
const [id, setId] = React.useState(1);
const [currentVideo, setCurrentVideo] = React.useState('');
const [barCompleted, setBarCompleted] = React.useState<any>({
myBar1: false,
myBar2: false,
myBar3: false,
});
const videoRef = React.useRef<any>();
const progress1 = React.useRef<any>();
const progress2 = React.useRef<any>();
const progress3 = React.useRef<any>();
const myBar1 = React.useRef<any>();
const myBar2 = React.useRef<any>();
const myBar3 = React.useRef<any>();
const handleOnEnded = () => {
videoRef.current.removeEventListener('timeupdate', () => {});
// setBarCompleted(prev=>{myBar1:true,...prev})
setId((prev) => prev + 1);
};
const getVideoById = (id) => {
if (id == 1) {
setCurrentVideo(v1);
} else if (id == 2) {
setCurrentVideo(v2);
} else if (id == 3) {
setCurrentVideo(v3);
}
};
React.useEffect(() => {
getVideoById(id);
}, [id]);
React.useEffect(() => {
videoRef?.current?.load();
configureProgress(id);
}, [currentVideo, id]);
const configureProgress = (id) => {
videoRef?.current?.addEventListener('timeupdate', (e) => {
// console.log(e.target.currentTime);
let i = 0;
if (i == 0) {
i = 1;
// var elem = document.getElementById('myBar1');
let width = 1;
let sid = setInterval(frame, 1000);
function frame() {
if (videoRef.current.ended || width >= 100) {
clearInterval(sid);
i = 0;
if (id == 1) {
progress1.current.style.backgroundColor = 'green';
myBar1.current.style.width = 0 + '%';
} else if (id == 2) {
progress2.current.style.backgroundColor = 'green';
myBar2.current.style.width = 0 + '%';
} else if (id == 3) {
progress3.current.style.backgroundColor = 'green';
myBar3.current.style.width = 0 + '%';
}
} else {
width = Math.ceil(
(videoRef.current.currentTime / videoRef.current.duration) * 100
);
if (id == 1) {
myBar1.current.style.width = width + '%';
console.log('width update id1');
} else if (id == 2) {
myBar2.current.style.width = width + '%';
console.log('width update id2');
} else if (id == 3) {
myBar3.current.style.width = width + '%';
console.log('width update id3');
}
}
}
}
});
};
return (
<div>
<div className="progress-container">
<div id="myProgress1" ref={progress1}>
<div id="myBar1" ref={myBar1}></div>
</div>
<div id="myProgress2" ref={progress2}>
<div id="myBar2" ref={myBar2}></div>
</div>
<div id="myProgress3" ref={progress3}>
<div id="myBar3" ref={myBar3}></div>
</div>
</div>
{currentVideo && (
<video
autoPlay={true}
controls
muted={true}
id="myVideo1"
width={300}
height={250}
ref={videoRef}
crossOrigin="anonymous"
onEnded={handleOnEnded}
preload="metadata"
playsInline
>
<source src={currentVideo} type="video/mp4" />
</video>
)}
</div>
);
}
`
.progress-container {
display: flex;
}
#myProgress1,
#myProgress2,
#myProgress3 {
width: 33%;
background-color: #ddd;
}
#myBar1,
#myBar2,
#myBar3 {
width: 1%;
height: 30px;
background-color: #04aa6d;
}
[enter image description here](https://i.stack.imgur.com/usYQq.png)
I am expecting that "timeupdate" event should not run for second video as it also updates width for previous video(1st video).

Why's my image fade behaving weirdly when fading into next & last image in the array?

I don't understand why the previous image's being shown for a split second before moving on to the next image upon clicking.
Also, when I reach the last image, it should redirect to indexTwo.html which it does successfully. However, 'image down' coming from the alt attribute in <img/> is being shown for like two seconds before it reaches indexTwo.html successfully.
I tried many many different attempts to rectify this, way too many to list!
How can I prevent this behavior from happening?
Here's my html:
<img id="the-image" class="img-responsive"
src="http://tech21info.com/admin/wp-content/uploads/2013/03/chrome-logo-200x200.png"
alt="image down"
onclick="clickedImage()"
/>
Here's my js:
let theImage = document.getElementById('the-image');
let index = [
"http://tech21info.com/admin/wp-content/uploads/2013/03/chrome-logo-200x200.png",
"https://cdn.tutsplus.com/net/uploads/legacy/155_drupal/200x200.png",
"https://townandcountryremovals.com/wp-content/uploads/2013/10/firefox-logo-200x200.png"
];
let op = 1;
let imageId = 0;
let clickedImage = () => {
// start animation opacity
if(op === 1) {
let timer = setInterval(() => {
if(op <= 0.1) {
// load the next image
imageId = imageId + 1;
console.log(imageId);
theImage.src = index[imageId];
if (imageId >= index.length) {
window.location = "indexTwo.html";
}
// reset the opacity
theImage.style.opacity = op = 1;
clearInterval(timer);
} else {
op -= 0.1;
theImage.style.opacity = op;
}
}, 100);
}
};
The issue is that you are overflowing the array.
When imageId == 3 then the following line:
theImage.src = index[imageId];
results in theImage.src being set to undefined.
An easy way to resolve this would be to rearrange your code so that the image only advances to the next image if the id is within the bounds of the array.
let clickedImage = () => {
// start animation opacity
if(op === 1) {
let timer = setInterval(() => {
if(op <= 0.1) {
// load the next image
imageId = imageId + 1;
console.log(imageId);
if (imageId >= index.length) {
window.location = "indexTwo.html";
} else {
theImage.src = index[imageId];
// reset the opacity
theImage.style.opacity = op = 1;
}
clearInterval(timer);
} else {
op -= 0.1;
theImage.style.opacity = op;
}
}, 100);
}
};

This Javascript function keeps looping, how can i make it run once?

The code is meant to animated some text in a typing fashion. I want it to run once, but it keeps looping through the area of sentences. How would i go about stopping it looping through. The top of the code gathers the value of a input and puts into the array, this all works fine. It is just the looping i am having issues with.
var yourWord = document.getElementById("myText").value;
var yourtext = "I took the word " + yourWord + "...";
var infomation = [yourtext,
'I looked at the most relevant news article relating to it...',
'And created this piece of art from the words in the article! '
],
part,
i = 0,
offset = 0,
pollyLen = Polly.length,
forwards = true,
skip_count = 0,
skip_delay = 5,
speed = 100;
var wordflick = function () {
setInterval(function () {
if (forwards) {
if (offset >= infomation[i].length) {
++skip_count;
if (skip_count == skip_delay) {
forwards = false;
skip_count = 0;
}
}
} else {
if (offset == 0) {
forwards = true;
i++;
offset = 0;
if (i >= pollyLen) {
i = 0;
}
}
}
part = infomation[i].substr(0, offset);
if (skip_count == 0) {
if (forwards) {
offset++;
} else {
offset--;
}
}
$('#pollyInfo').text(part);
}, speed);
};
$(document).ready(function () {
wordflick();
});
Modify the line:
setInterval(function () {
into:
var interval = setInterval(function () {
and then clear the interval where you are setting i=0;
if (i >= pollyLen) {
i = 0;
}
to:
if (i >= pollyLen) {
i = 0;
clearInterval(interval);
}
This should do the job!

svgjs how to replay and control series of animations using slider

I am using svg.js and would like to play a series of animations and then provide a slider for the user to control the animation to look at it more closely. It looks like when an animation is complete, svg.js cleans up the resources so the situation gets nulled out so I can't reset it. I have a fiddle with a simplified example. After the animation plays once, I would like to then be able to use the slider and use the at method to reposition the animations.
https://jsfiddle.net/voam/xeajbhea/2/
var draw = SVG('drawing'),
rectA1 = draw.rect(50, 50).fill('#f06'),
rectA2 = draw.rect(50, 50).fill('#60f').translate(200),
rectB1 = draw.rect(50, 50).fill('#ce0').translate(0, 100).opacity(0),
rectB2 = draw.rect(50, 50).fill('#0ec').translate(200, 100).opacity(0);
var animation1 = rectA1.animate().move(200).opacity(0);
var animation2 = rectA2.animate().move(-200).opacity(0).during(function(pos) {
document.getElementById("range_animation").value = pos;
});
var animation3, animation4;
animation2.after(function(situation) {
animation3 = rectB1.animate().move(200).opacity(1);
animation4 = rectB2.animate().opacity(1).move(-200)
.during(function(pos) {
document.getElementById("range_animation").value = 1 + pos;
});
console.log('animations', animation1, animation2, animation3, animation4);
});
document.getElementById("range_animation").addEventListener("change", function(el) {
///console.log('change', el, );
var val = this.value;
if (animation1.situation) {
if (val < 1) {
animation1.at(val).pause();
animation2.at(val).pause();
} else {
animation3.at(val - 1).pause();
animation4.at(val - 1).pause();
}
}
}, false);
HTML below:
<div id="drawing">
</div>
<input type="range" id="range_animation" min="0.01" max="2" step=".01" value=".01">
One approach that works is as #Fuzzyma mentioned is to make the animations loop so they don't get terminated. Then one has to manage the transition sets from one to another. Any animations that don't get run immediately start in a paused state. In my real project not this demo there are 5 animation sets each with subanimations so lets see if this turns out to be manageable!
var atEnd = function (pos) {
var rounded = pos.toFixed(2);
return (rounded == .99 || rounded == 1.00);
};
var draw = SVG('drawing')
, rectA1 = draw.rect(50, 50).fill('#f06')
, rectA2= draw.rect(50, 50).fill('#60f').translate(200)
, rectB1 = draw.rect(50, 50).fill('#ce0').translate(0, 100).opacity(0)
, rectB2 = draw.rect(50, 50).fill('#0ec').translate(200, 100).opacity(0);
var animation3, animation4, lastTotalRange;
var animation1 = rectA1.animate().move(200).opacity(0).loop();
var animation2 = rectA2.animate().move(-200).opacity(0).loop();
animation2
.during(function( pos ) {
document.getElementById("range_animation").value = pos;
if ( atEnd (pos) ) {
animation2.pause();
animation3 = rectB1.animate().move(200).opacity(1).loop();
animation4 = rectB2.animate().opacity(1).move(-200).loop();
animation4
.during(function( pos ) {
if (pos > 0) {
document.getElementById("range_animation").value = 1 + pos;
}
if (atEnd (pos)) {
animation4.pause();
}
});
animation3.during( function(pos) {
if (atEnd (pos)) {
animation3.pause();
}
});
}
});
animation1.during(function( pos ) {
if (atEnd (pos)) {
animation1.pause();
}
});
$('input#range_animation').on('input', function() {
$(this).trigger('change');
})
$('input#range_animation').on('change', function() {
var val = $( this).val(),
delta = 0;
if (lastTotalRange) {
delta = val - lastTotalRange;
}
if (val < 1) {
animation1.at(val).pause();
animation2.at(val).pause();
if (lastTotalRange > 1) {
animation3.at(.01);
animation4.at(.01);
}
}
else {
animation3.at(val - 1).pause();
animation4.at(val - 1).pause();
if (lastTotalRange < 1) {
animation1.at(.99);
animation1.at(.99);
}
}
// console.log('totalAnimationRange:change', delta, val);
lastTotalRange = val;
})
and the html
<div id="drawing"></div>
<input type="range" id="range_animation" min="0.00" max="1.99" step=".01" value=".01">
and the jsfiddle:
jsfiddle.net/voam/ob2bjfur/1/

function is undefined in firefox only

ok, the following code works ok in IE7+ and Chrome.
but for some reason, xfade is undefined in firefox
<html>
<body>
<div id="slider"></div>
<script type="text/javascript">
var Klimateka = {
Slider: function () {
// Check if we have a slider div on page
var slider = document.getElementById('slider');
if (slider != null) {
var images = ["slide-image-1.jpg", "slide-image-2.jpg", "slide-image-3.jpg", "slide-image-4.jpg"];
var i = images.length;
while (i) {
i -= 1;
var img = document.createElement("img");
img.src = "images/" + images[i];
slider.appendChild(img);
}
var d = document, imgs = new Array(), zInterval = null, current = 0, pause = false;
imgs = d.getElementById("slider").getElementsByTagName("img");
for (i = 1; i < imgs.length; i++) imgs[i].xOpacity = 0;
imgs[0].style.display = "block";
imgs[0].xOpacity = .99;
setTimeout("xfade()", 3500);
function xfade() {
cOpacity = imgs[current].xOpacity;
nIndex = imgs[current + 1] ? current + 1 : 0;
nOpacity = imgs[nIndex].xOpacity;
cOpacity -= .05;
nOpacity += .05;
imgs[nIndex].style.display = "block";
imgs[current].xOpacity = cOpacity;
imgs[nIndex].xOpacity = nOpacity;
setOpacity(imgs[current]);
setOpacity(imgs[nIndex]);
if (cOpacity <= 0) {
imgs[current].style.display = "none";
current = nIndex;
setTimeout(xfade, 3500);
} else {
setTimeout(xfade, 50);
}
function setOpacity(obj) {
if (obj.xOpacity > .99) {
obj.xOpacity = .99;
return;
}
obj.style.opacity = obj.xOpacity;
obj.style.MozOpacity = obj.xOpacity;
obj.style.filter = "alpha(opacity=" + (obj.xOpacity * 100) + ")";
}
}
}
},
bar: function () {
}
};
Klimateka.Slider();
i have setup a jsfiddler for testing:
http://jsfiddle.net/rTtKh/10/
This might only apply to Firefox:
functions do not hoist when declared inside a child block.
You declare xfade inside the if block, but you are calling it prior to the declaration:
setTimeout(xfade, 3500);
Put the function declaration on top.
You have to do the same with setOpacity inside xfade. <- That is not necessary.
Fix your line that says this: setTimeout("xfade()", 3500); to match your others:
setTimeout(xfade, 3500);
Use setTimeout(xfade, 3500) instead.

Categories