JQuery For simple horizontal slider - javascript

Hi There,
I try to create very simple slider using Jquery scrollLeft() method .
I found some answers and i tried this one here .... but not working .... I'm still beginner in jquery and don't know why .
HTML
<div class="gallery-slider ">
<div class="images-preview">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
<img alt="" class="img-responsive" src="http://placehold.it/300">
</div>
<div class="controls">
<div class="right-arrow"><i class="fa fa-angle-left fa-3x"></i></div>
<div class="left-arrow"><i class="fa fa-angle-right fa-3x"></i></div>
</div>
</div>
CSS
.gallery-slider {
position: relative;
}
.gallery-slider .images-preview {
margin: auto;
height: 230px;
overflow: hidden;
}
.gallery-slider .images-preview img {
display: inline-block;
overflow: visible;
width: 410px;
margin: 10px 17px;
}
.gallery-slider .images-preview img, .controls {
height: 200px;
width: 26%;
}
/* Controls */
.controls {
position: absolute;
top: 10px;
width: 100%;
}
.right-arrow, .left-arrow {
display: inline-block;
padding: 62px;
background-color: rgba(255, 255, 255, 0.76);
position: absolute;
height: 100%;
cursor: pointer;
}
.right-arrow i, .left-arrow i{
margin: 23px 20px;
}
.left-arrow {
right: 0px;
}
.right-arrow {
left: 0px;
text-align: right;
}
jQuery
$(".left-arrow").click(function () {
var leftPos = $('.images-preview img').scrollLeft();
$(".images-preview img").animate({scrollLeft: leftPos - 100}, 1000);
});
$(".right-arrow").click(function () {
var leftPos = $('.images-preview img').scrollLeft();
$(".images-preview img").animate({scrollLeft: leftPos + 100}, 1000);
});
So Any help ?!
Thanks in advance
Fiddle here
Update:
also i need it to return to scrollleft():0 at the end of scrolling

What you are asking for is simple but full of issues. These issues makes things complicated.
I have made images-preview position absolute. It allows you to
scroll by controlling the left(css). Couldnt get the scrollLeft to
work. Dont know why. If anyone do, i would love to know.
Need to calculate the number of img inside the images-preview. Allow you to add or delete images.
var active is added to prevent clicking too fast.
javascript:
var target = $('.images-preview');
//get the total number of images
var total = $('.images-preview img').length;
//calculate the width of the image-preview
var width = total * 300 + total * 40;
var c = 1;
// 80 is to center the image-preview
var originalLeft = 80;
// 300 is the image size, 40 is the total margin (this is how many px image-preview
// would have to move left for one image
var totalImg = 300 + 40;
// startToEnd is the total width when you click left(arrow-right) on first image
var startToEnd = width -originalLeft -340;
var a = '';
//need this to prevent multiple clicks
var active = false;
//put in the width at page rendering
$(document)function(){
target.css('width', width);
});
$(".left-arrow").click(function () {
if (active === false){
if (c === total){
a = originalLeft;
c = 1;
}else{
a = '-='+totalImg;
c++;
}
//turn the active to true to prevent another animation from activating
active = true;
target.animate(
{left: a},
{duration:500,
//turn the active off after animation is complete
complete: function(){
active = false;
}
});
}
});
$(".right-arrow").click(function () {
if (active === false){
if (c === 1){
a = '-'+startToEnd;
c = total;
}else{
a = '+='+totalImg;
c--;
}
active = true;
target.animate(
{left: a},
{duration:500,
complete: function(){
active = false;
}
});
}
});
css:
.gallery-slider{
width:500px;
height:300px;
position:relative;
overflow:hidden;
}
.images-preview{
width:300px;
height:300px;
position:absolute;
left:80px;
}
.images-preview img{
width:300px;
height:300px;
position:relative;
float:left;
margin:0 20px;
}
.control{
width:100%;
height:100%;
position:relative;
}
.right-arrow, .left-arrow{
position:absolute;
padding:0 26px;
}
.right-arrow i, .left-arrow i{
line-height:300px;
}
.right-arrow{
left:0;
}
.left-arrow{
right:0;
}
Here is the demo: https://jsfiddle.net/ood26n7b/1/

Related

set div height to an image height with javascript

I have an image gallery with a main image and some thumbnail images on the right side of the main image.
I want to set the height of the thumbnails div the same as the main image. The problem is, this image is always different so it doesn't have a static height. Tried to use javascript to get it's height then give it to the thumbnails div, but it doesn't do anything.
<div class="gallery">
<a href="images/1.jpg">
<div class="main-image">
<img class="card-img-top" id="modal-img-top" src="images/1.jpg" alt="Fő kép">
</div>
<div class="image-container" id="image-thumbnails">
<img src="images/1.jpg" alt="Egy kép a hirdetésről">
<img src="images/motor.jpg" alt="Egy kép a hirdetésről">
<img src="images/motor2.jpg" alt="Egy kép a hirdetésről">
<img src="images/2.jpg" alt="Egy kép a hirdetésről">
<img src="images/1.jpg" alt="Egy kép a hirdetésről">
<img src="images/motor.jpg" alt="Egy kép a hirdetésről">
<img src="images/motor2.jpg" alt="Egy kép a hirdetésről">
<img src="images/2.jpg" alt="Egy kép a hirdetésről">
</div>
</a>
</div>
<script type="text/javascript">
const img = new Image();
img.onload = function() {
alert(this.width + 'x' + this.height);
document.getElementById("image-thumbnails").style.height = this.height;
}
img.src = document.getElementById("modal-img-top").getElementsByTagName('img');
</script>
Edit: Ok let's have another try.
The main issue is to size your main image which should stay in its ratio and be wrapped in its parent. After trial and error there seems to be no easy method to archive this. I also tried object-fit property, but event this is not working as you want to. So here are my two solutions.
Solution 1:
The most easy way is to use a div with the background-image property instead of an img. As you see in the solution below, the main-image is a div now. You could also use the element .image-wrapper as the background image. But I wrapped a main-image into it to get some padding between these two elements.
Solution 2: Instead of using the background-image property you can still use a img, but you'll need some javascript and calculations. The calculation is done by the function calculateMainImage. It is not too complex, but it needs some lines. The strategy is this:
Get the dimensions of the main image and its parent element
Assume that the image fits into its parent (in css: width: 100%). So calculate the image dimensions for this assumption.
If the calculated height is greater than the height of the parent, the image won't fit into the parent. So now set the image's height to the height of its parent and recalculate the width.
This function is also called when the document is ready (initialization) and when the window resizes (window.onresize).
let mainImage = document.querySelector('.main-image');
let thumbnails = document.querySelectorAll('.thumbnail');
thumbnails.forEach(thumbnail => {
thumbnail.addEventListener('click', () => {
let backgroundImage = 'url(' + thumbnail.src +')';
mainImage.style.backgroundImage = backgroundImage;
});
});
.gallery{
position: relative;
width: 100%;
height: 400px;
background: #dedede;
display: grid;
grid-template-columns: 70% 30%;
}
.image-wrapper{
position: relative;
width: 100%;
height: 100%;
background: #aaa;
padding: 12px;
box-sizing: border-box;
}
.main-image{
position: relative;
width: 100%;
height: 100%;
background-image: url("https://via.placeholder.com/350x150");
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.thumbnail-wrapper{
position: relative;
width: 100%;
height: 100%;
overflow-y: auto;
padding: 12px;
box-sizing: border-box;
}
.thumbnail-wrapper > .thumbnail:not(:last-child){
margin-bottom: 12px;
}
.thumbnail{
position: relative;
display: block;
width: 100%;
height: auto;
margin-left: auto;
margin-right: auto;
cursor: pointer;
}
<section class="gallery">
<!-- Main image -->
<div class="image-wrapper">
<div class="main-image">
</div>
</div>
<!-- Thumbnails -->
<div class="thumbnail-wrapper">
<img class="thumbnail" src="https://via.placeholder.com/350x150">
<img class="thumbnail" src="https://via.placeholder.com/200x100">
<img class="thumbnail" src="https://via.placeholder.com/140x100">
<img class="thumbnail" src="https://via.placeholder.com/350x65">
<img class="thumbnail" src="https://via.placeholder.com/350x150">
<img class="thumbnail" src="https://via.placeholder.com/200x100">
<img class="thumbnail" src="https://via.placeholder.com/140x100">
</div>
</section>
let gallery = document.querySelector('.gallery');
let container = document.querySelector('.container');
let mainImage = document.querySelector('.main-image');
let thumbnails = document.querySelectorAll('.thumbnail');
(function(){
// Document ready
calculateMainImage();
// When window resizes
window.addEventListener('resize', () => {
calculateMainImage();
});
})();
thumbnails.forEach(thumbnail => {
thumbnail.addEventListener('click', () => {
mainImage.src = thumbnail.src;
// Fit image to container
calculateMainImage();
});
});
function calculateMainImage(){
// Reset current dimensions
mainImage.style.width = 'initial';
mainImage.style.height = 'initial';
// Container dimensions
let containerWidth = container.getBoundingClientRect().width;
let containerHeight = container.getBoundingClientRect().height;
// Image dimensions
let width = mainImage.getBoundingClientRect().width;
let height = mainImage.getBoundingClientRect().height;
let ratio = width / height;
// Calculate image dimensions when width: 100%
let maxWidth = containerWidth;
let maxHeight = maxWidth / ratio;
// Check if image fits in parent
if(maxHeight > containerHeight){
// Scale image down. Recalculate image's width
let newHeight = containerHeight;
let newWidth = newHeight * ratio;
setMainImageSize(newWidth, newHeight);
}else{
setMainImageSize(maxWidth, maxHeight);
}
}
function setMainImageSize(width, height){
mainImage.style.width = width + 'px';
mainImage.style.height = height + 'px';
}
.gallery{
position: relative;
width: 100%;
height: 400px;
background: #dedede;
display: grid;
grid-template-columns: 70% 30%;
}
.image-wrapper{
position: relative;
width: 100%;
height: 100%;
background: #aaa;
padding: 12px;
box-sizing: border-box;
}
.container{
position: relative;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.main-image{
position: relative;
flex-grow: 0;
flex-shrink: 0;
}
.thumbnail-wrapper{
position: relative;
width: 100%;
height: 100%;
overflow-y: auto;
padding: 12px;
box-sizing: border-box;
}
.thumbnail-wrapper > .thumbnail:not(:last-child){
margin-bottom: 12px;
}
.thumbnail{
position: relative;
display: block;
width: 100%;
height: auto;
margin-left: auto;
margin-right: auto;
cursor: pointer;
}
<section class="gallery">
<!-- Main image -->
<div class="image-wrapper">
<div class="container">
<img class="main-image" src="https://via.placeholder.com/200x100">
</div>
</div>
<!-- Thumbnails -->
<div class="thumbnail-wrapper">
<img class="thumbnail" src="https://via.placeholder.com/350x150">
<img class="thumbnail" src="https://via.placeholder.com/200x100">
<img class="thumbnail" src="https://via.placeholder.com/140x100">
<img class="thumbnail" src="https://via.placeholder.com/350x65">
<img class="thumbnail" src="https://via.placeholder.com/350x150">
</div>
</section>
Update
When you have several gallerys on your page and use use solution #1, then you need to add this JS snipped.
let gallerys = document.querySelectorAll('.gallery');
gallerys.forEach(gallery => {
updateGalleryPictures(gallery)
});
function updateGalleryPictures(gallery) {
// Get gallery's main image
let mainImage = gallery.querySelector('.main-image');
if (mainImage === null) return;
// Get gallery's thumbnail images
let thumbnails = gallery.querySelectorAll('.thumbnail');
// Change the background-image property on click
thumbnails.forEach(thumbnail => {
thumbnail.addEventListener('click', () => {
let backgroundImage = 'url(' + thumbnail.src + ')';
mainImage.style.backgroundImage = backgroundImage;
});
});
// Initialize background-image property using the 1st thumbnail image
let firstThumbnail = thumbnails[0];
if (firstThumbnail === null || firstThumbnail === undefined) return;
let initialBackgroundImage = 'url(' + firstThumbnail.src + ')';
mainImage.style.backgroundImage = initialBackgroundImage;
}
Update 2: Usage of baguetteBox
Step 1: Add the property overflow: hidden; to the class .image-wrapper and create a new class
.baguettebox-image{
opacity: 0 !important;
}
Step 2: Change the structure of the main-image setup.
<div class="image-wrapper">
<div class="main-image"> <!-- THis is the baguette box -->
<a class="baguettebox-link" href="">
<img class="baguettebox-image" src=""></a>
</a>
</div>
</div>
Step 3: Change the JS snipped of the 1st update to:
Note that the baguette boxes are also initialized in this script. According to the documentation querySelectorAll is used, so all boxes (.main-image) should be initialized.
let gallerys = document.querySelectorAll('.gallery');
gallerys.forEach(gallery => {
updateGalleryPictures(gallery);
});
// Initialize all baguette boxes
baguetteBox.run('.main-image');
function updateGalleryPictures(gallery) {
// Get gallery's thumbnail images
let thumbnails = gallery.querySelectorAll('.thumbnail');
// Change the background-image property on click
thumbnails.forEach(thumbnail => {
thumbnail.addEventListener('click', () => {
updateMainImage(gallery, thumbnail.src)
});
});
// Initialize background-image property using the 1st thumbnail image
let firstThumbnail = thumbnails[0];
if (firstThumbnail === null || firstThumbnail === undefined) return;
updateMainImage(gallery, firstThumbnail.src)
// Initialize baguette
}
function updateMainImage(gallery, src) {
// Get main image and check if it exists
let mainImage = gallery.querySelector('.main-image');
if (mainImage === null) return;
mainImage.style.backgroundImage = 'url(' + src + ')';
// Get baguette elements
let boxLink = gallery.querySelector('.baguettebox-link');
let boxImage = gallery.querySelector('.baguettebox-image');
// Update baguette elements href and src
if (boxLink !== null && boxLink !== undefined) boxLink.href = src;
if (boxImage !== null && boxImage !== undefined) boxImage.src = src;
}
document.getElementById("image-thumbnails").style.height = '300px';

Avoid slideshow div resizing according to displayed image?

I did a slideshow with fade animation of images in a div. However, when the next image shows, the div gets smaller/bigger according to the image and the page auto-scrolls, and I do not want that. How can I avoid this?
I wrote a function that once the page loads, it finds the biggest image, and sets the div to have that height of that image so that whenever a new image shows, the div height does not change. However, the problem is when the browser gets smaller/larger, the value of the div's height does not change even though I am resitting it every time the browser changes the size using on resize listener ("biggestImage" variable).
JQuery
var slideIndex = 0;
showSlides();
divResizeIssue();
function showSlides() {
var slides = $(".images");
slides.each(function(){
$(this).fadeOut(500).delay(490);
});
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides.each(function(index){
if(index == slideIndex-1){
$(this).fadeIn(500).delay(490);
}
});
setTimeout(showSlides, 5000);
}
function divResizeIssue(){
var biggestImage;
var object;
var slides = $(".images");
var firstLoad = true;
if(firstLoad){
slides.each(function(index){
if(index == 0 || $(this).outerHeight() > biggestImage){
biggestImage = $(this).outerHeight();
object = $(this)[0]
}
});
slides.each(function(){
if($(this)[0] != object){
$(this).outerHeight(biggestImage);
}
});
firstLoad = false;
}
$(window).on('resize', function(){
biggestImage = 0;
object = null;
slides.each(function(index){
if(index == 0 || $(this).outerHeight() > biggestImage){
biggestImage = $(this).outerHeight();
object = $(this)[0];
}
});
slides.each(function(){
if($(this)[0] != object){
$(this).outerHeight(biggestImage);
}
});
});
}
HTML
<div id="top-div" class="row">
<div class="row">
<h1 class="col-sm-12">Activities</h1>
<span class="col-sm-2"><!-- <button class="leftButton"></button> --></span>
<div class="col-sm-12 col-lg-8">
<figure class="images">
<figcaption class="caption">Outdoor</figcaption>
<img class="img-fluid" id="Outdoor" src=".\src\Hiking.jpg">
</figure>
<figure class="images">
<figcaption class="caption">Indoor</figcaption>
<img class="img-fluid" id = "Indoor" src=".\src\indoor.jpg">
</figure>
<figure class="images">
<figcaption class="caption">Join Us!</figcaption>
<img class="img-fluid" id = "Member" src=".\src\member.png">
</figure>
</div>
<span class="col-sm-2"><!-- <button class="rightButton"> --></button></span>
</div>
</div>
CSS
#top-div {
width: 100%;
margin-top:90vh;
background: #AB3F05;
text-align: center;
height: auto;
}
figure img{
padding-left: 5vh;
padding-right: 5vh;
padding-top: 0;
padding-bottom: 0;
margin: 0;
}
.images{
position: relative;
}
If you have some better suggestion, please do suggest, or if you can tell me what's wrong with my code, that would be great.
Generally speaking, when doing slide shows it's much easier and looks nicer when you just manually resize the images to the same resolution using gimp or photoshop.
However if for whatever reason you can't do that you can use percentages in CSS to create dynamic lengths.
Here's what I came up with
//changed '.images' to '.image-container' also removed the divResizeIssue //function because we don't need it
var slideIndex = 0;
showSlides();
function showSlides() {
var slides = $(".image-container"); //here
slides.each(function(){
$(this).fadeOut(500).delay(490);
});
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides.each(function(index){
if(index == slideIndex-1){
$(this).fadeIn(500).delay(490);
}
});
setTimeout(showSlides, 5000);
}
CSS
#top-div {
width: 100%;
margin-top:90vh;
background: #AB3F05;
text-align: center;
height: auto;
}
figure img{
padding-left: 5vh;
padding-right: 5vh;
padding-top: 0;
padding-bottom: 0;
margin: 0;
}
/*Changed Below*/
.image-container {
width: 50%;
margin: 0 auto;
}
.image {
width: 100%;
height: 400px;
}
.image-container
the width: 50% makes it so the .image-container resizes when the browser viewport changes width. margin: 0 auto centers the .image-container inside it's parent.
.image
the width: 100% streaches the img tag to be the width of its parent (the .image-container).
the fixed height: 400px keeps tall images from expanding the height of the parent.
HTML
<div id="top-div" class="row">
<div class="row">
<h1 class="col-sm-12">Activities</h1>
<span class="col-sm-2"><!-- <button class="leftButton"></button> --></span>
<div class="col-sm-12 col-lg-8">
<figure class="image-container">
<figcaption class="caption">Outdoor</figcaption>
<img class="image img-fluid" id="Outdoor" src="https://picsum.photos/200/300">
</figure>
<figure class="image-container">
<figcaption class="caption">Indoor</figcaption>
<img class="image img-fluid" id = "Indoor" src="https://picsum.photos/300/300">
</figure>
<figure class="image-container">
<figcaption class="caption">Join Us!</figcaption>
<img class="image img-fluid" id = "Member" src="https://picsum.photos/400/300">
</figure>
</div>
<span class="col-sm-2"><!-- <button class="rightButton"> --></button></span>
</div>
</div>
I just renamed the class="images" to class="image-container" and added an image class to the img elements, also changed the src on the images to use picsum so you might want to change them back.
The solution that I did was harcoding height values when the screen size changes, I don't really like to hardcode it, but it's the only way I can think of right now.
CSS
#media only screen and (min-width: 576px) {
/*Change slides height to 950px when at sm (576px)*/
#top-div{
height: 950px;
}
}
#media only screen and (max-width: 576px) {
/*Change slides height to 440px when greater than sm*/
#top-div{
height: 440px;
}
}

jquery image slider at multiple time interval

I am trying to implement a jquery image slider. Following is my code and there is something that prevents me achieving what I am looking for. Could someone explain to me what am I doing wrong here? Meanwhile, in the 'motion2' class, I am trying to move the slider image at a separate time from the 'motion1' class. How to do it efficiently. Thank you
$(function(){
//configuration
let width = $('.two').width();
let animationSpeed = 2000;
let pause = 4000;
let currentSlide = 1;
//cache
let $image = $('.motion1').find('img');
setInterval(function(){
$image.animate({'margin-left': '-=' + width}, animationSpeed, function(){
currentSlide++;
if (currentSlide === $image.length){
currentSlide = 1;
$image.css({'margin-left': 0});
}
});
}, pause);
});
html, body{
margin:0;
padding:0;
}
.one{
height:25rem;
width:80rem;
background:orange;
margin:0 auto;
display:grid;
grid-template-columns:1fr 1fr 1fr;
overflow:hidden;
}
.two{
border:1px solid;
height:100%;
overflow:hidden;
}
img{
width:100%;
height:100%;
object-fit:cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="one">
<div class='two motion1'>
<img src="https://www.mtlblog.com/uploads/ded37dd9e380abe15e45eea13ed050c13e5fe206.jpg_facebook.jpg" alt="">
<img src="https://wallpaperbrowse.com/media/images/soap-bubble-1958650_960_720.jpg" alt="">
</div>
<div class='two motion2'>
<img src="https://cdn-image.travelandleisure.com/sites/default/files/styles/1600x1000/public/1497645355/04-banff-national-park-moraine-lake-canada-150CANADA0617.jpg?itok=O6eAZSSV" alt="">
<img src="data:image/jpeg;base64,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" alt="">
</div>
<div class='two motion1'>
<img src="http://www.adventureworld.co.nz/advnz/media/destinations/south-america/latin-america/venezuela/tours/canada-best-of-ontario-and-quebec-river-2000.jpg" alt="">
<img src="https://cdn.theculturetrip.com/wp-content/uploads/2015/11/New-Zealand-%C2%A9-vichie81-Shutterstock.jpg" alt="">
</div>
</div>
Well, I tried to reuse some components and ended up with this dirty (hackish) approach.
I am sure there is a better way to do it but I just don't have the time to work on it right now... Feel free to comment if you do not think this will be useful and I will remove the answer if that's the case.
$(function() {
//configuration
let width = $('.two').width();
let animationSpeed = 2000;
let pause1 = 4000;
let pause2 = 6000;
let currentSlide = 0;
let currentSlideRight = 0;
let currentSlideLeft = 0;
//cache
let $images = $('.motion-middle').find('img');
let $image = $images[currentSlide];
let $rightImages = $('.motion-right').find('img');
let $rightImage = $rightImages[currentSlideRight];
let $leftImages = $('.motion-left').find('img');
let $leftImage = $leftImages[currentSlideLeft];
$([$image, $rightImage, $leftImage]).show();
setInterval(function() {
anim($image, $images, currentSlide, 'middle');
}, 3500);
setInterval(function() {
anim($leftImage, $leftImages, currentSlideLeft, 'left');
}, 4000);
setInterval(function() {
anim($rightImage, $rightImages, currentSlideRight, 'right');
}, 5500);
function anim(img, imageArray, slideIdx, position) {
$(img).animate({
"margin-left": -width
}, animationSpeed, function() {
nextImg(img, imageArray, slideIdx, position);
});
}
function nextImg(img, imageArray, idx, position){
idx++;
$(img).hide();
// reset
if (idx >= imageArray.length) {
idx = 0;
}
var imgObj;
switch(position){
case 'left':
$leftImage = imageArray[idx];
imgObj = $leftImage;
currentSlideLeft = idx;
break;
case 'middle':
$image = imageArray[idx];
imgObj = $image;
currentSlide = idx;
break;
case 'right':
$rightImage = imageArray[idx];
imgObj = $rightImage;
currentSlideRight = idx;
break;
}
$(imgObj).css("margin-left",0).show();
}
});
html,
body {
margin: 0;
padding: 0;
}
.one {
height: 25rem;
width: 80rem;
background: orange;
margin: 0 auto;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
overflow: hidden;
}
.two {
border: 1px solid;
height: 100%;
overflow: hidden;
}
.two>img {
display: none;
}
img {
width: 100%;
height: 100%;
object-fit: cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="one">
<!-- left -->
<div class='two motion-left'>
<!--image 1-->
<img src="https://cdn-image.travelandleisure.com/sites/default/files/styles/1600x1000/public/1497645355/04-banff-national-park-moraine-lake-canada-150CANADA0617.jpg?itok=O6eAZSSV" alt="">
<!--image 2-->
<img src="https://cdn.theculturetrip.com/wp-content/uploads/2015/11/New-Zealand-%C2%A9-vichie81-Shutterstock.jpg" alt="">
<!--image 3-->
<img src="https://wallpaperbrowse.com/media/images/soap-bubble-1958650_960_720.jpg" alt="">
</div>
<!-- middle -->
<div class='two motion-middle'>
<!--image 1-->
<img src="https://cdn-image.travelandleisure.com/sites/default/files/styles/1600x1000/public/1497645355/04-banff-national-park-moraine-lake-canada-150CANADA0617.jpg?itok=O6eAZSSV" alt="">
<!--image 2-->
<img src="https://cdn.theculturetrip.com/wp-content/uploads/2015/11/New-Zealand-%C2%A9-vichie81-Shutterstock.jpg" alt="">
<!--image 3-->
<img src="https://wallpaperbrowse.com/media/images/soap-bubble-1958650_960_720.jpg" alt="">
</div>
<!-- right -->
<div class='two motion-right'>
<!--image 1-->
<img src="https://cdn-image.travelandleisure.com/sites/default/files/styles/1600x1000/public/1497645355/04-banff-national-park-moraine-lake-canada-150CANADA0617.jpg?itok=O6eAZSSV" alt="">
<!--image 2-->
<img src="https://cdn.theculturetrip.com/wp-content/uploads/2015/11/New-Zealand-%C2%A9-vichie81-Shutterstock.jpg" alt="">
<!--image 3-->
<img src="https://wallpaperbrowse.com/media/images/soap-bubble-1958650_960_720.jpg" alt="">
</div>
</div>

Click toggle with multiple targets

I have a two images and when you click on one, text (relevant to image) slides into view below the image. Currently the method for closing/toggling the text is to click on the image again.
If I click on the second image while the text on the first image is still visible, it closes the text. I then have to click on the second image again to see its text content appear.
I'd like to be able to click on the second image and either the text content just swaps OR it closes the text for the first image and opens the text for the second image (in just one click, not two).
Any input appreciated!
I have a fiddle here
JS:
var teamMember = document.getElementsByClassName("team-member");
var teamRow = document.getElementsByClassName("team-row");
var bioContainer = $( "<div class='container' id='bio-container'></div>" );
$(bioContainer).hide();
$(teamMember).click(function() {
$(this).toggleClass('member-selected');
$('.team-grid').toggleClass('member-active');
$(bioContainer).html("");
var thisBio = $(this).find(".team-bio");
var thisRow = $(this).parent(teamRow);
$(thisRow).after(bioContainer);
var bioHTML = $(thisBio).html();
$height = $(thisBio).outerHeight(true)
$(bioContainer).css('height', $height);
$(bioContainer).slideToggle( "slow", function() {
$(this).html(bioHTML);
});
});
HTML:
<section class="team-grid">
<div class="team-row">
<div class="col-sm-6 team-member">
<img src="https://www.catster.com/wp-content/uploads/2017/11/A-Siamese-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
JOHN'S Bio
</div>
</div>
</div>
<div class="col-sm-6 team-member">
<img src="https://r.hswstatic.com/w_907/gif/tesla-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
SALLY'S Bio
</div>
</div>
</div>
</div>
</section>
CSS:
.col-sm-6 {
width:50%;
float:left;
}
img {
width:100%;
height:200px;
object-fit:cover;
cursor:pointer;
}
.close-bio {
color:pink;
font-weight:bold;
}
.team-bio {
visibility: hidden;
padding: 80px 20%;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
#bio-container {
background: #666;
width: 100%;
max-width: none;
position: relative;
float: left;
padding: 25px;
color:#fff;
font-size:20px;
}
Please check this answer,
Js Fiddle
var teamMember = document.getElementsByClassName("team-member");
var teamRow = document.getElementsByClassName("team-row");
var bioContainer = $( "<div class='container' id='bio-container'></div>" );
var bioContainerExpanded = false;
$(bioContainer).hide();
$(teamMember).click(function() {
if(bioContainerExpanded){
$(bioContainer).slideToggle( "slow", function() {});
bioContainerExpanded = false;
}
$('.team-grid').toggleClass('member-active');
// Resets bioContainer html to blank
$(bioContainer).html("");
$(this).toggleClass('member-selected');
// Assign 'this' team bio to variable
var thisBio = $(this).find(".team-bio");
// Assign 'this' row to variable (find teamRow parent of this teamMember)
var thisRow = $(this).parent(teamRow);
// Place bio after row
$(thisRow).after(bioContainer);
// Assign 'this' bio html to variable
var bioHTML = $(thisBio).html();
// Dynamically calculte height of the bio including padding
$height = $(thisBio).outerHeight(true)
//assign height to bioContainer before the toggle so that it slides smoothly
$(bioContainer).css('height', $height);
// Slide toggle the bioContainer
$(bioContainer).slideToggle( "slow", function() {
// Insert bioHTML into 'this' bioContainer
$(this).html(bioHTML);
});
bioContainerExpanded = true;
});
.col-sm-6 {
width:50%;
float:left;
}
img {
width:100%;
height:200px;
object-fit:cover;
cursor:pointer;
}
.close-bio {
color:pink;
font-weight:bold;
}
.team-bio {
visibility: hidden;
padding: 80px 20%;
position: fixed;
top: 0;
left: 0;
width: 100%;
}
#bio-container {
background: #666;
width: 100%;
max-width: none;
position: relative;
float: left;
padding: 25px;
color:#fff;
font-size:20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="team-grid">
<div class="team-row">
<div class="col-sm-6 team-member">
<img src="https://www.catster.com/wp-content/uploads/2017/11/A-Siamese-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
JOHN'S Bio
</div>
</div>
</div>
<div class="col-sm-6 team-member">
<img src="https://r.hswstatic.com/w_907/gif/tesla-cat.jpg">
<div class="team-bio">
<div class="team-bio-inner">
SALLY'S Bio
</div>
</div>
</div>
</div>
</section>

Animate a PNG sequence by scrolling

Basically, I want to dynamically add/remove the class .show to the images inside .container depending on the scroll position. I want to change the class after some position.
$(document).ready(function() {
var container = $('#container'),
nImg = 0; // active picture
imgNum = $('#container img').length;
var topDiv = (container).offset() || {
"top": NaN
}).top;
$(window).bind('scroll', function() {
var y = $(this).scrollTop();
if (y > topDiv) {
nImg++;
} else {
nImg--;
}
if (nImg >= imgNum) {
nImg = 0;
}
if (nImg < 0) {
nImg = imgNum - 1;
}
$(".animated").each(function() {
$(this).removeClass("show")
});
$(".animated").eq(nImg).addClass("show");
});
});
.animated {
display: none;
}
.show {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:200px"></div>
<div id="container">
<img src="http://i.imgur.com/2oVbl7z.png" class="animated show" />
<img src="http://i.imgur.com/S5s0Mv1.png" class="animated" />
<img src="http://i.imgur.com/0vBEXL7.png" class="animated" />
<img src="http://i.imgur.com/ffg7v9n.png" class="animated" />
<img src="http://i.imgur.com/9FD5kdE.png" class="animated" />
</div>
If you scroll slowly you see that it actually works, but much too fast - that's the problem. I just to move slowly and want to start it from after some position.
See the below example for how to animate sequence image when page scroll.
$(document).ready(function () {
$('.aniScrollContainer').aniScroll({});
});
.aniScrollContainer {
height:300px;
background-color:#a1a1a1;
}
.myAniScrollContainer200 {
height:200px;
}
#header {
display: block;
height: 500px;
width: 100%;
background-color:#e0e0e0;
}
.gap {
display: block;
height: 100px;
width: 100%;
background-color:#e0e0e0;
}
#footer {
display: block;
height: 1500px;
width: 100%;
background-color:#e0e0e0;
}
.aniScrollContainer {
position: relative;
height: 100px;
}
.aniScrollContainer img.animated {
position: absolute;
display: none;
top: 0;
left: 0;
height:100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="http://www.durley.net/animate-on-scroll/js/aniscroll.js"></script>
<div id="header"></div>
<div class="aniScrollContainer myAniScrollContainer">
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-01.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-02.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-03.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-04.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-05.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-06.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-07.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-08.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-09.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-10.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-11.jpg"/>
<img src="http://www.durley.net/animate-on-scroll/images/armani-bag-1000-03-12.jpg"/>
</div>
<div id="footer"></div>
See this jsFiddle for an example for how to limit how often it can change.
function animationTimer(){
canChange = true;
}
$(window).bind('scroll', function() {
if(canChange)
{
canChange = false;
setTimeout(animationTimer, 250);
// ...
}
});
This will allow the image to change every 250 ms, so change the 250 to a number which suits you to throttle the speed of which it changes.
You can use a sleep function (setTimeout) to wait some time between actions. And to be sure that isn't executet more than 1 time, you can use semaphores to lock critical regions.
In the example below I add and remove a class (this is the semaphore). And I make use of setTimeout to wait a time to execute that code.
$(document).ready(function () {
var container = $('#container'),
nImg = 0; // active picture
imgNum = $('#container img').length;
var topDiv = ((container).offset() || { "top": NaN }).top;
$(window).bind('scroll', function() {
if(!container.hasClass('lock')) {
container.addClass('lock');
setTimeout(function() {
var y = $(this).scrollTop();
if(y>topDiv){
nImg++;
}else{
nImg--;
}
if(nImg>=imgNum){ nImg = 0; }
if(nImg<0){ nImg = imgNum-1; }
$(".animated").each(function(){
$(this).removeClass("show")
});
$(".animated").eq(nImg).addClass("show");
container.removeClass('lock');
},200);
}
});
});
.animated { display: none;}
.show { display: block;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="height:200px"></div>
<div id="container">
<img src="http://i.imgur.com/2oVbl7z.png" class="animated show" />
<img src="http://i.imgur.com/S5s0Mv1.png" class="animated" />
<img src="http://i.imgur.com/0vBEXL7.png" class="animated" />
<img src="http://i.imgur.com/ffg7v9n.png" class="animated" />
<img src="http://i.imgur.com/9FD5kdE.png" class="animated" />
</div>
Note: You can change the value of setTimeout to match your speed needs.

Categories