I am making a slider and am having a few issues.
1) On first slide the animation doesn't animate.
2) The spacing for the last box is off in the beggining but as the slider progresses it corrects.
3) Sometimes the animations have some stuttering.
I have put this in a codepen here:
http://codepen.io/mpaccione/pen/MyJNxM
Any advice is much appreciated. I am unsure why these issues are arising. I am using css transitions for the animation and javascript/jquery to change the css/dom/calcs.
CODE
<style type="text/css">
html,body {
margin: 0;
background-color: #888;
height: 100%;
width: 100%;
box-sizing: border-box;
}
#slider {
width: 100%;
height: 100%;
display: block;
position: relative;
transition-duration: 0.5s;
transition-timing-function: ease-in-out;
}
#slider ul {
padding: 0;
margin: auto;
display: block;
top: 50%;
position: relative;
transform: translateY(-50%);
white-space: nowrap;
}
#slider li {
display: inline-block;
height: 150px;
width: 150px;
margin: 10px;
}
.sliderContainer {
width: 60%;
height: 200px;
overflow: hidden;
background-color: white;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
position: relative;
}
</style>
<div class="sliderContainer">
<div id="slider">
<ul>
<li style="background-color: red">a</li>
<li style="background-color: green">b</li>
<li style="background-color: blue">c</li>
<li style="background-color: orange">d</li>
<li style="background-color: purple">e</li>
<li style="background-color: yellow">f</li>
</ul>
</div>
</div>
<script type="text/javascript">
$(document).on("ready", function(){
var slider = $("#slider"),
sliderWidth = slider.outerWidth(true),
img = slider.find("li"),
imgWidth = img.outerWidth(true),
imgCount = img.length,
imgSize = sliderWidth/imgCount,
imgHorMargin = parseFloat(img.css("margin-left")) + parseFloat(img.css("margin-right")),
imgVerMargin = parseFloat(img.css("margin-bottom")) + parseFloat(img.css("margin-top")),
imgSizeX = (imgSize-imgHorMargin),
imgSizeY = (imgSize-imgVerMargin);
slider.find("li").css({"width": imgSizeX, "height": imgSizeY});
(function slideActivate(){
setTimeout(function loop(){
slider.css("transition-duration", "0.5s");
slider.css("left",-imgSize);
setTimeout(function(){
console.log("timeout2");
firstImage = slider.find("li")[0];
firstImage.remove();
slider.css("transition-duration", "0s");
slider.css("left", "0px");
setTimeout(function(){
console.log("timeout3");
slider.find("ul").append(firstImage);
requestAnimationFrame(slideActivate);
}, 100);
}, 500);
}, 2000);
})();
});
</script>
Turns out that the margin issue was do to the browser rendering space as the elements were inline-block. Browsers add uneditable spacing.
The best solution I have found is to make the parent of the ul to have font-size:0.
The second issue was the first slide not animating which was because I did not have an initial css left value set to animate from.
Related
I'm working with an image fader program, but I'm not understanding absolute positioning. I have the images fading nicely and resizing the way I want if the screen resizes. but I have 2 problems. Div#2 gets covered up by the images. I want div2 to always appear below the image div. Also, I have control buttons on the images. I want them in the middle. I thought using top:50% would do that, but it's not. Here's an example...
var slides = document.querySelectorAll('#slides .slide');
var currentSlide = 0;
var slideInterval = setInterval(nextSlide,5000);
function nextSlide(){goToSlide(currentSlide+1);}
function previousSlide(){goToSlide(currentSlide-1);}
function goToSlide(n){
slides[currentSlide].className = 'slide';
currentSlide = (n+slides.length)%slides.length;
slides[currentSlide].className = 'slide showing';}
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function(){nextSlide();};
previous.onclick = function(){previousSlide();};
#slides {position: relative}
.slide{
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:auto;
min-height:300px;
object-fit:cover;
opacity: 0;
box-sizing:border-box;
transition: opacity 2s;}
.showing{opacity: 1;}
.controls{
background: transparent;
color: #fff;
font-size: 30px;
cursor: pointer;
border: 1px solid #555;
width: 30px;
position: absolute;
}
.controls:hover{ opacity:.5}
.fadenext{right: 10px; top: 50%;}
.fadeprev{left: 10px; top: 50%;}
<br><br>
<div id="slides">
<img src='https://www.panotools.org/dersch/Monp.JPG' class="slide showing">
<img src='https://www.panotools.org/dersch/StBp.JPG' class="slide">
<button class="controls fadeprev" id="previous"><</button>
<button class="controls fadenext" id="next">></button>
</div>
<div style='margin-top:40px;border:1px solid red;width:200px;height:100px'>
This is Div # 2</div>
I've amended your snippet to fix your issues.
Adding margin-top instead of top will fix your issue with the
controls.
Div 2 will now always remain below your slider.
P.S. I moved your div2 inline styles to keep it neat.
var slides = document.querySelectorAll('#slides .slide');
var currentSlide = 0;
var slideInterval = setInterval(nextSlide, 5000);
function nextSlide() {
goToSlide(currentSlide + 1);
}
function previousSlide() {
goToSlide(currentSlide - 1);
}
function goToSlide(n) {
slides[currentSlide].className = 'slide';
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].className = 'slide showing';
}
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function() {
nextSlide();
};
previous.onclick = function() {
previousSlide();
};
* {
margin: 0;
padding: 0;
}
#slides {
position: relative
}
.slide {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: auto;
min-height: 300px;
object-fit: cover;
opacity: 0;
box-sizing: border-box;
transition: opacity 2s;
}
.showing {
opacity: 1;
}
.controls {
background: transparent;
color: #fff;
font-size: 30px;
cursor: pointer;
border: 1px solid #555;
width: 30px;
position: absolute;
}
.controls:hover {
opacity: .5
}
.fadenext {
right: 10px;
margin-top: 25%;
}
.fadeprev {
left: 10px;
margin-top: 25%;
}
.div2 {
margin-top: 50%;
border: 1px solid red;
width: 200px;
height: 100px;
}
<br><br>
<div id="slides">
<img src='https://www.panotools.org/dersch/Monp.JPG' class="slide showing">
<img src='https://www.panotools.org/dersch/StBp.JPG' class="slide">
<button class="controls fadeprev" id="previous"><</button>
<button class="controls fadenext" id="next">></button>
</div>
<div class="div2">This is Div # 2</div>
It's not feasible to use % based positions when you use "top" style. So to achieve what you want to do, use margin-top instead. As shown below:
.fadenext{right: 10px; margin-top: 25%;}
.fadeprev{left: 10px; margin-top: 25%;}
And for your div2, just change it's style to:
margin-top: 50%
I would like to have the first image slide from left to right. The second image slides from left to right, and the third image will be coming from the bottom to top. I managed to slide the first image from left to right with the answers I found here on stackoverflow. But when I modified the script & css for the other images, they're not sliding. I am not so knowledgeable in javascript.
$(document).ready(function() {
function animateImgs() {
$('ul.slide1 li:not(.visible)').first().animate({
'margin-right': '500px'
}, 2000, function() {
$(this).addClass('visible');
animateImgs();
});
}
animateImgs();
});
.content {
position: relative;
margin: 0 auto;
top: 0;
left: 0;
width: 500px;
height: 500px;
border: 1px solid #000;
overflow: hidden;
}
img {
width: 100%;
height: 100%;
border-radius: 50%;
position: absolute;
}
.img1 {
max-width: 300px;
max-height: 300px;
z-index: 2;
}
.img2 {
max-width: 260px;
max-height: 260px;
z-index: 3;
left: 200px;
top: 100px;
}
.img3 {
max-width: 200px;
max-height: 200px;
z-index: 4;
left: 65px;
top: 235px;
}
/* -------------------------------------------------------------------- */
ul {
padding: 0;
margin: 0;
overflow: hidden;
}
ul.slide1 li {
float: right;
margin: 0 10px 0 0;
margin-right: 9999px;
list-style-type: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="content">
<ul class="slide1">
<li>
<img src="http://www.pngmart.com/files/4/Chrysanthemum-Transparent-Background.png" class="img1 slideLeft" />
</li>
</ul>
<img src="http://www.estanciavitoria.com/en/images/sobre_planta.png" class="img2 slideRight" />
<ul class="slide3">
<li>
<img src="https://s-media-cache-ak0.pinimg.com/originals/4d/09/e4/4d09e455070957363b2c0660a0d8cfef.png" class="img3 slideUp" />
</li>
</ul>
</div>
Steps:
Define a container element with class slideContent
Within container define slide elements with class slide
Specify sliding direction to slide elements with either slideUp, slideDown, slideLeft or slideRight
Specify data-margin to place element in container by sliding
Do not define following in CSS (instead use data-margin attribute in slide element):
margin-bottom for slideUp element
margin-top for slideDown element
margin-right for slideLeft element
margin-left for slideRight element
$(document).ready(function() {
function animateImgs() {
// Animation duration
var duration = 200;
// Get element reference needs to be shown
var el = $('.slideContent .slide:not(.visible)').first();
if (el.length === 0) {
console.log('No more elements found');
return;
}
// Read the margin value
var marginValue = el.attr('data-margin');
// Direction
var marginDirection,
animationProp = {};
// Animate now
if (el.hasClass('slideLeft')) {
marginDirection = 'margin-right';
} else if (el.hasClass('slideRight')) {
marginDirection = 'margin-left';
} else if (el.hasClass('slideUp')) {
marginDirection = 'margin-bottom'
} else if (el.hasClass('slideDown')) {
marginDirection = 'margin-top'
}
if (typeof marginDirection === 'undefined') {
// No valid animation direction defined
console.log('Invalid animation direction');
return;
}
animationProp[marginDirection] = marginValue;
el.animate(animationProp, duration, function() {
$(this).addClass('visible');
animateImgs();
});
}
animateImgs();
});
.slideContent {
position: relative;
margin: 0 auto;
top: 0;
left: 0;
width: 500px;
height: 500px;
border: 1px solid #000;
overflow: hidden;
}
.slideContent .slide {
position: absolute;
}
.slideContent .slideLeft {
right: -100%
}
.slideContent .slideRight {
left: -100%
}
.slideContent .slideUp {
bottom: -100%
}
img {
width: 100%;
height: 100%;
border-radius: 50%;
}
.img1 {
max-width: 300px;
max-height: 300px;
}
.img2 {
max-width: 260px;
max-height: 260px;
top: 100px;
}
.img3 {
max-width: 200px;
max-height: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="slideContent">
<img src="http://www.pngmart.com/files/4/Chrysanthemum-Transparent-Background.png" data-margin="500px" class="img1 slide slideLeft" />
<img src="http://www.estanciavitoria.com/en/images/sobre_planta.png" data-margin="600px" class="img2 slide slideRight" />
<img src="https://s-media-cache-ak0.pinimg.com/originals/4d/09/e4/4d09e455070957363b2c0660a0d8cfef.png" data-margin="600px" class="img3 slide slideUp" />
</div>
Against all reason, I'm trying to create a vanilla JavaScript carousel.
I am having two problems:
1. The images move left at widths of -680px as they should but when I tried to create the same function for the right button, the left value goes to 1370px making the picture off the screen.
2. I would like for it to slide left rather jump left (same for right), I managed to get it to do this but it doesn't work on the first slide, only from the second slide.
Here is the HTML code just for the carousel:
<div id = "container">
<div id = "carousel">
<div class = "slide"><img class = "slideImage" class = "active" src = "sithCover.png"></div>
<div class = "slide"><img class = "slideImage" src = "darthVader.png"></div>
<div class = "slide"><img class = "slideImage" src = "darthSidious.png"></div>
<div class = "slide"><img class = "slideImage" src = "kyloRen.png"></div>
</div>
</div>
<div id = "left" class = "button"></div>
<div id = "right" class = "button"></div>
Here is the CSS code:
#container {
position: absolute;
top: 200px;
left: 100px;
width: 680px;
height: 360px;
white-space: nowrap;
overflow:hidden;
}
#carousel {
position: absolute;
width: 2740px;
height: 360px;
white-space: nowrap;
overflow: hidden;
transition: left 300ms linear;
}
.slide {
display: inline-block;
height: 360px;
width: 680px;
padding: 0;
margin: 0;
transition: left 300ms linear;
}
.slideImage {
position:relative;
height: 360px;
width: 680px;
float: left;
}
.button {
position: absolute;
top: 340px;
height: 60px;
width: 60px;
border-bottom: 12px solid red;
}
#left {
left: 115px;
border-left: 12px solid red;
transform: rotate(45deg);
}
#right {
left: 693px;
border-right: 12px solid red;
transform: rotate(-45deg);
}
Here is the JavaScript:
var carousel = document.querySelector('#carousel');
var firstVal = 0;
document.querySelector('#left').addEventListener("click", moveLeft);
function moveLeft (){
firstVal +=685;
carousel.style.left = "-"+firstVal+"px";
};
document.querySelector('#right').addEventListener("click", moveRight);
function moveRight() {
firstVal +=685;
carousel.style.left = "+"+firstVal+"px";
};
Here is a JSFiddle so that you can see what I mean:
"https://jsfiddle.net/way81/8to1kkyj/"
I appreciate your time in reading my question and any help would be much appreciated.
Ofcourse it goes from -685px on left click and then to +1370pxthe next right click; You are always adding 685 to your firstVal variable.
firstVal = 0
//firstVal is worth 0
moveLeft()
//firstVal is now worth 685
moveRight()
//firstVal is now worth 1370.
The problem is that when you apply the firstVal to your CSS thing in the javascript, you create a string to get your negative value (where you apply the "-" sign infront of firstVal)
Instead, write them like this
function moveLeft (){
firstVal -=685; //note we now subtract, the "-" should appear when the number becomes negative
carousel.style.left = firstVal + "px";
};
function moveRight() {
firstVal +=685;
carousel.style.left = firstVal + "px";
};
var left = document.getElementById("left");
left.addEventListener("click", moveLeft, false);
var right = document.getElementById("right");
right.addEventListener("click", moveRight, false);
var carousel = document.getElementById("carousel");
var images = document.getElementsByTagName("img");
var position = 0;
var interval = 685;
var minPos = ("-" + interval) * images.length;
var maxPos = interval * images.length;
//slide image to the left side <--
function moveRight() {
if (position > (minPos + interval)) {
position -= interval;
carousel.style.left = position + "px";
}
if (position === (minPos + interval)) {
right.style.display = "none";
}
left.style.display = "block";
}
//slide image to the right side -->
function moveLeft() {
if (position < (maxPos - interval) && position < 0) {
position += interval;
carousel.style.left = position + "px";
}
if (position === 0) {
left.style.display = "none";
}
right.style.display = "block";
}
#container {
position: absolute;
top: 200px;
left: 100px;
width: 680px;
height: 360px;
white-space: nowrap;
overflow: hidden;
}
#carousel {
position: absolute;
width: 2740px;
height: 360px;
white-space: nowrap;
overflow: hidden;
transition: left 300ms linear;
}
.slide {
display: inline-block;
height: 360px;
width: 680px;
padding: 0;
margin: 0;
transition: left 300ms linear;
}
.slideImage {
position: relative;
height: 360px;
width: 680px;
float: left;
}
.button {
position: absolute;
top: 340px;
height: 60px;
width: 60px;
border-bottom: 12px solid red;
}
#left {
left: 115px;
border-left: 12px solid red;
transform: rotate(45deg);
display: none;
}
#right {
left: 693px;
border-right: 12px solid red;
transform: rotate(-45deg);
}
<div id="container">
<div id="carousel">
<div class="slide">
<img class="slideImage" class="active" src="sithCover.png" alt="slide1">
</div>
<div class="slide">
<img class="slideImage" src="darthVader.png" alt="slide2">
</div>
<div class="slide">
<img class="slideImage" src="darthSidious.png" alt="slide3">
</div>
<div class="slide">
<img class="slideImage" src="kyloRen.png" alt="slide4">
</div>
</div>
</div>
<div id="left" class="button"></div>
<div id="right" class="button"></div>
I am extremely new to JQuery, I just started looking into it today. I have searched all around for what might be causing this bit of code to not work. When you scroll down, I want the h1 to move to the side and a menu button to appear. That works, but when I scroll back up again, it takes an extremely long time to reverse itself. I have tried to fine anything that might be causing it like a delay or something, but as far as I can see, there isn't any problems.
Link to website: http://www.dragonmath.net/rockets
Here is my code:
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="styles/main.css" />
<title>Rockets</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<header>
<img id="menu" src="images/menu1.png" />
<div id="headerdiv">
<h1>Rockets</h1>
<img id="logo" src="images/logo1.png" />
</div>
</header>
<nav>
<ul>
<li>
<a>Space Race</a>
</li>
<li>
<a>SpaceX</a>
</li>
</ul>
</nav>
<script>
$( document ).ready(function() {
var $menu = $('img#menu');
var $headerdiv = $("div#headerdiv")
var $nav = $('nav');
$(window).on('scroll', function () {
if ($(window).scrollTop() > 40) {
$headerdiv.addClass("testheaderdiv");
$menu.delay(800).slideDown(800);
$nav.addClass('testnav');
}
if ($(window).scrollTop() < 40) {
$menu.slideUp(800, function () {
$headerdiv.removeClass('testheaderdiv');
});
$nav.removeClass('testnav');
}
});
});
</script>
</body>
</html>
CSS
* {
margin: 0px;
padding: 0px;
color: #00AAFF;
font-family: Arial;
}
body {
height: 800px;
}
header {
position: fixed;
top: 0px;
left: 0px;
height: 100px;
width: 100%;
background-color: #333;
z-index: 1;
}
div#headerdiv {
display: inline;
transition: all 1s;
}
h1 {
display: inline;
margin-left: 40px;
font-size: 40px;
}
header > img#menu {
position: fixed;
top: 20px;
left: 40px;
width: 40px;
height: 40px;
display: none;
}
header > div > img#logo {
display: inline;
width: 60px;
height: 60px;
position: relative;
top: 18px;
left: 20px;
transition: height 1s, width 1s;
}
nav {
position: relative;
top: 100px;
height: 40px;
width: 100%;
background-color: #333;
}
nav > ul {
list-style: none;
}
nav > ul > li {
display: inline-block;
height: 40px;
width: 200px;
text-align: center;
border-right: 1px solid #00AAFF;
}
nav > ul > li > a {
position: relative;
top: 6px;
}
.testheaderdiv {
margin-left: 80px;
transition: all 1s;
}
.testnav {
display: none;
}
The main problem I could see with the code is how scroll is handled, for every scroll event you are adding delay to the menu element.
So try
$(document).ready(function () {
var $menu = $('img#menu');
var $headerdiv = $("div#headerdiv")
var $nav = $('nav');
var flag;
$(window).on('scroll', function () {
if (flag !== 1 && $(window).scrollTop() > 40) {
$headerdiv.addClass("testheaderdiv");
$menu.stop(true, true).delay(800).slideDown(800);
$nav.addClass('testnav');
flag = 1;
}
if (flag !== 2 && $(window).scrollTop() < 40) {
$menu.stop(true, true).slideUp(800, function () {
$headerdiv.removeClass('testheaderdiv');
});
$nav.removeClass('testnav');
flag = 2;
}
});
});
I have this code:
#main {
max-width: 500px;
height: 900px;
margin: auto;
background: green
}
.menu1 {
height: 30px;
background: red
}
.menu2 {
display: none;
}
<div id="main">
<div class="menu1">COntent 1</div>
<div class="menu2">Content 2</div>
</div>
How to: When I'm scroll down div .menu2 display sticky in top as css
.menu2 {
height: 30px; background: blue; position: fixed
}
My code: http://jsfiddle.net/rh1aLnxs/
Thanks
this can be accomplished with css's position:fixed, as long as you don't need additional behavior regarding the parent div (position:fixed is ignorant to the parent in css)
here's an example:
.menu1 {position:fixed; height: 30px; background: red; max-width: 500px; width:100%}
http://jsfiddle.net/rh1aLnxs/
If you need for example, for menu1 to go away when the user scrolls below main, then you need to use jquery's scroll event and handle the positioning manually (http://api.jquery.com/scroll/)
try this:
var headerTop = $('.menu1').offset().top;
// var headerBottom = headerTop + 120; // Sub-menu should appear after this distance from top.
$(window).scroll(function () {
var scrollTop = $(window).scrollTop(); // Current vertical scroll position from the top
if (scrollTop > headerTop) { // Check to see if we have scrolled more than headerBottom
if (($(".menu2").is(":visible") === false)) {
$('.menu1').hide();
$('.menu2').fadeIn('slow');
}
} else {
if ($(".menu2").is(":visible")) {
$('.menu2').hide();
$('.menu1').fadeIn('slow');
}
}
});
#main {
max-width: 500px;
height: 900px;
margin: auto;
background: green
}
.menu1 {
height: 30px;
background-color: red
}
.menu2 {
background-color: blue;
max-width: 500px;
width: 100%;
top: 0;
display: none;
/*display: none*/
position: fixed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="main">
<div class="menu1">Content1</div>
<div class="menu2">Content2</div>
</div>
Here are some improvements on your fiddle along with a simplified version of the script to add/remove a fixed class on scroll.
http://jsfiddle.net/rh1aLnxs/2/
jQuery(window).bind("scroll", function() {
if (jQuery(this).scrollTop() > 100) {
jQuery(".menu1").removeClass("no-fixed").addClass("fixed");
} else {
jQuery(".menu1").removeClass("fixed").addClass("no-fixed");
}
});
#main {max-width: 500px; height: 900px; margin: auto; background: green}
.menu1 {height: 30px; background: red}
.menu2 {display: none}
#main {
width:100%;
position:relative;
}
.no-fixed {
position: relative;
}
.fixed {
position: fixed;
width:100%;
max-width: 500px;
}
<div id="main">
<div class="menu1"></div>
<div class="menu2"></div>
</div>