I am trying to move images inside of a container using Javascript. Ultimately, I want to move it using setTimeout, but for now trying to do it using an event listener on a button click. It seems to work, but only once. I want to keep moving the images when the button is clicked. Any help is helpful and appreciated.
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
</div>
<button id="moveIt">MOVE</button>
<style>
.container {
display: flex;
justify-content: space-around;
overflow: hidden;
max-width: 100%;
z-index: 222;
}
.images {
width: 300px !important;
display: block;
text-align: center;
margin-right: 10px;
height: 400px !important;
}
</style>
<script>
let images = document.querySelectorAll('.images');
const moveBtn = document.getElementById('moveIt');
let pleaseWork = () => {
for(i=0; i < images.length; i++) {
images[i].style.marginLeft = "-300px";
}
}
moveBtn.addEventListener('click', pleaseWork);
</script>
You are setting margin-left to a static number rather than incrementing it. Here's an example that accesses the current margin-left, strips it of the 'px', converts that to a number, then increments it and applies it back to the element.
let images = document.querySelectorAll('.images');
const moveBtn = document.getElementById('moveIt');
let increment = -10
let pleaseWork = () => {
for (i = 0; i < images.length; i++) {
let ml = Number(images[i].style.marginLeft.replaceAll('px', ''))
ml += increment
images[i].style.marginLeft = `${ml}px`;
}
}
moveBtn.addEventListener('click', pleaseWork);
.container {
display: flex;
justify-content: space-around;
overflow: hidden;
max-width: 100%;
z-index: 222;
}
.images {
width: 300px !important;
display: block;
text-align: center;
margin-right: 10px;
height: 400px !important;
}
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
</div>
<button id="moveIt">MOVE</button>
Related
I'm trying to make a smooth, infinite, automatic carousel for my images but I'm stuck. I believe I have the carousel moving (thinking I may be moving the wrong div). The part I'm struggling with is to get the images t0o loop back around when they leave the page, making it infinite. I would love some help.
Thanks
LM
const carousel = document.querySelector(".carousel1");
const imageSection = document.querySelector(".imagesection");
let sliders = document.querySelectorAll('.sliders');
let increment= 0;
let index = 1;
const interval = 100;
const firstClone = sliders[0].cloneNode(true);
const lastClone = sliders[sliders.length -1].cloneNode(true);
let check = sliders.offsetHeight
console.log(check)
// Append the firstclone to the back of the carousel
carousel.appendChild(firstClone);
let timer = setInterval(() => {
increment++
carousel.style.transform = `translateY(-${increment}px)`
console.log('hey')
}, interval);
.imagesection{
width: 50%;
border: 1px solid blue;
display: flex;
flex-direction: row;
overflow: hidden;
}
.carousel1{
border: 1px solid pink;
width: 35%;
margin:0 2.5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.sliders{
border-radius: 5px;
width: 100%;
height: 300px;
margin: 5px 0;
object-fit: cover;
}
.images{
border-radius: 5px;
width: 100%;
height: 100%;
<div class="container">
<div class="heading">
<h1>Hey Luke</h1>
</div>
<div class="imagesection">
<!-- IMAGE SECTION 1 -->
<div class="carousel1">
<div class="sliders">
<img class="images" src="./images/bekir-donmez-eofm5R5f9Kw-unsplash.jpg" alt="clone">
</div>
<div class="sliders">
<img class="images" src="./images/conscious-design-eZIE5ZFR7Cs-unsplash.jpg" alt="second clone">
</div>
<div class="sliders">
<img class="images" src="./images/dane-wetton-t1NEMSm1rgI-unsplash.jpg" alt="third clone">
</div>
<div class="sliders">
<img class="images" src="./images/ginny-rose-stewart-UxkcSzRWM2s-unsplash (1).jpg" alt="">
</div>
</div>
I have a UI that involves (on wider devices) a 2 column layout that scroll in opposite directions in an infinite loop. On page load the UI seems to work pretty well but I really need some help improving some aspects of it.
The key things I want to work on are:
Order of items (projects) matches HTML structure. Currently they're reversed
Improve how the UI reacts and displays on browser resize
Fix ESLint undefined errors for "Map" and Weakmap"
1. Order of Items (projects)
You can see I've number each .project and on load the one that appears last in the HTML is first when viewing the webpage. It would make more sense the 'top' item is visible in the viewport before revealing the others in cascading order on scroll.
2. UI on Browser Resize
Though the UI seems to work well on page load, I think due to the positional values set on each .project this seems to lead to content overlapping or getting cropped on resize. I've tried matchMedia to see if I can run/recalculate once the viewport has 'stopped' resizing but doesn't seem to work.
It doesn't seem as bad going from desktop to mobile size screens. But vice versa, if you open on a narrow viewport and enlarge no content is visible and the UI appears empty until you scroll ...and then the left column doesn't loop (it stops) until you refresh the page.
On the mid-point #media when each .project has 50vh and not 100vh on scroll the items appear to flicker. Again, until you refresh.
It seems like maybe I need to run the script again after each resize? This is for a 'fun' portfolio style project so I appreciate that's a bit heavy on the resource but maybe acceptable in this instance, as it's not a commercial or D2C site?
3. ESLint Errors
Lastly, I get 2 errors saying Map and Weakmap are undefined when I compile using CodeKit and ESLint. That is in relation to these 2 lines...
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
I know there's a couple of issues but I wanted to break them down to try and be as clear as possible.
const leftLoop = document.querySelector(".split-loop__left");
const rightLoop = document.querySelector(".split-loop__right");
const scrollHeight = leftLoop.scrollHeight;
const offsetBoundary = 200; //the offset from the borders at which the element reordering event is triggered
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
[leftLoop, rightLoop],
[rightLoop, leftLoop]
]);
let scrollLockElement = null;
let scrollLockTimeout = null;
// the function sets handlers to scrolling for infinite scrolling
function infiniteScrollHandler(loop) {
const virtualLoop = Array.from(loop.children);
virtualLoop.forEach(
(el) => (el.style.top = scrollHeight / 2 + el.offsetHeight + "px")
);
loop.addEventListener("scroll", () => {
if (virtualLoop.length < 2) return; // not enough items to scroll
const topBound = loop.scrollTop;
const bottomBound = loop.scrollTop + loop.offsetHeight;
const firstEl = virtualLoop[0];
const lastEl = virtualLoop[virtualLoop.length - 1];
if (firstEl.offsetTop >= topBound - offsetBoundary) {
lastEl.style.top = firstEl.offsetTop - lastEl.offsetHeight + "px";
virtualLoop.unshift(lastEl);
virtualLoop.pop();
} else if (
lastEl.offsetTop + lastEl.offsetHeight <
bottomBound + offsetBoundary
) {
firstEl.style.top = lastEl.offsetTop + lastEl.offsetHeight + "px";
virtualLoop.push(firstEl);
virtualLoop.shift();
}
});
}
// the function sets handlers to scrolling for reverse interaction with the linked loop
function reverseLinkLoopHandler(loop) {
loop.addEventListener("scroll", () => {
const delta = lastScrollPos.get(loop) - loop.scrollTop;
lastScrollPos.set(loop, loop.scrollTop);
// this is blocked to prevent deadlock when events of two blocks are called each other.
{
if (scrollLockElement !== null && scrollLockElement !== loop)
return;
scrollLockElement = loop;
clearTimeout(scrollLockTimeout);
scrollLockTimeout = setTimeout(
() => (scrollLockElement = null),
300
);
}
linkedLoops
.get(loop)
.scrollTo(0, linkedLoops.get(loop).scrollTop + delta);
});
}
// set scroll handlers on all loops
linkedLoops.forEach((loop) => {
infiniteScrollHandler(loop);
loop.scrollTo(0, scrollHeight / 2);
lastScrollPos.set(loop, scrollHeight / 2);
reverseLinkLoopHandler(loop);
});
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
scrollbar-width: none;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 2px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 2px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
margin-left: 24px;
}
.split-loop__item {
background: white;
overflow: hidden;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
width: 100%;
}
.project__media {
margin-bottom: 24px;
}
.project__img {
border: 2px solid black;
width: 100%;
max-width: 100%;
}
.project__title {
font-family: Arial;
font-size: 12px;
margin-bottom: 24px;
}
/* Tablet View */
#media screen and (min-width: 400px) {
.split-loop {
height: 100vh;
position: relative;
margin: 0 48px;
}
.split-loop__left {
border-right: 2px solid black;
box-sizing: border-box;
width: 50%;
}
.split-loop__right {
position: fixed;
right: 24px;
bottom: 0;
width: calc(50% - 48px);
}
.split-loop__item {
display: flex;
flex-flow: column;
height: 50vh;
}
.project__media {
display: flex;
flex-grow: 1;
align-items: center;
justify-content: center;
overflow: hidden;
margin-bottom: 24px;
}
.project__img {
box-sizing: border-box;
display: block;
margin-bottom: 0;
width: auto;
max-width: 100%;
height: 100%;
max-height: 100%;
object-fit: contain;
overflow: hidden;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
width: 50%;
overflow: auto;
position: relative;
max-height: 100vh;
}
.split-loop__right:before,
.split-loop__left:before {
display: block;
content: "";
z-index: -1;
height: 9999999px;
}
.split-loop__right {
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
overflow: auto;
max-height: 100vh;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
position: absolute;
}
}
#media screen and (min-width: 600px) {
.split-loop__item {
height: 100vh;
}
}
<header class="bar-left"></header>
<div class="bar-right"></div>
<div class="split-loop" role="main">
<div class="split-loop__left">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #4</h2>
</div>
</div>
</div>
<div class="split-loop__right">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #4</h2>
</div>
</div>
</div>
</div>
On my website, I would like to add a grid consisting of square images (album covers). I also want to add this hover effect to said images: https://codepen.io/jarvis-ai/pen/GRJpQWO. How would I do this?
I have already tried a couple of things I found while researching my question but I never got the result I wanted. I have always had issues with the sizing of the images and making the sizes responsive. Here is a visualization of what I want it to look like and what I to happen:
Grid on a normal-sized monitor:
Grid on a smaller monitor or window:
Image on hover:
Pretty much: If the page is viewed on a normal-sized monitor, there should be 4 images in one row. If the page is viewed on a phone or if the window is resized, the images split into more rows with one row containing less than 4 now. If the mouse is being hovered over an image, the image should do the effect thing.
Notice: I should be able to do the hover effect by myself since there is already a working demo. I am just mentioning that I want the effect so that you can give me a solution that works with the effect.
Here is the last thing I have tried:
:root {
--grey: grey;
--white: white;
}
#music {
width: 100%;
min-height: 100vh;
background-color: var(--grey);
display: flex;
color: var(--white);
justify-content: center;
align-items: center;
text-align: center;
flex-direction: column;
}
#cover-section {
display: flex;
align-items: center;
vertical-align: middle;
justify-content: center;
flex-direction: row;
}
.cover {
flex: 1 0 21%;
width: 100%;
height: auto;
background-image: url(https://commons.wikimedia.org/wiki/File:Stack_Overflow_icon.svg);
}
<div id="music">
<div id="cover-section">
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
<div class="cover"></div>
</div>
</div>
Thanks in advance for your help!
By the way: If I need JavaScript to achieve this, please do not tell me to just use JavaScript but give me some code I could use, as I have done next to nothing with JavaScript before.
Something that works is that.
I cant implement all the part you want, but for use this example in a mobile view use the media-query css.
Something to start, not a definitive solution! It would be expensive to do it all here.
This is the code:
<!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">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<title>Document</title>
<style>
#music {
width: 100%;
height: 100vh;
text-align: center;
margin-top: 60px;
}
#cover-section {
width: 100%;
height: 100vh;
}
.b-game-card {
width: 20%;
height: 30%;
float: left;
}
.cover {
width: 90%;
height: 90%;
background: url('https://m.media-amazon.com/images/I/81aTawcGdmL._AC_SL1500_.jpg');
background-size: cover;
background-position: center;
float: left;
}
</style>
</head>
<body>
<div id="music">
<div id="cover-section">
<div class="b-game-card">
<div class="cover">
</div>
</div>
<div class="b-game-card">
<div class="cover">
</div>
</div>
<div class="b-game-card">
<div class="cover">
</div>
</div>
<div class="b-game-card">
<div class="cover">
</div>
</div>
</div>
</body>
<script>
const maxTilt = 50; // Max card tilt (deg).
$(".b-game-card")
.mousemove(function (evt) {
let bounding = mouseOverBoundingElem(evt);
let posX = bounding.width / 2 - bounding.x;
let posY = bounding.height / 2 - bounding.y;
let hypotenuseCursor = Math.sqrt(Math.pow(posX, 2) + Math.pow(posY, 2));
let hypotenuseMax = Math.sqrt(Math.pow(bounding.width / 3, 2) + Math.pow(bounding.height / 3, 2));
let ratio = hypotenuseCursor / hypotenuseMax;
$(".cover", this).css({
transform: `rotate3d(${posY / hypotenuseCursor}, ${-posX / hypotenuseCursor}, 0, ${ratio * maxTilt}deg)`,
filter: `brightness(${2 - bounding.y / bounding.height})`
});
$(".gloss", this).css({
transform: `translateX(${posX * ratio * 1}px) translateY(${posY * ratio}px)`
});
})
.mouseleave(function () {
let css = {
transform: "",
filter: ""
};
$(".cover, .gloss", this).css(css);
});
function mouseOverBoundingElem(evt) {
let bounding = evt.target.getBoundingClientRect();
let x = evt.originalEvent.pageX - Math.round(bounding.left);
let y = evt.originalEvent.pageY - Math.round(bounding.top);
return {
x: Math.max(0, x),
y: Math.max(0, y),
width: Math.round(bounding.width),
height: Math.round(bounding.height)
};
}
</script>
</html>
I managed to figure out a solution by myself. Here is the code:
HTML:
<div id="music">
<div id="cover-section">
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover">
<!--Cover-->
</div>
<div class="cover" id="tablet-cover">
<!--Cover-->
</div>
</div>
</div>
The tablet cover does not actually exist and is just a placeholder in case there are an uneven amount of squares in one row. As you can see in the...
CSS:
#music {
width: 100%;
min-height: 100vh;
background-color: var(--grey);
display: flex;
color: var(--white);
justify-content: center;
align-items: center;
text-align: center;
flex-direction: column;
}
#cover-section {
display: flex;
flex-wrap: wrap;
width: 80%;
}
.cover {
margin: 0px;
flex: 1 0 21%;
background-color: blue;
border: 2px solid black;
}
#tablet-cover {
display: none;
}
#media only screen and (max-width: 768px) {
/* For phones: */
.cover {
flex: 1 0 41%;
}
#waving-hand span {
font-size: 30pt;
}
}
#media only screen and (min-width: 600px) and (max-width: 800px) {
/* For tablets: */
.cover {
flex: 1 0 31%;
}
#tablet-cover {
display: block;
}
#waving-hand span {
font-size: 70pt;
}
}
The tablet cover is being removed on smaller or larger screens, where there would be an even number of squares in one row. It gets added once there is an uneven amount of covers in a row so that the last row has two squares instead of two rectangles.
Now for the self-engineered JavaScript code:
let coverWidth = document.querySelector('.cover').offsetWidth;
const allCovers = document.getElementsByClassName('cover')
for (var i = 0; i < allCovers.length ; i++){
allCovers[i].style.height= coverWidth + "px";
}
function coverheight(){
let coverWidth = document.querySelector('.cover').offsetWidth;
const allCovers = document.getElementsByClassName('cover')
for (var i = 0; i < allCovers.length ; i++){
allCovers[i].style.height= coverWidth + "px";
}
}
window.onresize = coverheight;
This is what the code basically does:
Check the width of the divs and then apply the value of the div-width to the height attribute of the divs
Every time the screen is resized, it re-checks the values and sets the new values accordingly
I do not know if this code is the "cleanest" code, but as long as it works, I am happy. What sucks to me is that I had to work with media queries, because the flex layout is usually used for when you want a layout that is responsible by default, AFAIK.
Thanks to everyone who tried helping me out though! I hope I can help someone else with my spaghetti code.
I have solved all the problems before, thank you very much for help. But now new ones appeared. The thing is that when I deleted the size of all containers (it was 1024px before), my slide images became way bigger than the screen. See the images 1[and]2.
Please help cause I need slide images to be full sized on the home page without scrolling down.
HTML
<!--Start Home-->
<section class="home" id="home">
<div class="container">
<div class="mySlides">
<img src="img/Home/вид1 классика.jpg" style="width:100%">
</div>
<div class="mySlides">
<img src="img/Home/спальня море1.jpg" style="width:100%">
</div>
<div class="mySlides">
<img src="img/Home/07.jpg" style="width:100%">
</div>
<div class="mySlides">
<img src="img/Portfolio/4/розовая комната (5).jpg" style="width:100%">
</div>
<div class="mySlides">
<img src="img/Portfolio/3/титова мал спальня (3).jpg" style="width:100%">
</div>
</div>
</section>
<!--End Home-->
CSS for the Home section
/*Home Section*/
.home {
height: 100vh;
background-size: cover;
background-position: center;
}
.home .container {
height: 850px;
}
.home .container .mySlides {
padding-top: 70px;
width: 100%;
}
CSS for the whole website (to see the characteristics of main elements)
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font-family: 'Montserrat', sans-serif;
max-width: 100%;
}
*{
box-sizing: border-box;
margin: 0;
padding: 0;
}
.container {
margin: auto;
}
.row {
display: flex;
flex-wrap: wrap;
}
.section-title {
flex: 0 0 100%;
max-width: 100%;
margin-bottom: 40px;
}
.section-title h1 {
display: inline-block;
font-size: 30px;
text-transform: uppercase;
font-weight: 500;
margin: 0 0 10px;
position: relative;
}
.text-center {
text-align: center!important;
}
.text-left {
text-align: left!important;
}
.text-right {
text-align: right!important;
}
JS
// Automatic Slideshow - change image every 5 seconds
var myIndex = 0;
carousel();
function carousel() {
var i;
var x = document.getElementsByClassName("mySlides");
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
myIndex++;
if (myIndex > x.length) {myIndex = 1}
x[myIndex-1].style.display = "block";
setTimeout(carousel, 5000);
}
It is written in the devtools that the section and the container has the height of 850 but the div with slides is way bigger. Don't know why. See 3
Thank in advance for help.
the mySlides div has no height value so it takes the height of his content, and even if it did had a height you have an overflow problem. I suggest giving the img itself the height value or max-height.
So I have been learning animations with JS,CSS,HTML and I was trying to learn how to animate a scroll similar to a this
I have tried to use jQuery-SlotMachine though I am very lost on how the action is executed even with the JS code next to it. Could someone explain me how I can code this with the same API or another or Code it in vanilla JS.
You can try CSS animations with a little javascript code to control your custom animation state.
I think my sample could help you.
CodePen
$(document).ready(function() {
let $elements = $(".element");
let $transitionList = $(".transition-list");
let currentIndex = 0;
setInterval(function() {
$transitionList.css(
"transform",
"translateY(" + currentIndex * -250 + "px)"
);
currentIndex++;
if ($elements.length - 1 < currentIndex) {
currentIndex = 0;
}
}, 750);
});
body {
display: flex;
align-items: center;
justify-content: center;
}
.container {
display: flex;
width: 50%;
}
.center {
align-items: center;
justify-content: center;
}
.border-container {
border: 25px solid #dfe0a0ed;
border-radius: 30%;
overflow: hidden;
}
.transition-list {
width: 250px;
height: 250px;
background-color: #fefefe;
transition-property: all;
transition-duration: 0.5s;
transition-timing-function: cubic-bezier(0, 1, 0.1, 0.2, 0.7, 1);
}
.element {
background-color: #6f6f6f;
width: 250px;
height: 250px;
font-size: 188px;
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<div class="conainer center">
<div class="border-container">
<div class="transition-list">
<div class="element center"><i class="fas fa-clock"></i></div>
<div class="element center"><i class="fas fa-unlock"></i></div>
<div class="element center"><i class="fas fa-th"></i></div>
<div class="element center"><i class="fas fa-american-sign-language-interpreting"></i></div>
</div>
</div>
</div>
1. To begin, you must have a container:
<div id="theContainer" class="container">
</div>
2. Great, now let's put some images in it.
<div id="theContainer" class="container">
<img src="https://picsum.photos/100/?random">
<img src="https://picsum.photos/100/?random">
<img src="https://picsum.photos/100/?random">
</div>
3. Now, let's add two buttons to move it:
<div id="theContainer" class="container">
<img src="https://picsum.photos/100/?image=0">
<img src="https://picsum.photos/100/?image=1">
<img src="https://picsum.photos/100/?image=2">
</div>
<button id="prev" value="Previous">
<button id="next" value="Next">
4. Sweet! We got our HTML, now we just got to add our Javascript:
// Set up previous button
const btnPrev = document.querySelector('#prev');
// Set up Next Button
const btnNext = document.querySelector('#next');
// Set up our container
const el = document.querySelector('#theContainer');
// Create new SlotMachine
const slot = new SlotMachine(el, {});
// Add Event Listeners or do things when we click it
btnPrev.addEventListener('click', () => slot.prev());
btnNext.addEventListener('click', () => slot.next());
<link href="https://cdn.jsdelivr.net/npm/jquery-slotmachine#4.0.0/dist/jquery.slotmachine.min.css"></style>
<div id="theContainer" class="container" style="width: 100px; height: 100px">
<div><img src="https://picsum.photos/100/?image=0"></div>
<div><img src="https://picsum.photos/100/?image=1"></div>
<div><img src="https://picsum.photos/100/?image=2"></div>
</div>
<button id="prev">Previous</button>
<button id="next">Next</button>
<!-- Add script files -->
<script src="https://cdn.jsdelivr.net/npm/jquery-slotmachine#4.0.0/dist/slotmachine.min.js"></script>
5. Notes:
you must add a width & height to #theContainer. (style="width: 100px; height: 100px")
the images must be surrounded by a block element. (<div><img /></div>)