I’m a totally JavaScript rookie, and I can’t really figure out how to do it.
I want a horizontal slider or tab script with thumbnails and arrow indication which thumbnail current showing in the slider, like this:
*http://jqueryglobe.com/labs/slide_thumbs/*
But it needs to be horizontal vertical. Can someone maybe help me to solve that problem?
Thanks in advance
Edit:
Yes, I'm sorry. I mean vertical. My bad.
It is not that hard actually.
You just need to re-order the HTML so that the images appear on the right/left of the preview main image container.
Then, if you look at the simple javascript involved, just modify everything that says "left" to "top" and "width" to "height" like so (this code is taken from the page itself -> view source):
$(document).ready(function() {
// Save the jQuery objects for later use.
var outer = $("#preview_outer");
var arrow = $("#arrow");
var thumbs = $("#thumbs span");
var preview_pos;
var preview_els = $("#preview_inner div");
var image_width = preview_els.eq(0).height(); // Get height of imaages
// Hook up the click event
thumbs.click(function() {
// Get position of current image
preview_pos = preview_els.eq( thumbs.index( this) ).position();
// Animate them!
outer.stop().animate( {'scrollTop' : preview_pos.top}, 500 );
arrow.stop().animate( {'top' : $(this).position().top }, 500 );
});
// Reset positions on load
arrow.css( {'top' : thumbs.eq(0).position().top } ).show();
outer.animate( {'scrollTop' : 0}, 0 );
// Set initial width
$("#preview_inner").css('height', preview_els.length * image_height);
});
Related
I have a carousel (Owl Carousel) with vertically centered controls. Because of the structure, I have to absolutely position the previous and next arrow. Because the page is responsive, their position is dynamic. The size of the controls may also change.
I've written a function that runs on load and resize. It gets the height of the image and the height of the controls, subtracts the latter from the former, divides by two, and then uses that number as the controls' margin-top.
It works, but I'm questioning if I'm getting and using all the variables correctly. Does JavaScript read in order? Where it runs the first line, then the next, then the next... I'm strong in CSS but JS has always been a crutch.
Can I write this more efficiently?
function centerCarouselControls() {
var carouselImage = $('.carousel-card > img');
var carouselControls = $('.owl-nav > div');
var carouselHeight = carouselImage.outerHeight();
var controlHeight = carouselControls.outerHeight();
var controlMargin = (carouselHeight - controlHeight) / 2;
carouselControls.css('margin-top', controlMargin);
}
$('.carousel-card > img').load(centerCarouselControls);
$(window).on('resize', centerCarouselControls);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I feel like this might be the type of question that gets flagged on here for not being specific enough. If that's the case, could someone please point me to a community where this would be more appropriate? Thanks!
In some browsers your code works like firefox 51, but it is more complete code this:
carouselControls.css('margin-top', controlMargin + 'px');
I am looking to create a scrolling effect similar to that shown here: http://www.seaham-hall.co.uk/
However I am unable to achieve the desired effect, and inspecting the sites code gives me no hints. Quite difficult to google for as it is also quite difficult to describe. The closest I can get to finding a solution is this JSFiddle:
http://jsfiddle.net/xtyus/1/
(function($){
/* Store the original positions */
var d1 = $('.one');
var d1orgtop = d1.position().top;
var d2 = $('.two');
var d2orgtop = d2.position().top;
var d3 = $('.three');
var d3orgtop = d3.position().top;
var d4 = $('.four');
var d4orgtop = d4.position().top;
/* respond to the scroll event */
$(window).scroll(function(){
/* get the current scroll position */
var st = $(window).scrollTop();
/* change classes based on section positions */
if (st >= d1orgtop) {
d1.addClass('latched');
} else {
d1.removeClass('latched');
}
if (st >= d2orgtop) {
d2.addClass('latched');
} else {
d2.removeClass('latched');
}
if (st >= d3orgtop) {
d3.addClass('latched');
} else {
d3.removeClass('latched');
}
if (st >= d4orgtop) {
d4.addClass('latched');
} else {
d4.removeClass('latched');
}
});
})(window.jQuery);
However I am not sure that is going in the right direction, this pulls images up and covers the previous image, but notice on the Seaham Hall site the images don't appear to move up at all, they are stationary and become revealed as you scroll.
How do I recreate this effect? My initial thought was to have the first image shrink as you scroll from 1000px down to 0px, and the second image grow to 1000px, and as you continue to scroll this image then shrinks and the third grows, and so on. However this means that after the first image all the other images have a starting size of 0px and there would technically be no scrolling on the page to begin with, so that is an issue.
My second thought is that perhaps the second image is fixed to the page, the first image slides up revealing the second as you scroll, the second image would not appear to move. Once the first image has gone off the top of the page the second image is detached from the page and allowed to move up with scrolling, while the third image is attached and revealed as the second moves up, this would give the exact effect seen in the Seaham website but I have no clue of it is the correct answer.
If anyone can point me to tutorials or a JSFiddle with a basic concept I can probably figure it out from there. Just stumped what direction to approach this from.
That's a nice effect. Here's one way to do it.
Put each image in a fixed position div, which takes up the entire viewport (initially) and has overflow:hidden.
Set each div's z-index to be higher than the next div's.
As the window scrolls, adjust the height of the divs as a function of the window height times the div's position (index) in the DOM, minus the window's scrollTop:
$(window).scroll(function() {
$('.D').each(function(index) {
$(this).css({
height: $(window).height()*(index+1) - $(window).scrollTop()
});
});
});
Additional content will need a higher z-index than the image divs. And note that z-index works with positioned elements only.
Fiddle
Your desired effect isn't technically a parallax background, but it's close enough that parallax jQuery frameworks should work for you.
I would suggest you research jQuery Parallax plugins as they'll likely provide the functionality you'd like without much custom work. Of course since you're dealing with large images it's also best to keep an eye on the resource management; a good plugin should be fairly efficient but others may be slow or resource intensive.
Check this jquery plugin:ScrollMagic
usage: taken from github
The basic ScrollMagic design pattern is one controller, which has several scenes attached.
Each scene has a definite start and end position and defines what happens when the container is scrolled to the specific offset.
/*
Basic workflow example
*/
// init controller
var controller = new ScrollMagic();
// assign handler "scene" and add it to controller
var scene = new ScrollScene({duration: 100})
.setPin("#my-sticky-element") // pins the element for a scroll distance of 100px
.addTo(controller); // add scene to controller
// adding multiple scenes at once
var scene2 = new ScrollScene();
var scene3;
controller.addScene([
scene2,
scene3 = new ScrollScene({duration: 200}), // add scene and assign handler "scene2"
new ScrollScene({offset: 20}) // add anonymous scene
]);
I am building a Parallax website using SuperScrollorama which have some animation frame by frame using jquery and css3...
But after ending up doing so i am stuck in a problem, i am trying to navigate the pages using some scroll plugin...
I have tried Basic jquery using scrollTop event, using Jquery ScrollTo and using Tween Lite ScrollTo plugin to navigate through pages but nothing seems to work...
The issue i get after goggling it is if pages are pinned together as position:fixed; and pages doesnot scroll to that position and stuck between...
With Jquery ScrollTo, my code:-
$('.menus a').click(function(e){
e.preventDefault();
$.scrollTo(this.hash, 2000, {
easing:'easeInOutExpo',
offset:3000,
axis:'y',
queue:true
});
});
With basic scrollTop jquery, my code:-
$('a').bind('click',function(event){
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500,'easeInOutExpo');
event.preventDefault();
});
Currently my code works like this:- http://jsfiddle.net/tFPp3/6/
As you can see in my demo, the scroll stuck between before reaching the exact position through hash...
What is the solution if i have to play through the pinned elements in Superscrollorama?
You'll have to do 2 animations : one to reach the ancher offset and then, after superscrollorama added new element for animation and recalculate the document height, do the second animation to reach the correct key frame on that page (that you fixed at offset 3000 of that section).
$(function(){
var hashes = [];
$('.menus a').each(function(){
hashes.push(this.hash);
});
console.log('hashes:', hashes);
$('.menus a').click(function(e){
e.preventDefault();
var h = this.hash;
var pageTop = $(h).offset()['top'];
console.log('pageTop=',pageTop);
$.scrollTo( pageTop+1, 2000, {
easing:'easeInExpo',
axis:'y',
onAfter:function(){
setTimeout(function(){
console.log('hashes:', hashes);
var id = hashes.indexOf(h);
console.log('hashes['+(id+1)+']=', hashes[(id+1)]);
var nextPageTop = $(hashes[id+1]).offset()['top'];
console.log('nextPageTop=', nextPageTop);
var keyOffset = pageTop + 3000;
console.log('keyOffset=',keyOffset);
if(keyOffset < nextPageTop ){
$.scrollTo( keyOffset, 2000, {
easing:'easeOutExpo',
axis:'y'
});
}
},100);
}
});
});
});
Note that each section offset changes constantly so, before launching the second animation, we have to test that we are not scrolling till the next section again. We also need a little delay here to let superscrollorama make its sauce before testing respective offsets (saddly it doesn't seem to provide an event to do so).
I had the same issue as you. Here's how I went about fixing it....
First of all we know that Superscrollorama adds a spacer pin before your element, it sets the height of the element which defines how long the user has to scroll through a section (the duration)....So in theory all we have to do is add up all the pin heights that happen BEFORE the element you want to scroll to and then offset from the top of that element...
What I did was....
Find out what element you want to scroll to. Check how many supersrollorama-pin-spacers there are before that pin, work out the heights of all of the pins and then offset it to your initial scrollTo function.
pin = $('#pin-id').prev(); //find the spacer pin
prevPin = pin.prevAll('.superscrollorama-pin-spacer'); //find all the pins before this
heights = []; //create an array to store the pin heights
$.each(prevPin, function( index, value ) {
value = $(this).attr('height'); //get each height
heights.push(value); // push it to array
});
//use eval to join all the heights together
heights = eval(heights.join("+"));
Now we have the height so lets scroll to it.....
TweenMax.to($('html,body'),1, { scrollTop:heights, });
Good Luck! I hope this helps you.
I have had a similar issue and found that janpaepke on the superscrollorama project added an additional toggle to make this easier.
You can manually add the spacers so you don't need to make adjustments by setting the pushFollowers flag in your pin to false.
Example JS
controller.pin($('#pin-id'), 200, {
anim: new TimelineLite().append([TweenMax.fromTo( $('#pin-id'), 2, {css:{opacity: 1}}, {css:{opacity: 0}})]),
offset: 0,
pushFollowers: false
});
Example HTML
<div id="pin-id">
Bunch of Content
</div>
<div style="padding-top: 200px"></div>
Let me start of by saying, I'm just now learning JS and Jquery, so my knowledge is very limited.
I've been looking around for 2 days now, and tried all sorts of combinations. But I just can't get this to work.
Below is an example of the layout
I'm looking for a way to trigger an event when div 1 is X px from the top of the screen. Or when div 1 collides with div 2.
What I'm trying to accomplish is to change the css of div 2 (the fixed menu) when div 1 is (in this case) 100px from the top of screen (browser window). Alternatively, when div1 passes div2 (I'm using responsive design, so the fixed height from top might become a problem on smaller screens right? Seeing as the header for example won't be there on a hand held.). So maybe collision detection is better here? Would really appreciate some thoughts and input on this matter.
Another issue is, div2 has to revert back to is previous css once div1 passes it (going back (beyond the 100px)).
This is what I have but it has no effect
$(document).ready(function() {
var content = $('#div1');
var top = $('#div2');
$(window).on('scroll', function() {
if(content.offset().top <= 100) {
top.css({'opacity': 0.8});
}else{
top.css({'opacity': 1});
}
});
});
I am not sure of the reason but $("#content").offset().top was giving a constant value on console. So I added window.scrollTOp() to check its distance from top, here is how it works,
$(document).ready(function() {
var top = $("#menu");
$(window).on('scroll', function(){
if(($('#content').offset().top - $(window).scrollTop()) <= 100){
top.css({'opacity': 0.4});
}else{
top.css({'opacity': 1});
}
});
});
And DEMO JSFIDDLE....
I have run into a strange phenomena I believe and I was wonder if anyone has a the answer to why this occurs. I have been doing a lot of manipulation of images for a photography site using a custom jQuery slideshow I created and have run into some problems.
I have a gallery here: http://www.daemondeveloper.com/photography/gallery.php
I have been adding some functions that resize the images in this gallery so that they scale to the size of the preview image size. As you can see, the very last image is panoramic and does not fill up the entire height of the div even though I have javascript telling it to resize.
If you refresh the page, the javascript seems to work all of a sudden and the pictures scales how it should.
Now try clicking on the panoramic picture of the girl and my slideshow will appear displaying the image scaled and centered vertically using jQuery. The function below is what handles clicking on the small image previews in the gallery.
If you look at where the commented changeSize() function is, that is where I USED to have the function and the scaling did not work. Then I moved it after the .show() functions which show my slideshow and now it works. So it appears that the display:none; affected how the javascript fired because when I debugged, the currentImg object was null, as if the .slides selector did not exist when it was set to display:none;. Is this really happening or am I just seeing a side effect of something else?
If this is really happening it may have something to do with the cause of the first problem I stated about the panoramic image not scaling on the first load of the gallery.php page.
$('.imgHolder').click(function(){
currentPosition = $('.imgHolder').index(this);
$('#slideShow').width(slideWidth);
// Remove scrollbar in JS
$('#slideContainer').css('overflow', 'hidden');
// Wrap all .slides with #slideInner div
slides.css({
'float' : 'left',
'width' : slideWidth
});
// Set #slideInner width equal to total width of all slides
$('#slideInner').css('width', (slideWidth * numberOfSlides));
// Hide left arrow control on first load
manageControls(currentPosition);
$('#slideInner').css('margin-left' , slideWidth*(-currentPosition));
//changeSize(); used to be here
$('#filter').show();
$('#photoWrap').show();
//Change image scale and center
changeSize();
});
And here is the changeSize() function that does the scaling and centering
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img:first')[0];
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
$('#gallery ul li').each(function() {
var img = $(this).children('div').children('img').first();
var ratio = img.height() / img.width();
var goal = img.parent('div').height() / img.parent('div').width();
if (ratio < goal) {
img.addClass('portrait');
img.css('margin-left', -(img.width() / 2) + ($(this).children('div').width() / 2));
} else {
img.css('width', '100%');
}
});
Here I removed the unnecessary $() instances from your code, as you have already selected the element that you wish to call your methods on when you set the img variable. I doubt that this redundancy is the ultimate issue, but it is a good place to start.
Update your code to this and let's debug from there.
EDIT:
I think I found your error (well, I found one at least):
function configGallery()
{
var currentPosition;
var slides = $('.slide')
var currentSlide;
var currentImg;
var slideWidth = 720;
var numberOfSlides = slides.length;
...
}
Do you see what's wrong here? You forgot a semi-colon after var slides = $('.slide') and that could be your issue. Honestly, I'm surprised any of your scripts ran at all. Missing semi-colons usually crash the whole thing.
UPDATE:
Here are a few more selectors for you to remove the $() from when you get a chance:
function changeSize(){
currentSlide = $('.slide').get(currentPosition);
currentImg = $(currentSlide).children('img').first();
imgRatio = $(currentImg).height() / $(currentImg).width();
if(imgRatio < slideRatio)
{
$(currentImg).addClass('landscape');
//Vertically align
var thisHeight = $(currentImg).height();
$(currentImg).css('margin-top', ($('#slideShow').height()/2)-(thisHeight/2));
}else{
$(currentImg).addClass('portrait');
}
}
UPDATE:
Okay I wrote you a little fiddle to help you re-write your image-sizing function. I'll work on prettying it up and putting it in a plugin for you.
UPDATE:
Here's the same function again in a quick and dirty plugin: http://jsfiddle.net/Wj3RM/3/
I didn't pretty it up though - I figured it would be easier for you to adapt and modify like this.