I have trying for some time. And I gave a look at the image slider questions already. But I would really appreciate if I get some specific help here. Please tell me where the following code went wrong.
Here's my jQuery code:
function slideMe {
$('.imgcontainer').animate({"margin-left":"-= 100%"}, 2000, function () {
if($('.imgcontainer').css("margin-left") == (-300%)) {
$('.imgcontainer').css("margin-left", "0px");
}
slideMe();
});
}
window.onload = slideMe();
And here's the script on HTML page:
<div class="fitimage">
<div class="imgcontainer">
<img src="img/copywrtng.jpg" class="headerimage" alt="copywriting" />
<img src="img/copywrtng1.jpg" class="headerimage" alt="copywriting" />
<img src="img/copywrtng2.jpg" class="headerimage" alt="copywriting" />
</div>
</div>
And here's what I have on CSS:
div.fitimage {
width:100%;
height:93vh;
overflow: hidden;
}
img.headerimage {
padding: 0;
margin:0 auto;
width:100%;
/*max-height:100%;
max-width:100%;*/
height:93vh;
}
My logic is that as each image takes up 100% width, as the ".imgcontainer" div slides left with margin-left: -100%, each image should come up one by one from the right, until it reaches the last one when it reverts to the first image again.
It's not working!
Please help.
Your "main" issue is in this line:
$('.imgcontainer').css("margin-left") == (-300 % )
// ^^^^^^^^
beside you can only use string format "-300%", .css("margin-left") will give you a px value which you cannot compare with a non-computed %.
Another issue is that the slides set at 100% - will be the width of their container, which might be actually greater (300% for 3 slides).
Solution:
Instead I'd suggest you to use a c counter that goes like 0,1,2, 0,1... etc.
Than calculate the overflow-wrapper width and animate scrollLeft: width * counter (instead of -marginLeft).
Use display:flex on the parent and min-width:100%; on the child DIV elements (than place your images inside those DIVs instead!)
$(".imgcontainer").each(function(){ // Now you can have multiple independent sliders!
var $gal = $(this),
$slides = $gal.children(), // get the slides
tot = $slides.length, // number of slides
c = 0; // the counter we mentioned
(function anim() { // internal animation callback function
var w = $gal.width();
c = ++c % tot; // increment or loop-back counter to 0
$gal.delay(2000).animate({scrollLeft: w*c }, 1000, anim); // anim callback !
}()); // << START!
});
/*QuickReset*/ *{margin:0;box-sizing:border-box;font:14px/1.4 sans-serif;} html,body{height:100%;}
.imgcontainer{
position:relative;
height: 93%; /* or whatever you see fit */
display: flex;
overflow: hidden;
}
.imgcontainer > div {
min-width: 100%;
background: none 50% 50% / cover;
/* Set background-image inline (see HTML) */
/* Or use inner images like you did */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="imgcontainer">
<div style="background-image:url(http://placehold.it/500x340/0bf);">
Slide 1
</div>
<div style="background-image:url(http://placehold.it/500x340/f0b);">
Slide 2
</div>
<div style="background-image:url(http://placehold.it/500x340/b0f);">
Slide 3
</div>
</div>
Related
I have a fixed div containing an image that scrolls with the user from the top of the page. As new content divs enter the viewport I want the image to change.
I found a related piece of code that will change the image based on how far a user scrolls in pixels. This works, but only if the viewport is a specific size, else the image changes too early/late:
Example
I'm trying to modify this so that the change is instead based on when another div comes into view so that it works no matter the screen size (content div heights are set with relative units). I think this can be done if the other divs positions are saved to a variable and then used in place of the pixel values in the above code. However I can't seem to get this right, probably because I've not calculated the other div positions correctly.
$("#display1").fadeIn(1000);
$(window).scroll(function() {
var pos = $(window).scrollTop();
var first = $("#first").offset();
var second = $("#second").offset();
if (pos < first) {
hideAll("display1");
$("#display1").fadeIn(1000);
}
if (pos > first && pos < second) {
hideAll("display2");
$("#display2").fadeIn(1000);
}
etc...
});
function hideAll(exceptMe) {
$(".displayImg").each(function(i) {
if ($(this).attr("id") == exceptMe) return;
$(this).fadeOut();
});
}
You should try
getBoundingClientRect()
JS method, since It gets the position of the elements relative to the viewport. Check this answer: https://stackoverflow.com/a/7557433/4312515
Here is a quick proof of concept of changing a background image based on an element getting into view.
There are three divs. When the third div reaches the bottom of the viewport it will change the color of the background. When the third divs scroll out of the view again the background color is reset to its initial color.
Normally you should debounce the scroll event to prevent slowing down the UI. For this example I didn't debounce the event so you get a better sense of when the background is changed.
const
card3 = document.getElementById('card3'),
background = document.getElementById('background');
let
isCardVisible = false;
function checkDivPosition() {
const
cardTopPosition = card3.getBoundingClientRect().top,
viewportHeight = document.documentElement.clientHeight,
isInView = cardTopPosition - viewportHeight < 0;
if (isInView && !isCardVisible) {
background.style.backgroundColor = 'rebeccapurple';
isCardVisible = true;
} else if (!isInView && isCardVisible) {
background.style.backgroundColor = 'orange';
isCardVisible = false;
}
}
function onWindowScroll(event) {
checkDivPosition();
}
window.addEventListener('scroll', onWindowScroll);
body {
margin: 0;
}
.background {
height: 100vh;
opacity: .2;
position: fixed;
transition: background-color .3s ease-out;
width: 100vw;
}
.card {
border: 1px solid;
height: 100vh;
width: 100vw;
}
.card + .card {
margin-top: 5vh;
}
<div id="background" class="background" style="background-color:orange"></div>
<div class="card">
Card 1
</div>
<div class="card">
Card 2
</div>
<div id="card3" class="card">
Card 3.
</div>
I have one wrapper div (the grey background) and 5 squares inside it. After the press of a button, the blue one moves and has to stop at the end of the wrapper div, but it goes behind it. How do I make it go to the end of the div, and not behind it?
There is what I've tried so far:
<button id = "start">
Start
</button>
<div style="background-color:rgb(201, 201, 201);width:80%;height:250px" id="horsewrapper">
<div style="height: 50px; width: 100px; text-align: center; background-color: blue;" id="horse1">1</div>
<div style="background-color:red;text-align:center;height:50px;width:100px" id="horse2">1</div>
<div style="background-color:green;text-align:center;height:50px;width:100px" id="horse3">1</div>
<div style="background-color:yellow;text-align:center;height:50px;width:100px" id="horse4">1</div>
<div style="background-color:orange;text-align:center;height:50px;width:100px" id="horse5">1</div>
</div>
Demo can be found here:
https://jsfiddle.net/wqrun6ny/2/
Thanks
https://jsfiddle.net/wqrun6ny/3/
Margin 100% adds margin to widh of element. To avoid this you should add to your animate function left property which is equal to width of element:
$('#horse1').animate({"margin-left":"100%", 'left': -100} ....
but it will works only if element has position:relative
You can make a calculation before start the animation. It takes the width of the wrapper and substract it the width of the "horse":
https://jsfiddle.net/wqrun6ny/4/
$('#start').click(function(){
var margin = $('#horsewrapper').width() - $('#horse1').width();
$('#horse1').animate({"margin-left": margin},{"duration":1000,"easing":"linear"});
});
Edit
According with the request in comments, you can use stop()method and then reinitialise the animation, it works perfectly:
https://jsfiddle.net/wqrun6ny/15/
$('#start').click(function(){
animate($('#horse1'));
});
$(window).on('resize', function() {
$('#horse1').stop();
animate($('#horse1'));
});
var animate = function(element) {
var margin = $('#horsewrapper').width() - element.width();
element.animate({"margin-left": margin},{"duration":5000,"easing":"linear"});
};
You will notice a problem, if you don't push the button but you resize the window, it will start the animation. To avoid this you can add a flag or check if the div is in the initial position.
You have to calculate margin first, then animate according to margin.
Try like this:
$('#start').click(function(){
var mar = $('#horsewrapper').width() - $('#horse1').width();
$('#horse1').animate({"margin-left": mar}, {"duration":1000,"easing":"linear"});
});
https://jsfiddle.net/wqrun6ny/14/
You could calculate the width of the container, and subtract the width of the boxes your moving. Pushing it 100% will result in what your demo is displaying.
If its a static box width the same width, you can just use a static pixel value as well.
var horsewrapperWidth = $('#horsewrapper').width() -100;
100 is the width of your "horses".
$('#horse1').animate({"margin-left": horsewrapperWidth + 'px'},{"duration":5000,"easing":"linear"});
Simplest way !
$('#start').click(function() {
// added this variable to get width of box
var box = $('#horsewrapper').width();
$('#horse1').finish().css("margin-left", "initial");
$('#horse1').animate({
"margin-left": box - 100 // box - width of horse (100%-100px)
}, {
"duration": 5000,
"easing": "linear"
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button id="start">
Start
</button>
<div style="background-color:rgb(201, 201, 201);width:80%;height:250px" id="horsewrapper">
<div style="height: 50px; width: 100px; text-align: center; background-color: blue;" id="horse1">1</div>
<div style="background-color:red;text-align:center;height:50px;width:100px" id="horse2">1</div>
<div style="background-color:green;text-align:center;height:50px;width:100px" id="horse3">1</div>
<div style="background-color:yellow;text-align:center;height:50px;width:100px" id="horse4">1</div>
<div style="background-color:orange;text-align:center;height:50px;width:100px" id="horse5">1</div>
</div>
Using the flexbox justify-content property, elements can be distributed evenly in their container. However, I want to animate their positions when a new element is inserted or an existing one is removed.
I only managed to animate the height of the elements so far. However, there is a jump at the end of the animation since the gaps around the removed element that got animated to height: 0 vanish. Analogously, when inserting an element there is a jump at the beginning of the animation.
Is it possible to make an animation from end to end with justify-content? Here is an example to play with. Using CSS transition is preferred.
The main problem is that the behavior you are getting is the expected one.
In the very same instant that card.remove() is executed the flexbox justify-content property need to adjust the gaps around the removed element (as you said). And, as Paulie D has pointed out, there is nothing to animate about.
The only solution I can think about is to skip the flex thing and use javascript to create the necessary gaps among the card elements.
Here I leave the snippet:
var animation_time = 500;
var column_height = $('.column').height();
var cards_height = $('.card').height();
var cards_number;
var cards_total_height;
var space_to_be_distributed;
var placeholder_height;
function updateSizes(cards_number)
{
cards_total_height = cards_number * cards_height;
space_to_be_distributed = column_height - cards_total_height;
placeholder_height = space_to_be_distributed / (cards_number + 1);
}
updateSizes($('.card').length);
$('.placeholder').height(placeholder_height);
$(document).on('click', '.card', function () {
var card = $(this);
card.animate({height: 0, opacity: 0}, animation_time, function () {
card.remove();
});
updateSizes($('.card').length - 1);
var placeholder = card.next();
$('.placeholder').not(placeholder).animate({height: placeholder_height}, animation_time);
placeholder.animate({height: 0}, animation_time, function () {
placeholder.remove();
updateSizes($('.card').length);
$('.placeholder').animate({height: placeholder_height}, animation_time);
});
});
$('a').click(function () {
var card = $('<div class="card">');
card.css({opacity: 0, height: 0})
.appendTo('.column')
.animate({height: 25, opacity: 1}, animation_time);
var placeholder = $('<div class="placeholder">');
placeholder.css({height: 0})
.appendTo('.column');
updateSizes($('.card').length);
$('.placeholder').animate({height: placeholder_height}, animation_time);
});
body, html, .column {
height: 100%;
margin: 0;
}
.column {
float: left;
width: 100px;
background: navy;
overflow: hidden;
}
.card {
height: 25px;
width: 100px;
background: grey;
}
.placeholder {
height: 25px;
width: 100px;
}
<html>
<head>
<script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
</head>
<body>
<div class="column">
<div class="placeholder"></div>
<div class="card"></div>
<div class="placeholder"></div>
<div class="card"></div>
<div class="placeholder"></div>
<div class="card"></div>
<div class="placeholder"></div>
</div>
Add card
</body>
</html>
Hope it helps!
EDIT - I made the following changes in the code:
I change the fiddle for a SO snippet.
I forced an update of elements size at the end of the animation (in case you click to remove an element before the last one has been completely removed)
I change the size of the elementes to adapt it to the (small) SO snippet window.
Here is the effect I want to achieve:
This is i.e. one image, and the other images should slide diagonally in the way that arrow goes. The effect should not be fade effect. The slide effect has to be achieved.
Here is the html:
<div id="slider_page">
<div style="display: block;">
<img src="img1.jpg">
<img src="img2.jpg">
</div>
</div>
Please for help guys.
Sorry for the mess in the html code.
Thanks in advance
Here is a rough sketch on how to do it on your own, without a library. The code might need some adaption for your particular circumstances. For instance, if you want to slide not only images but elements containing text as well, change from using <img> to <div>. You'll find explanation in the comments.
HTML
<div id="carousel">
<img class="carousel-img" src="img1.jpg" />
<img class="carousel-img" src="img2.jpg" />
<img class="carousel-img" src="img3.jpg" />
</div>
CSS
#carousel {
position: relative; /* So images are positioned relative to it. */
width: 400px;
height: 300px;
overflow: hidden; /* So we clip the other images. */
}
.carousel-img {
width: 100%;
position: absolute; /* Position relative to parent div. */
left: 400px; /* Hide just beyond bottom right corner. */
top: 300px;
}
.carousel-img:first-child {
/* Do not hide the first image. */
left: 0px;
top: 0px;
}
JavaScript
//Some settings.
var animation_time = 500; //Millisecs the animation takes.
var waiting_time = 2000; //Millisecs between animations.
//Some variables.
var images; //A list of the images.
var i = 0; //Index of the current image.
var w; //Width of carousel.
var h; //Height of carousel.
$(function() {
//Runs when the DOM is ready.
//Set the variables.
images = $("#carousel .carousel-img");
w = $("#carousel").css("width");
h = $("#carousel").css("height");
//Start the carousel.
setTimeout(slideToNext, waiting_time)
});
function slideToNext() {
//Get the index of the next image.
var next = (i + 1) % images.length;
//Make sure the new image is on top.
images.css("z-index", 0);
images.eq(next).css("z-index", 1);
//Animate the next image.
images.eq(next).animate({left: "0px", top: "0px"}, animation_time, function() {
//Runs when the animation is compleated.
//Move the old image out.
images.eq(i).css({left: w, top: h});
//Now this is the current image.
i = next;
//Do it again.
setTimeout(slideToNext, waiting_time);
});
}
Here is a working JSFiddle, including some beautiful artwork by Caspar David Friedrich.
It might also be possible to configure an existing carousel library (like Slick or Jssor) to do this.
I'm trying to implement a content slider with Closure, using the goog.fx.dom.Slide function. The idea is to be able to drag a slide bar on the bottom of a container div, and have the container div slide accordingly as the slider is moved by the user. I get no errors on the console with my current setup, but the container div doesn't slide anywhere.
HTML:
<div id="sliderContainer">
<div id="slider">
<div id="s-h">
<div class="sliderBox"></div>
...
<div class="sliderBox"></div>
</div>
</div>
JS (fired from a click on the slider, which works). A and B are the destination values (for example, 100 and 0, since I only need horizontal scrolling):
function slide(a, b) {
// a and b are coordinates provided b
var el = document.getElementById('s-h');
var duration = 1000;
var x = el.offsetLeft;
var y = 0;
var anim = new goog.fx.dom.Slide(el, [x, y], [a, b], duration,goog.fx.easing.easeOut);
anim.play();}
Any advice, or anything obviously wrong?
require('goog.ui.Slider');
// then later
var slider = new goog.ui.Slider();
slider.render();
// but you also have to add css
.goog-slider-thumb {
top: 0;
width: 20px;
height: 100%;
position: absolute;
/* background image */
}
.goog-slider-horizontal {
width: 200px;
height: 20px;
/* color, etc... */
}