How Can I make this touch Slider move atomically? - javascript

I am trying to make this touch slider, which move between slides automatically.
I tried many ways but nothing helped, this bellow is my Code:
.slider-container {
height: 100vh;
display: inline-flex;
overflow: hidden;
scrollbar-width: none;
transform: translateX(0);
will-change: transform;
transition: transform 0.3s ease-out;
cursor: grab;
}
.slide{
max-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
<div class="slider-container">
<div class="slide">
<img src="pics/slider/127616685-multi-colored-samples-of-marble-granite-and-travertine-chips-and-pebbles-for-landscape-design-close-.jpg"/>
</div>
<div class="slide">
<img src="pics/slider/1554689647283.jpg"/>
</div>
</div>

Just add this code at the bottom of your JS code.
This code changes the value of currentTranslate every 1 second and then calls the touchEnd(); function.
**I added the variable "loop" if the value is true when the last slide is reached... the script will call the first one again and so on indefinitely. If it has a value of false when the last slide is reached, the interval will be removed. And scrolling the slides will stop.
var loop = true; //<-- "true" Loop or "false" Stop on the End
var slideShw = setInterval(() => {
currentTranslate = currentTranslate - 101;
touchEnd();
if (currentIndex === slides.length - 1) {
if (loop) {
currentIndex -= slides.length;
} else {
stop_slideShw();
}
}
}, 1000);
function stop_slideShw() {
clearInterval(slideShw);
}
Example:
// get our elements
const slider = document.querySelector('.slider-container'),
slides = Array.from(document.querySelectorAll('.slide'))
// set up our state
let isDragging = false,
startPos = 0,
currentTranslate = 0,
prevTranslate = 0,
animationID,
currentIndex = 0
// add our event listeners
slides.forEach((slide, index) => {
const slideImage = slide.querySelector('img')
// disable default image drag
slideImage.addEventListener('dragstart', (e) => e.preventDefault())
// touch events
slide.addEventListener('touchstart', touchStart(index))
slide.addEventListener('touchend', touchEnd)
slide.addEventListener('touchmove', touchMove)
// mouse events
slide.addEventListener('mousedown', touchStart(index))
slide.addEventListener('mouseup', touchEnd)
slide.addEventListener('mousemove', touchMove)
slide.addEventListener('mouseleave', touchEnd)
})
// make responsive to viewport changes
window.addEventListener('resize', setPositionByIndex)
// // prevent menu popup on long press
// window.oncontextmenu = function (event) {
// event.preventDefault()
// event.stopPropagation()
// return false
// }
function getPositionX(event) {
return event.type.includes('mouse') ? event.pageX : event.touches[0].clientX
}
// use a HOF so we have index in a closure
function touchStart(index) {
return function (event) {
currentIndex = index
startPos = getPositionX(event)
isDragging = true
animationID = requestAnimationFrame(animation)
slider.classList.add('grabbing')
}
}
function touchMove(event) {
if (isDragging) {
const currentPosition = getPositionX(event)
currentTranslate = prevTranslate + currentPosition - startPos
}
}
var movedBy;
function touchEnd() {
cancelAnimationFrame(animationID)
isDragging = false
movedBy = currentTranslate - prevTranslate
// if moved enough negative then snap to next slide if there is one
if (movedBy < -100 && currentIndex < slides.length - 1) currentIndex += 1
// if moved enough positive then snap to previous slide if there is one
if (movedBy > 100 && currentIndex > 0) currentIndex -= 1
setPositionByIndex()
slider.classList.remove('grabbing')
}
function animation() {
setSliderPosition()
if (isDragging) requestAnimationFrame(animation)
}
function setPositionByIndex() {
currentTranslate = currentIndex * -window.innerWidth
prevTranslate = currentTranslate
setSliderPosition()
}
function setSliderPosition() {
slider.style.transform = `translateX(${currentTranslate}px)`
}
// NEW LINES /////////////////////////////////////////
var loop = true; //<-- "true" Loop or "false" Stop on the End
var slideShw = setInterval(() => {
currentTranslate = currentTranslate - 101;
touchEnd();
if (currentIndex === slides.length - 1) {
if (loop) {
currentIndex -= slides.length;
} else {
stop_slideShw();
}
}
}, 1000);
function stop_slideShw() {
clearInterval(slideShw);
}
/* :root {
--shadow: rgba(0, 0, 0, 0.8)
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
*/
.slider-container {
height: 100vh;
display: inline-flex;
overflow: hidden;
scrollbar-width: none;
transform: translateX(0);
will-change: transform;
transition: transform 0.3s ease-out;
cursor: grab;
}
.slide {
max-height: 100vh;
width: 100vw;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
#media(min-width: 1200px) {
.slide {
padding: 3rem;
}
}
.slide img {
max-width: 100%;
max-height: 100%;
transition: transform 0.3s ease-in-out;
box-shadow: 5px 5px 50px -1px var(--shadow);
border-radius: 4px;
user-select: none;
}
.grabbing {
cursor: grabbing;
}
.grabbing .slide img {
transform: scale(0.9);
box-shadow: 5px 5px 40px -1px var(--shadow);
}
<div class="slider-container">
<div class="slide">
<img
src="https://images.pexels.com/photos/145939/pexels-photo-145939.jpeg?auto=compress&cs=tinysrgb&dpr=3&h=750&w=1260" />
</div>
<div class="slide">
<img
src="https://images.pexels.com/photos/47547/squirrel-animal-cute-rodents-47547.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940" />
</div>
<div class="slide">
<img
src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fspecials-images.forbesimg.com%2Fimageserve%2F5faad4255239c9448d6c7bcd%2FBest-Animal-Photos-Contest--Close-Up-Of-baby-monkey%2F960x0.jpg%3Ffit%3Dscale" />
</div>
</div>

To move your slider automatically you should use the animation property.

Its difficult to work on slider without Javascript. I am giving some fresh codes, you can check them and rewrite your codes accordingly.
var photos = ["1.png","2.png","3.png"]
var time = 3000;
var imgTag = document.querySelector("img")
var count = 0;
function changeImg() {
document.slide.src = photos[count];
count++;
if(count==3){
count=0;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("lap");
setTimeout("changeImg()",time);
}
window.onload = changeImg;
function next(){
count++;
time=3000;
if(count==3){
count=0;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("next");
}
function prev(){
count--;
time=3000;
if(count==-1){
count=2;
imgTag.src = photos[count];
}
else{
imgTag.src = photos[count];
}
console.log("prev");
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stack Overflow</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<button onclick="prev()">Prev</button>
<img src="1.png" name="slide" alt="" height="300" width="300">
<button onclick="next()">Next</button>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
Put any 3 images named "1.png" "2.png" "3.png". And then run the code. Hopefully it will run, and you will get an idea. Here I have used a setTimeout function that will fire up after 3 seconds to change your slides.
Thank you.

Related

What could be the bare minimum steps to animate the following carousel implementation?

I am making a vanilla js carousel. I have laid out basic previous and next functionality using js along with html and css.
Now I tried to use css-animations (keyframes) to do left and right slide-in/slide-out animations but the code became messy for me. So here I am asking that what minimal changes would be needed to get the same animation effects in this implementation ?
Will you go for pure JS based or pure CSS based or a mix to do the same ?
My goal is get proper animation with minimal code.
(function () {
let visibleIndex = 0;
let carousalImages = document.querySelectorAll(".carousal__image");
let totalImages = [...carousalImages].length;
function makeNextVisible() {
visibleIndex++;
if (visibleIndex > totalImages - 1) {
visibleIndex = 0;
}
resetVisible();
renderVisible();
}
function makePrevVisible() {
visibleIndex--;
if (visibleIndex < 0) {
visibleIndex = totalImages - 1;
}
resetVisible();
renderVisible();
}
function resetVisible() {
for (let index = 0; index < totalImages; index++) {
carousalImages[index].className = "carousal__image";
}
}
function renderVisible() {
carousalImages[visibleIndex].className = "carousal__image--visible";
}
function renderCarousel({ autoplay = false, autoplayTime = 1000 } = {}) {
if (autoplay) {
[...document.querySelectorAll("button")].forEach(
(btn) => (btn.style.display = "none")
);
setInterval(() => {
makeNextVisible();
}, autoplayTime);
} else renderVisible();
}
renderCarousel();
// Add {autoplay:true} as argument to above to autplay the carousel.
this.makeNextVisible = makeNextVisible;
this.makePrevVisible = makePrevVisible;
})();
.carousal {
display: flex;
align-items: center;
}
.carousal__wrapper {
width: 500px;
height: 400px;
}
.carousal__images {
display: flex;
overflow: hidden;
list-style-type: none;
padding: 0;
}
.carousal__image--visible {
position: relative;
}
.carousal__image {
display: none;
}
<div class='carousal'>
<div class='carousal__left'>
<button onclick='makePrevVisible()'>Left</button>
</div>
<section class='carousal__wrapper'>
<ul class='carousal__images'>
<li class='carousal__image'>
<img src='https://fastly.syfy.com/sites/syfy/files/styles/1200x680/public/2018/03/dragon-ball-super-goku-ultra-instinct-mastered-01.jpg?offset-x=0&offset-y=0' alt='UI Goku' / width='500' height='400'/>
</li>
<li class='carousal__image'>
<img src='https://www.theburnin.com/wp-content/uploads/2019/01/super-broly-3.png' alt='Broly Legendary' width='500' height='400'/>
</li>
<li class='carousal__image'>
<img src='https://lh3.googleusercontent.com/proxy/xjEVDYoZy8-CTtPZGsQCq2PW7I-1YM5_S5GPrAdlYL2i4SBoZC-zgtg2r3MqH85BubDZuR3AAW4Gp6Ue-B-T2Z1FkKW99SPHwAce5Q_unUpwtm4' alt='Vegeta Base' width='500' height='400'/>
</li>
<li class='carousal__image'>
<img src='https://am21.mediaite.com/tms/cnt/uploads/2018/09/GohanSS2.jpg' alt='Gohan SS2' width='500' height='400'/>
</li>
</ul>
</section>
<div class='carousal__right'>
<button onclick='makeNextVisible()'>Right</button>
</div>
</div>
Updated codepen with feedback from the below answers and minor additional functionalities = https://codepen.io/lapstjup/pen/RwoRWVe
I think the trick is pretty simple. ;)
You should not move one or two images at the same time. Instead you should move ALL images at once.
Let's start with the CSS:
.carousal {
position: relative;
display: block;
}
.carousal__wrapper {
width: 500px;
height: 400px;
position: relative;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
}
.carousal__wrapper,
.carousal__images {
transform: translate3d(0, 0, 0);
}
.carousal__images {
position: relative;
top: 0;
left: 0;
display: block;
margin-left: auto;
margin-right: auto;
}
.carousal__image {
float: left;
height: 100%;
min-height: 1px;
}
2nd step would be to calculate the maximum width for .carousal__images. For example in your case 4 * 500px makes 2000px. This value must be added to your carousal__images as part of the style attribute style="width: 2000px".
3rd step would be to calculate the next animation point and using transform: translate3d. We start at 0 and want the next slide which means that we have slide to the left. We also know the width of one slide. So the result would be -500px which also has to be added the style attribute of carousal__images => style="width: 2000px; transform: translate3d(-500px, 0px, 0px);"
That's it.
Link to my CodePen: Codepen for Basic Carousel with Autoplay
Try this. First stack all the images next to each other in a div and only show a single image at a time by setting overflow property to hidden for the div. Next, add event listeners to the buttons. When a bottom is clicked, the div containing the images is translated by -{size of an image} * {image number} on the x axis. For smooth animation, add transition: all 0.5s ease-in-out; to the div.
When someone clicks left arrow on the first image, the slide should display the last image. So for that counter is set to {number of images} - 1 and image is translated to left size * counter px.
For every click on the right arrow, the counter is incremented by 1 and slide is moved left. For every click on the left arrow, the counter is decremented by 1.
Slide.style.transform = "translateX(" + (-size * counter) + "px)"; this is the condition which is deciding how much the slide should be translated.
const PreviousButton = document.querySelector(".Previous-Button");
const NextButton = document.querySelector(".Next-Button");
const Images = document.querySelectorAll("img");
const Slide = document.querySelector(".Images");
const size = Slide.clientWidth;
var counter = 0;
// Arrow Click Events
PreviousButton.addEventListener("click", Previous);
NextButton.addEventListener("click", Next);
function Previous() {
counter--;
if (counter < 0) {
counter = Images.length - 1;
}
Slide.style.transform = "translateX(" + (-size * counter) + "px)";
}
function Next() {
counter++;
if (counter >= Images.length) {
counter = 0;
}
Slide.style.transform = "translateX(" + (-size * counter) + "px)";
}
* {
margin: 0px;
padding: 0px;
box-sizing: border-box;
}
.Container {
width: 60%;
margin: 0px auto;
margin-top: 90px;
overflow: hidden;
position: relative;
}
.Container .Images img {
width: 100%;
}
.Images {
transition: all 0.5s ease-in-out;
}
.Container .Previous-Button {
position: absolute;
background: transparent;
border: 0px;
outline: 0px;
top: 50%;
left: 20px;
transform: translateY(-50%);
filter: invert(80%);
z-index: 1;
}
.Container .Next-Button {
position: absolute;
background: transparent;
border: 0px;
outline: 0px;
top: 50%;
right: 20px;
transform: translateY(-50%);
filter: invert(80%);
z-index: 1;
}
.Container .Images {
display: flex;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="https://fonts.googleapis.com/css2?family=Cabin&family=Poppins&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<title>Carousel</title>
</head>
<body>
<div class="Container">
<button class="Previous-Button">
<svg style = "transform: rotate(180deg);" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M8.122 24l-4.122-4 8-8-8-8 4.122-4 11.878 12z"/></svg>
</button>
<button class="Next-Button">
<svg xmlns="http://www.w3.org/2000/svg" width = "24" height = "24" viewBox = "0 0 24 24"><path d="M8.122 24l-4.122-4 8-8-8-8 4.122-4 11.878 12z"/></svg>
</button>
<div class="Images">
<img src="https://source.unsplash.com/1280x720/?nature">
<img src="https://source.unsplash.com/1280x720/?water">
<img src="https://source.unsplash.com/1280x720/?rock">
<img src="https://source.unsplash.com/1280x720/?abstract">
<img src="https://source.unsplash.com/1280x720/?nature">
<img src="https://source.unsplash.com/1280x720/?trees">
<img src="https://source.unsplash.com/1280x720/?human">
<img src="https://source.unsplash.com/1280x720/?tech">
</div>
</div>
<script src="main.js"></script>
</body>
</html>

Carousel onmouseover and onmouseout does not work

I am practising Javascript. I made an images carousel. My carousel slide works fine. To run the slide I used setinterval. When user will hover over the image, I want to stop the slide and when it will hover out then slide will start where it pause. For that I used clearinterval. When I onmouseover then onmouseout my carousel behave weird. Seems like my logic does not work. I don't know how to do that.
const images = document.getElementById('imgs')
const allImages = document.querySelectorAll('#imgs img')
let index = 0;
function run() {
index++;
if (index > allImages.length - 1) {
index = 0
}
imgs.style.transform = `translateX(${-index * 500}px)`
}
setInterval(run, 2000);
images.onmouseover = () => {
console.log('In');
clearInterval(run) + 1
}
images.onmouseout = () => {
console.log('Out');
setInterval(run, 2000);
}
*{
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.carousel {
overflow: hidden;
width: 500px;
height: 500px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, .3);
}
.image-container {
display: flex;
transition: transform 300ms linear;
transform: translateX(0);
}
img {
width:500px;
height: 500px;
object-fit: cover;
}
<div class="carousel">
<div class="image-container" id="imgs" >
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1516026672322-bc52d61a55d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1573081586928-127ecc7948b0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/flagged/photo-1572850005109-f4ac7529bf9f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
</div>
You made a mistake with the interval.
To be able to clear the interval in the onmouseover event, you need to assign it to a variable
var x = setInterval(run, 2000);
then you pass the variable to the clearInterval method.
clearInterval(x)
then onmouseout you set again the interval
x = setInterval(run, 2000);
Final code would look like this:
var x = setInterval(run, 2000);
images.onmouseover = () => {
console.log('In');
clearInterval(x) + 1
}
images.onmouseout = () => {
console.log('Out');
x = setInterval(run, 2000);
}

How to make the element stop falling?

Below this text is my code - I am trying to create the chrome dino game, and so far everything is going well, but I have one problem - after the red block jumps, the dino doesn't stop falling down - while it should. I don't understand where my problem is, as I wrote about the same code yesterday and everything worked just fine. The gravity function can be found in the JavaScript under // Gravity.
Notice how it's code is very similar to the jump function, but it doesn't work as good as the jump function. Any help would be appreciated!!!!!
// HTML Elements + Other Variables
const floor1 = document.getElementById("floor1");
const floor2 = document.getElementById("floor2");
const floor3 = document.getElementById("floor3");
const floor4 = document.getElementById("floor4");
const floor5 = document.getElementById("floor5");
const floor6 = document.getElementById("floor6");
const floor7 = document.getElementById("floor7");
const dino = document.getElementById("dino");
const highBird = document.getElementById("highBird");
const lowBird = document.getElementById("lowBird");
const wideCactus = document.getElementById("wideCactus");
const thinCactus = document.getElementById("thinCactus");
let jump = 0;
// Floor Function
setTimeout(function () {
floor1.classList.add("floor1Animation");
}, 0);
setTimeout(function () {
floor2.classList.add("floor2Animation");
}, 1000);
setTimeout(function () {
floor3.classList.add("floor3Animation");
}, 2000);
setTimeout(function () {
floor4.classList.add("floor4Animation");
}, 3000);
setTimeout(function () {
floor5.classList.add("floor5Animation");
}, 4000);
setTimeout(function () {
floor6.classList.add("floor6Animation");
}, 5000);
setTimeout(function () {
floor7.classList.add("floor7Animation");
}, 6000);
// Jump
document.onkeydown = function (event) {
let key = event.key;
if (key == "ArrowUp") {
let jumpCount = 0;
if (dino.offsetTop == 95) {
let jumpInterval = setInterval(function () {
dino.style.top = (dino.offsetTop - 5) + "px";
jumpCount += 1;
jump = true;
if (jumpCount == 20) {
clearInterval(jumpInterval);
jump = false;
jumpCount = 0;
}
}, 10);
}
}
}
// Gravity
setInterval(function () {
if (jump == false) {
let jumpGravity = setInterval(function () {
dino.style.top = (dino.offsetTop + 5) + "px";
}, 10);
if (dino.offsetTop == 95) {
clearInterval(jumpGravity);
}
}
}, 10);
body {
margin: 0;
padding: 0;
justify-content: center;
align-items: center;
display: flex;
width: 100vw;
height: 100vh;
}
#gameBoard {
width: 1000px;
height: 150px;
border: 2px solid black;
overflow: hidden;
margin: auto;
position: relative;
background-color: white;
}
#dino {
width: 30px;
height: 50px;
background-color: red;
left: 10px;
top: 95px;
position: absolute;
}
.floorBackground {
position: relative;
height: 10px;
width: 200px;
display: flex;
justify-content: center;
align-items: center;
}
.floor {
position: absolute;
top: 140px;
height: 10px;
width: 200px;
}
#floor1 {
right: -200px;
background-color: red;
}
.floor1Animation {
animation: floorAnimation 6s infinite linear;
}
#floor2 {
right: -200px;
background-color: blue;
}
.floor2Animation {
animation: floorAnimation 6s infinite linear;
}
#floor3 {
right: -200px;
background-color: green;
}
.floor3Animation {
animation: floorAnimation 6s infinite linear;
}
#floor4 {
right: -200px;
background-color: purple;
}
.floor4Animation {
animation: floorAnimation 6s infinite linear;
}
#floor5 {
right: -200px;
background-color: brown;
}
.floor5Animation {
animation: floorAnimation 6s infinite linear;
}
#floor6 {
right: -200px;
background-color: orange;
}
.floor6Animation {
animation: floorAnimation 6s infinite linear;
}
#floor7 {
right: -200px;
background-color: yellow;
}
.floor7Animation {
animation: floorAnimation 6s infinite linear;
}
#keyframes floorAnimation {
from {
right: -200px;
}
to {
right: 1000px;
}
}
#keyframes jumping {
}
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>
Dino Game
</title>
<link rel = "stylesheet" type = "text/css" href = "DinoCSS.css">
</head>
<body>
<div id = "gameBoard">
<div id = "floor1" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor2" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor3" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor4" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor5" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor6" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "floor7" class = "floor">
<img src = "Pictures/dinoBackground.PNG" class = "floorBackground">
</div>
<div id = "dino"></div>
<div id = "highBird"></div>
<div id = "lowBird"></div>
<div id = "wideCactus"></div>
<div id = "thinCactus"></div>
</div>
<script type = "text/javascript" src = "DinoJS.js"></script>
</body>
</html>
You should try simplifying your code, it may make the issue easier to find or it may even remove it entirely.
I'd suggest using a velocity system, where every frame you adjust the dino's offsetTop by the dino's current velocity, and then subtract the gravity amount from the dino's current velocity.
This causes the velocity to decrease at a constant rate, but the dino's offsetTop position to decrease at an exponential pace, mimicking real gravity.
Then, to make collision work, just test if the dino is at or above the correct "offsetTop" value before subtracting the gravity. If you find that the dino is below the ground, just set the offsetTop to the ground level and clear the velocity.
I'd also suggest moving your game over to the HTML5 Canvas API, since then you just have to deal with properties of objects rather than DOM element style attributes.
Velocity example with canvas:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var x = 10;
var y = 10;
var VelocityX = 0;
var VelocityY = 0;
const gravity = 0.75;
// width and height of the square
var width = 10;
var height = 10;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height); // Clear the canvas
x += VelocityX;
if( x > 500) {
x = 0;
}
if ( y >= 450 ) {
y = 450
VelocityY = 0
} else {
y += VelocityY;
VelocityY += gravity; // Higher values = lower position on canvas
}
ctx.fillRect(x, y, width, height);
}
setInterval(animate, 1000 / 60); // 60 FPS
#canvas {
border: 1px solid black;
}
<canvas id="canvas" width="500" height="500"></canvas>
JSFiddle

display 3 items in carousel - used existing pen

I found a pen online to create image carousel, problem is I can't get it display 3 items inside a container.
I have tried removing the opacity for the carousel photo but then it messes up the display for the full container.
Here is link to my fiddle:
!(function(d) {
// Variables to target our base class, get carousel items, count how many carousel items there are, set the slide to 0 (which is the number that tells us the frame we're on), and set motion to true which disables interactivity.
var itemClassName = "carousel__photo";
items = d.getElementsByClassName(itemClassName),
totalItems = items.length,
slide = 0,
moving = false;
// To initialise the carousel we'll want to update the DOM with our own classes
function setInitialClasses() {
// Target the last, initial, and next items and give them the relevant class.
// This assumes there are three or more items.
items[totalItems - 1].classList.add("prev");
items[0].classList.add("active");
items[1].classList.add("next");
}
// Set click events to navigation buttons
function setEventListeners() {
var next = d.getElementsByClassName('carousel__button--next')[0],
prev = d.getElementsByClassName('carousel__button--prev')[0];
next.addEventListener('click', moveNext);
prev.addEventListener('click', movePrev);
}
// Disable interaction by setting 'moving' to true for the same duration as our transition (0.5s = 500ms)
function disableInteraction() {
moving = true;
setTimeout(function() {
moving = false
}, 500);
}
function moveCarouselTo(slide) {
// Check if carousel is moving, if not, allow interaction
if (!moving) {
// temporarily disable interactivity
disableInteraction();
// Preemptively set variables for the current next and previous slide, as well as the potential next or previous slide.
var newPrevious = slide - 1,
newNext = slide + 1,
oldPrevious = slide - 2,
oldNext = slide + 2;
// Test if carousel has more than three items
if ((totalItems - 1) > 3) {
// Checks if the new potential slide is out of bounds and sets slide numbers
if (newPrevious <= 0) {
oldPrevious = (totalItems - 1);
} else if (newNext >= (totalItems - 1)) {
oldNext = 0;
}
// Check if current slide is at the beginning or end and sets slide numbers
if (slide === 0) {
newPrevious = (totalItems - 1);
oldPrevious = (totalItems - 2);
oldNext = (slide + 1);
} else if (slide === (totalItems - 1)) {
newPrevious = (slide - 1);
newNext = 0;
oldNext = 1;
}
// Now we've worked out where we are and where we're going, by adding and removing classes, we'll be triggering the carousel's transitions.
// Based on the current slide, reset to default classes.
items[oldPrevious].className = itemClassName;
items[oldNext].className = itemClassName;
// Add the new classes
items[newPrevious].className = itemClassName + " prev";
items[slide].className = itemClassName + " active";
items[newNext].className = itemClassName + " next";
}
}
}
// Next navigation handler
function moveNext() {
// Check if moving
if (!moving) {
// If it's the last slide, reset to 0, else +1
if (slide === (totalItems - 1)) {
slide = 0;
} else {
slide++;
}
// Move carousel to updated slide
moveCarouselTo(slide);
}
}
// Previous navigation handler
function movePrev() {
// Check if moving
if (!moving) {
// If it's the first slide, set as the last slide, else -1
if (slide === 0) {
slide = (totalItems - 1);
} else {
slide--;
}
// Move carousel to updated slide
moveCarouselTo(slide);
}
}
// Initialise carousel
function initCarousel() {
setInitialClasses();
setEventListeners();
// Set moving to false now that the carousel is ready
moving = false;
}
// make it rain
initCarousel();
}(document));
/* Parent wrapper to carousel. Width can be changed as needed. */
.carousel-wrapper {
overflow: hidden;
width: 90%;
margin: auto;
}
.carousel-custom-section {
width: 100%;
display: flex;
}
.carousel-single-item {
width: 33%;
display: flex;
}
.carousel-single-item-row {
display: flex;
width: 33%;
flex-direction: row;
}
.carousel-wrapper * {
box-sizing: border-box;
}
.carousel {
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.carousel__photo {
opacity: 0;
position: absolute;
top: 0;
width: 100%;
margin: auto;
padding: 1rem 4rem;
z-index: 100;
/* transition: transform .5s, opacity .5s, z-index .5s; */
}
.carousel__photo.initial,
.carousel__photo.active {
opacity: 1;
position: relative;
z-index: 900;
}
.carousel__photo.prev,
.carousel__photo.next {
z-index: 800;
}
/* Style navigation buttons to sit in the middle, either side of the carousel. */
.carousel__button--prev,
.carousel__button--next {
position: absolute;
top: 50%;
width: 3rem;
height: 3rem;
background-color: #FFF;
transform: translateY(-50%);
border-radius: 50%;
cursor: pointer;
z-index: 1001;
}
.carousel__button--prev {
left: 0;
}
.carousel__button--next {
right: 0;
}
/* Use pseudo elements to insert arrows inside of navigation buttons */
.carousel__button--prev::after,
.carousel__button--next::after {
content: " ";
position: absolute;
width: 10px;
height: 10px;
top: 50%;
left: 54%;
border-right: 2px solid black;
border-bottom: 2px solid black;
transform: translate(-50%, -50%) rotate(135deg);
}
.carousel__button--next::after {
left: 47%;
transform: translate(-50%, -50%) rotate(-45deg);
}
<div class="carousel-wrapper">
<div class="carousel">
<div class="carousel-custom-section">
<div class="carousel-single-item">
<img class="carousel__photo initial" src="https://via.placeholder.com/150/0000FF/808080?text=one">
</div>
<div class="carousel-single-item">
<img class="carousel__photo" src="https://via.placeholder.com/150/FF0000/808080?text=two">
</div>
<div class="carousel-single-item">
<img class="carousel__photo" src="https://via.placeholder.com/150/00FF00/808080?text=three">
</div>
</div>
<div class="carousel-custom-section">
<div class="carousel-single-item">
<img class="carousel__photo" src="https://via.placeholder.com/150/FF0000/808080?text=four">
</div>
<div class="carousel-single-item">
<img class="carousel__photo" src="https://via.placeholder.com/150/00FF00/808080?text=five">
</div>
<div class="carousel-single-item">
<img class="carousel__photo" src="https://via.placeholder.com/150/00FF00/808080?text=six">
</div>
</div>
<div class="carousel__button--next"></div>
<div class="carousel__button--prev"></div>
</div>
</div>
Can somebody please point me in right direction what I am doing wrong?

Javascript CSS transition end firing at start of transition

I'm trying to build a simple slideshow where an image slides out for two seconds whilst another image appears beneath it.
(function ready(fn) {
if (document.readyState != 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
})(init);
function init() {
var pictureCollection = document.getElementsByClassName('slideshowimg');
var pictureTracker = document.getElementsByClassName('trackPoint');
var count = 0;
//load initial pic
pictureCollection[count].style.animation = 'fadein10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'black';
//Fade
var fadetime = setInterval(function() {
fading()
}, 5000);
function fading() {
pictureCollection[count].style.animation = 'fadeout10 2s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count == pictureCollection.length - 1) {
count = -1;
}
count++;
pictureCollection[count].style.animation = 'fadein10 2s forwards';
pictureTracker[count].style.backgroundColor = 'black';
}
function fixer(direction) {
//remove event listener to ensure it doesn't reset EVERY transition
event.target.removeEventListener('transitionend', fixer);
pictureCollection[count].style.animation = 'fadeout10 0.1s forwards';
pictureCollection[count].style.transform = 'translateX(0px)';
//reset counter
if (count === 3 && direction === "right") {
count = 0;
return;
}
if (count === 0 && direction === "left") {
count = 3;
return;
}
if (direction === "right") {
count++;
}
if (direction === "left") {
count--;
}
}
//add event listener to handle user clicks to each lside
for (i = 0; i < pictureCollection.length; i++) {
pictureCollection[i].addEventListener('click', function() {
//cancel autofade
clearInterval(fadetime);
//check where on pic user clicked
if (event.clientX > event.target.width / 2) {
event.target.style.animation = 'nofade10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count === 3) {
pictureCollection[0].style.animation = 'fadein5 0.1s forwards';
pictureTracker[0].style.backgroundColor = 'black';
} else {
//bring next pic forwards and unhide
pictureCollection[count + 1].style.animation = 'fadein5 0.1s forwards';
pictureTracker[count + 1].style.backgroundColor = 'black';
}
//slide out right
event.target.style.transform = 'translateX(250px)';
//ensure that when the picture slides out it repositions behind
pictureCollection[count].addEventListener('transitionend', fixer('right'));
}
//or going left . . .
else {
pictureCollection[count].style.animation = 'nofade10 0.1s forwards';
pictureTracker[count].style.backgroundColor = 'gray';
if (count === 0) {
pictureCollection[3].style.animation = 'fadein5 0.1s forwards';
pictureTracker[3].style.backgroundColor = 'black';
} else {
//bring next pic forwards and unhide
pictureCollection[count - 1].style.animation = 'fadein5 0.1s forwards';
pictureTracker[count - 1].style.backgroundColor = 'black';
}
//slide out left
event.target.style.transform = 'translateX(-' + pictureCollection[count].width + 'px)';
//ensure that when the picture slides out it repositions behind
pictureCollection[count].addEventListener('transitionend', fixer("left"), false);
}
});
}
}
.slideshowimg {
height: 100%;
width: 100%;
position: inherit;
z-index: 0;
opacity: 0;
transition: all 2s ease-in-out;
}
#sliderCase {
overflow: hidden;
position: absolute;
z-index: 5;
background-color: black;
height: 150px;
width: 225px;
}
.trackPoint {
height: 10px;
width: 10px;
margin: 0 2px;
background-color: gray;
display: inline-block;
border-radius: 2em;
text-align: center;
position: relative;
top: 160px;
left: 75px;
}
#keyframes fadein10 {
from {
opacity: 0;
}
to {
opacity: 1;
z-index: 10;
}
}
#keyframes fadeout10 {
from {
opacity: 1;
}
to {
opacity: 0;
z-index: 0;
}
}
#keyframes fadein5 {
from {
opacity: 0;
}
to {
opacity: 1;
z-index: 5;
}
}
#keyframes nofade10 {
from {
opacity: 1;
}
to {
opacity: 1;
z-index: 10;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf8'>
<script src='mainedit.js'></script>
<link rel='stylesheet' href='stylesedit.css' type='text/css'></link>
<title>Slideshow test</title>
</head>
<body>
<h1> Slideshow test: </h1>
<div id='sliderCase'>
<div style='background-color:red' class='slideshowimg'>pic 1</div>
<div style='background-color:blue' class='slideshowimg'>pic 2</div>
<div style='background-color:green' class='slideshowimg'>pic 3</div>
<div style='background-color:orange' class='slideshowimg'>pic 4</div>
</div>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
<span class='trackPoint'></span>
</body>
</html>
It seems as if the transition end event is firing as the transition starts. Additionally the movement of slides seems to be inverted in the snippet, yet works locally.
I have used coloured divs in place of images for the sake of this example.
This isn't correct:
pictureCollection[count].addEventListener('transitionend', fixer("left"), false);
Here, you are calling and adding the return value of fixer("left") to the event listener, which isn't a valid value anyway.

Categories