obligatory dummy slider - using jQuery dynamically - javascript

I created a slider with 2 buttons, previous and next, allowing the user to interact with images by going forward or back. If at the first image and previous is fired, the last image is slid left into view. Opposite goes for the end of images case.
The problem I'm having is getting the width of the static images dynamically. When I use the browser console with the exact same selector and methods, I get the correct width, but when i console.log(width), the value is 0, which throws off the animation to slide 0px, hence no interaction.
Here is my JS:
$(document).ready(function () {
//initialize/cache variables needed in program
var sliderUL = $('div.content5').css('overflow', 'hidden').children('ul'); //we can chain variables, for example: we are setting the overflow of an element to hidden, and then we are getting the selected elements of 'ul'.
var imgs = sliderUL.find('img');
var imgWidth = imgs.eq(0).width(); //*SHOULD BE 400, but is 0*
var imgsLen = imgs.length; //5
var current = 1;
var totalImgsWidth = imgsLen * imgWidth; //2000
$('#slider-nav').show().find('button').on('click', function () {
//direction tells us what button is clicked, previous or next. This is needed for moving forward or backwards
var direction = $(this).data('dir'),
loc = imgWidth; //400, the amount needed to shift to new image, which also is the width of an image
//update current value
//if the user clicks on the next button, increase current by 1. else, decrease current by 1, meaning they clicked on the previous button.
(direction === 'next') ? ++current : --current;
//if on the first image and the user presses previous, set current equal to the last image
if (current === 0) {
current = imgsLen;
loc = totalImgsWidth - imgWidth;
//direction next means that it will animate left all the way over to the last image
direction = 'next';
} else if (current - 1 === imgsLen) {
//if the user is on the very last image and they press next, send them back to the first image
current = 1;
//send the img location back to 0 pixels, or the first image
loc = 0;
}
transition(sliderUL, loc, direction);
});
//params: 1.what we are animating 2.the location (margin) we're moving to 3.the direction we are moving
function transition(container, loc, direction) {
var unit; // -= OR +=
//as long as the user isn't trying to reset, the unit is either going to be equal to -= or +=
console.log(loc + ' and ' + direction);
if (direction && loc !== 0) {
//does direction equal next?
//if so, increment left sign, else, increment right sign
if (direction == 'next') {
unit = '-=';
} else {
unit = '+=';
}
// unit = (direction === 'next') ? '-=' : '+=';
}
console.log("you are on image: " + current + ", going " + unit);
container.animate({
//if unit isn't undefined, animate container. else, reset to 0/first img
'margin-left': unit ? (direction + loc) : loc // if true, -=400 OR +=400 if false, reset back to first image at 0
});
}
});
Here is my HTML:
<div class="content5">
<h1 class="content5_h1">Content #5 - The Obligatory Slider</h1>
<ul class="content5_imgs">
<li><img src="imgs/img1.jpg" alt="/" /></li>
<li><img src="imgs/img2.jpg" alt="/" /></li>
<li><img src="imgs/img3.jpg" alt="/" /></li>
<li><img src="imgs/img4.jpg" alt="/" /></li>
<li><img src="imgs/img5.jpg" alt="/" /></li>
</ul>
</div>
<div id="slider-nav">
<button data-dir="prev">Previous</button>
<button data-dir="next">Next</button>
</div>
and finally, here is my CSS:
.content5 {
width:400px;
margin:auto;
height: 368px;
overflow: scroll;
}
.content5_imgs {
width:10000px;
height: 250px;
list-style: none;
padding: 0px;
}
.content5_imgs li {
float:left;
}
#slider-nav {
display: none;
margin-top: 1em;
width:170px;
margin:auto;
padding-top: 10px;
}
#slider-nav button {
padding:1em;
margin-right: 1em;
border-radius:10px;
cursor: pointer;
background-color: Lime;
}
I tried chaining the variables, and I tried even changing the selectors for imgWidth including first() and [0].
Any insight is helpful.

JavaScript will return a width of 0 if the image hasn't loaded yet.
To work around this, any code that depends on content to be loaded, rather than just the DOM being ready, needs to be called on
$(window).load()
Instead of $(document).ready().
More information: Official way to ask jQuery wait for all images to load before executing something

Related

How can I disable(not hide) the scrolling vertical bar on scrolling with paralax effect

I want to try the same effect of this site but am getting lost in action on how to implement this animation.
When the user starts scrolling, the images in the header zoom in, the scrolling tab(vertical) does not move, up to a point which another image shows up, and only afterward the scroll bar starts working.
How can I achieve this animation when scrolling?
At the moment, what I thought was: to get the pixel value of the DOM when am scrolling, as well as the height of the div I want to target.
While the value of the DOM is less than the height of the box, the scale value should change based on the scrolling value.
The JS looks like this:
<script>
$(window).scroll(function() {
var initial_scroll = $('html').scrollTop();
var firstbox_height = $('#firstbox').height();
// console.log(firstbox_height);
while(initial_scroll < firstbox_height){
var sum = firstbox_height + ((firstbox_height * 0.01) / 100);
$('img').css({
// "transform": "scale(" + sum + ")"
});
}
});
</script>
I seem to be going into an infinite loop.
My pen is here
Here's a working sample. It's not flawless, it bugs when you scroll just a little back and forth at the top, the text size might change in the wrong direction. Also it doesn't work when scrolling with arrow keys. But what it does is that it should give you the idea on how to proceed.
There's probably a cleaner, nicer and more concise way to do this, but this is one way.
To get a perfectly working one, I think you might have to place a transparent <div> over the one that changes, just to keep track of the position and hence the direction.
Fiddle here: https://jsfiddle.net/codesam/nedj3ubx/53/
HTML:
<body>
<div id="box">
Text
</div>
<p id="direction">
</p>
</body>
CSS:
body {
height: 200vh;
}
#box {
width: 100%;
height: 50vh;
background-color: black;
color: white;
font-size: 72px;
}
jQuery:
$(document).ready(function(){
var initialScroll = -1;
var size;
$(window).on('scroll touchmove mousewheel', function(e){
var currentScroll = $(window).scrollTop();
if (currentScroll > initialScroll) {
$("#direction").text("down");
size = parseInt($("#box").css("font-size"));
if (size > 10) {
$("#box").css("font-size", "-=2");
e.preventDefault();
e.stopPropagation();
return false;
}
}
else if (currentScroll < initialScroll) {
$("#direction").text("up");
}
else if (currentScroll == 0 && initialScroll == 0) {
size = parseInt($("#box").css("font-size"));
if (size < 72) {
$("#box").css("font-size", "+=2");
e.preventDefault();
e.stopPropagation();
return false;
}
}
initialScroll = currentScroll;
});
});

Height not increasing using setInterval (creating border around screen)

I'm trying to create a border that slowly wraps around the screen. As part of this process, I'm playing around with only increasing the height of the border right now by using the setInterval method. However, I can't get the border height to increase slowly. Below is what I'm doing:
var i = 1;
setBorder = setInterval(borderAnimation(), 200);
function borderAnimation() {
var border = document.getElementById("border-animation");
border.style.height = i + "vh";
i = i + 1;
document.write(i);
if(i = 100){
clearInterval(setBorder);
}
}
document.write(2);
If I change the variable i inside the function to say 5, then the height changes to that number so I know the function is being called at least once.
Similarly, document.write(i) prints only once. So if i is 1, then in the screen I see only 1; it also does not print 2 at any time even though I have document.write(2). Why is this?
After this, I intend to make it so that another div is called that goes around the top (this one is left), then another on the right then another around bottom, thus completing a border that goes around the screen. If someone has a better idea or way of achieving this, please let me know as well.
There are a couple mistakes:
1: pass the function reference (don't call the function) to setInterval
2: if(i = 100) should be if(i == 100)
var i = 1;
setBorder = setInterval(borderAnimation, 200);
function borderAnimation() {
var border = document.getElementById("border-animation");
border.style.height = i + "vh";
i = i + 1;
console.log(i);
if(i == 20){
clearInterval(setBorder);
}
}
#border-animation{
position: absolute;
width: 200px;
border: 1px solid #333;
}
<div id="border-animation"><div>

How to make a div slide with scrolling?

I want to make a div slide (in,out,left,up,right or down) when I reach a specific scrollTop() value. However, I don't want it to trigger some animation... I want the div to move with the scroll, like the effect achieved here: http://www.tioluchin.com/
so far, the "closest" I got was this:
var vistaEstandar = document.getElementById('vista');
vistaEstandar.onscroll = function() {animacionesEstandarVista()};
function animacionesEstandarVista()
{
var ypos = vistaEstandar.scrollTop;
if (($(window).width() >= 1800 && vistaEstandar.scrollTop > 6053) || ($(window).width() > 1800 && document.documentElement.scrollTop > 6053)) {
var image= document.getElementById("seccion9textoSegundo");
var toppin = ypos/6053;
image.style.top = toppin*150 + 'px';
}
else
{};
However, this doesn't work because the value I manage to set is too low.
The web I am trying to put together is long so when I multiply the value it is either too high or too low.
In the website http://www.tioluchin.com/ I want the effect the knives and food have
I went into that source code because it made me curious. I have found how they do it.
First part is catching what happens on scroll
$(document).scroll(function(){
windowScroll()
});
They have there a condition which disables it on smaller screens but that is not important here.
Second part is this:
function windowScroll(){
var st = $(document).scrollTop();
$("#aff").css({"top": 32 - st * 0.15 + "px"});
$("#aff").css({"left": 48 - st * 0.15 + "px"});
}
They have it bigger, for more elements. And this is my playground. In principle you have start with current position as an offset. "st" indicates how deep you are. st*0.15 tells you how fast the element will run from the screen.
My HTML:
<div class="wrapper">
<div id="aff" class="moving-div">
</div>
And CSS:
.moving-div {
width: 3rem;
height: 3rem;
position: relative;
top: 2rem;
left: 3rem;
background: red;
}
.wrapper {
height: 1000px;
}

Zoom inside of a div, changing the inner elements but not the div itself

I am looking for a way to zoom into a div element. Since this question did not provide some code example, I decided to post the following.
This jsfiddle already helped, but as you can see in my adapted jsfiddle, the whole div scales. I just want the image inside to scale. the div should have an overflow if zoomed in (also scroll bars).
Is this possible without including other scripts e.g. panzoom?
HTML
<div id="pane">
<img src="http://i.stack.imgur.com/oURrw.png">
</div>
JavaScript
$('#pane').bind('mousewheel DOMMouseScroll', function(e){
var stage = $(this);
scaleData = getZoom(stage);
if ( e.originalEvent.detail < 0 ){
setZoom( scaleData.curScale * '.9', stage );
}
else{
setZoom( scaleData.curScale * '1.1', stage );
}
});
function setZoom(scale, el){
scale = Math.round(scale*10)/10;
el.attr({
style:
'zoom: '+scale+';'+
'-webkit-transform: scale('+scale+');'+
'-moz-transform: scale('+scale+');'+
'-o-transform: scale('+scale+');'+
'-ms-transform: scale('+scale+');'+
'transform: scale('+scale+');'
});
}
function getZoom(el){
var curZoom = el.css('zoom');
var curScale = el.css('transform') ||
el.css('-webkit-transform') ||
el.css('-moz-transform') ||
el.css('-o-transform') ||
el.css('-ms-transform');
if ( curScale === 'none' ){
curScale = 1;
}else{
//Parse retarded matrix string into array of values
var scaleArray = $.parseJSON(curScale.replace(/^\w+\(/,"[").replace(/\)$/,"]"));
//We only need one of the two scaling components as we are always scaling evenly across both axes
curScale = scaleArray[0];
}
return { curZoom: curZoom, curScale: curScale };
}
CSS
div#pane{
height: 20em;
margin: auto;
background-color: #ffffff;
overflow: scroll;
position: relative;
z-index: 0;
}
Thank you
If I understand correctly the solution is to change the 2nd line of the JS you provided in a JSFiddle to:
var stage = $(this).find('img');
I just included .find('img') to the end of what you had there. Previously you were zooming the entire div, now it zooms just the img tag.

jQuery .Animate Opacity and .FadeOut/In Both Not Working Inside SetInterval

I trying to make what appears to the user to be an image fader. A string of images fade into each other. All the solutions that I found were complex, and normally required an for every image. I've come up with what should be a simple solution. It's working 90% on Firefox/Chrome/IE11 on Windows. On Android Chrome it's having issues.
Basically my idea is, I have two divs, absolutely positioned, one on top of the other. Both start with a background, sized to cover. The top one fades out, revealing the bottom one, and at the end of the animation, the background-image of the top one (current hidden) is changed to image 3. After a pause, it fades back in, and the background-image of the bottom one is changed to image 4. This repeats indefinitely.
HTML:
<div class="slideshow" id="slideshow-top"></div>
<div class="slideshow" id="slideshow-bottom"></div>
CSS:
.slideshow {
display:block;
background-size:cover;
width: 100%;
height: 100%;
position:absolute;
top:0;
left:0;
}
#slideshow-top {
z-index:-5;
background-image:url(http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg);
}
#slideshow-bottom {
z-index:-10;
background-image:url(http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg);
}
Javascript:
var url_array = [
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-3.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-4.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-5.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-6.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-7.jpg',
'http://www.walldoze.com/images/full/2013/12/04/wallpapers-desktop-winter-nature-x-wallpaper-backgrounds-natureabstract-designs-interesting-hd-19045.jpg'
];
var count = 1;
setInterval(function() {
if (count%2) { // Fade In
jQuery('#slideshow-top').animate({opacity:0}, '200000', function() {
jQuery('#slideshow-top').css('background-image','url('+url_array[count]+')');
});
}
else { //Fade Out
jQuery('#slideshow-top').animate({opacity:1}, '200', function() {
jQuery('#slideshow-bottom').css('background-image','url('+url_array[count]+')');
});
}
count = (count == url_array.length-1 ? 0 : count + 1);
}, 2000);
http://jsfiddle.net/5eXy9/
As seen in the Fiddle above, this mostly works. However, it seems to ignore the length of the animation. Using .fadeOut has the same effect. I've tried going from 200 to 20000, and there doesn't seem to be a difference.
I'm not sure if this is tied into the other issue, which is that on Android (Galaxy S4, Chrome, Android 4.x), the animation doesn't occur at all. It simply changes images. Any ideas?
EDIT: Jan 10 - Timing problem is fixed, but the main issue (Android) is still unsolved. Any thoughts?
The interval keeps going, so when increasing the animation speed, you have increase the interval speed as well.
The way you've built this, you should always keep the speed of both animations equal to the interval, or if you need a delay, increase the interval compared to the animations so it at least has a higher number than the highest number used in the animations.
The reason changing the speed doesn't work at all for you, is because it should be integers, not strings, so you have to do
jQuery('#slideshow-top').animate({opacity:0}, 200000, function() {...
// ^^ no quotes
I would do something like this
var url_array = [
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-1.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-2.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-3.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-4.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-5.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-6.jpg',
'http://www.andymercer.net/wp-content/uploads/2013/12/slider-7.jpg',
'http://www.walldoze.com/images/full/2013/12/04/wallpapers-desktop-winter-nature-x-wallpaper-backgrounds-natureabstract-designs-interesting-hd-19045.jpg'];
var count = 1;
var speed = 2000,
delay = 1000;
$.each(url_array, function(source) { // preload
var img = new Image();
img.src = source;
});
setInterval(function () {
if (count % 2) { // Fade In
jQuery('#slideshow-top').animate({
opacity: 0
}, speed, function () {
jQuery('#slideshow-top').css('background-image', 'url(' + url_array[count] + ')');
});
} else { //Fade Out
jQuery('#slideshow-top').animate({
opacity: 1
}, speed, function () {
jQuery('#slideshow-bottom').css('background-image', 'url(' + url_array[count] + ')');
});
}
count = (count == url_array.length - 1 ? 0 : count + 1);
}, speed + delay);
FIDDLE

Categories