how to make images swap as you scroll to appear in 3d - javascript

I have a client who has several powerpoint slides that they want to animate through seamlessly as the user scrolls down the page vertically. It is similar to this page:
http://www.bagigia.com/
Any advice on how to accomplish this? If you're familiar with webflow - that's usually the program of choice I use to help create the clean code for fast deployment but even raw code is totally welcome, OF COURSE!
Essentially, they have a water bottle that they have taken photos of in different positions and as they scroll down the page they want the water bottle to turn on its side and then towards the viewer. They have all of these images photographed and isolated but I can't figure out how to code it so that the bottle appears to animate.

From looking at the Bagigia source code it appears they have a bunch of ordered divs with background images inside a parent container #rotation .container. Each div has one angled product photo set as the background-image.
The jQuery code is bound to scroll events with $window.bind('scroll', function(){/*code*/}) which updates the .container's left property by a certain amount each time. This gives the impression of the images animating in rotation where really it is just sliding images to the left and off the visible area.
It is worth noting that the div elements have their width and height set on page load and on window resize event. This helps to determine what the left position should be updated by.
You can see all of this in their source code which is quite neatly formatted. Check out their script for the home page rotation at http://www.bagigia.com/js/bagigia.home.rotation.js?v=d38yhf5
Your question was only about the image rotation so I won't comment on the other features however you can always view the other source code as needed.
Good luck on building this yourself. I'd be interested in the results if you are able to share it, or perhaps write a blog post to share your approach, learnings, and outcomes.
Should Bagigia update/remove their website, I've pasted some of the relevant code below which is directly from their source and not my own work.
<div id="rotation">
<div class="popup">
<div class="item" id="popup-bag1"></div>
<div class="item" id="popup-bag5"></div>
<div class="item" id="popup-bag12"></div>
<div class="item" id="popup-bag17"></div>
<div class="item" id="popup-bag21"></div>
</div>
<div class="container">
<div class="bag-angle show" id="bag0" rel="popup-bag1"></div>
<div class="bag-angle" id="bag1" rel="popup-bag1"></div>
<div class="bag-angle" id="bag2" rel="popup-bag1"></div>
<div class="bag-angle" id="bag3"></div>
<div class="bag-angle" id="bag4"></div>
<div class="bag-angle" id="bag5" rel="popup-bag5"></div>
<div class="bag-angle" id="bag6" rel="popup-bag5"></div>
<div class="bag-angle" id="bag7" rel="popup-bag5"></div>
<div class="bag-angle" id="bag8"></div>
<div class="bag-angle" id="bag9"></div>
<div class="bag-angle" id="bag10"></div>
<div class="bag-angle" id="bag11"></div>
<div class="bag-angle" id="bag12" rel="popup-bag12"></div>
<div class="bag-angle" id="bag13" rel="popup-bag12"></div>
<div class="bag-angle" id="bag14" rel="popup-bag12"></div>
<div class="bag-angle" id="bag15"></div>
<div class="bag-angle" id="bag16"></div>
<div class="bag-angle" id="bag17" rel="popup-bag17"></div>
<div class="bag-angle" id="bag18" rel="popup-bag17"></div>
<div class="bag-angle" id="bag19" rel="popup-bag17"></div>
<div class="bag-angle" id="bag20"></div>
<div class="bag-angle" id="bag21" rel="popup-bag21"></div>
<div class="bag-angle" id="bag22" rel="popup-bag21"></div>
<div class="bag-angle" id="bag23" rel="popup-bag21"></div>
<div class="bag-angle" id="bag24"></div>
<div class="bag-angle" id="bag25"></div>
</div>
<div class="content">
</div>
</div>
$(document).ready(function(){
var $window = $(window);
var $introBox = $('#intro');
var $rotationBox = $('#rotation');
var $containerBox = $('#rotation .container');
var $bags = $('#rotation .bag-angle');
var blankHeight = 200;
var index = -1;
var $blankOpen = $('<div class="bag-blank"></div>');
$blankOpen.height($window.height() + blankHeight).appendTo($('#bag-blank-space'));
$bags.each(function(index){
var $blank = $('<div class="bag-blank" rel="bag' + index + '"></div>');
$blank.height(blankHeight).appendTo($('#bag-blank-space'));
});
$('.bag-blank:last').height(blankHeight/2);
$window.bind('scroll', function(){
var opacity = ($window.scrollTop()) / (($window.height()));
if (opacity <= 1){
if ($window.scrollTop() <= $introBox.height()){
$rotationBox.css({opacity: opacity});
}
}else{
$rotationBox.css({opacity: 1});
}
$('#bag-blank-space .bag-blank').each(function(i){
if ($window.scrollTop() > $(this).position().top){
index = i;
}
});
if (index < $bags.length){
var $toShow = $('#rotation .bag-angle:eq(' + index + ')');
var $toHide = $('#rotation .bag-angle.show');
if (!$toShow.hasClass('show')){
$toShow.addClass('show');
$toHide.removeClass('show');
var $popup = $('.popup .item#' + $toShow.attr('rel'));
if ($popup.length > 0 && !$rotationBox.is(':animated') && $rotationBox.position().top >= 0){
if (!$popup.hasClass('show') && !$rotationBox.hasClass('hide')){
$('.popup .item.show').removeClass('show').stop(false,true).animate({opacity:0},'fast');
if ($rotationBox.position().top >= 0){
$popup.addClass('show').stop(false,true).animate({opacity:1},'fast');
}
}
}else{
$('.popup .item.show').removeClass('show').stop(false,true).animate({opacity:0},'fast');
}
$containerBox.css({left: -1 * index * $window.width()});
}
if ($rotationBox.hasClass('hide')){
$rotationBox.removeClass('hide');
$('#payoffs .payoff-item:not(:first)').css({opacity:0});
$('#payoffs .payoff-item:first').addClass('show').animate({
opacity:0
},'slow', function(){
$('.payoff-bg-text').css({opacity:0});
$('.popup .item').stop().css({opacity:0}).show();
$rotationBox.stop(true,true).animate({top: 0},'slow', 'easeInOutBack',function(){$('.popup .item.show').stop().animate({opacity:1})});
});
}
}
});
$window.bind('resize', function(){
$('.bag-blank:first').height($window.height() + blankHeight);
$('.bag-blank:last').height(blankHeight/2);
$bags.width($window.width());
$bags.height($window.height());
$containerBox.css({left: -1 * index * $window.width()});
});
$bags.width($window.width());
$bags.height($window.height());
});

Related

Left align element with centered and variable width element in top row

I would like to find a way to left align <p> with centered <img> in the top.
As images are centered and my page contains different images with different widths, it seems to be a bit challenging.
Here is my html structure:
<div class="row">
<div class="container-fluid">
<div class="row">
<div class="col-md-4 my-auto">
<div class="d-flex flex-row justify-content-center">
<img class="img-fluid d-flex flex-wrap align-items-center" id="image-id">
</div>
</div>
<div class="col-md-8">
SOME CONTENT
</div>
</div>
<div class="collapse collapse-information">
<div class="row row-collapse m-0">
<!--What I want to be left aligned with img tag-->
</div>
</div>
</div>
</div>
A way to do it would be to get the distance between image's div and border of centered image and to report this measure as a left-margin on the element I want to be aligned.
To solve it, I tried to use margin measurments based on window width but it as not working.
While working to have a clean question, I went through https://developer.mozilla.org/en/docs/Web/API/HTMLElement/offsetLeft.
The interresting part is that, javascript allows a dynamic measurement I can also dynamically attribute to other elements.
// get left offset
var leftDistanceLogo = document.querySelector("#image-id").offsetLeft;
// assing as margin to the following element
document.querySelector('.row-collapse').style.marginLeft = leftDistanceLogo + "px";
Last interesting point, this code should wait until the end of page loading (otherwise offet will be equal to 0), so I called it in a structure like:
window.addEventListener("load", function (event) {
setTimeout(() => {
var leftDistanceLogo = document.querySelector("#image-id").offsetLeft;
document.querySelector('.row-collapse').style.marginLeft = leftDistanceLogo + "px";
}, 0);
});

Get distance (horizontal distance i.e-left border to right - in pixels) between multiple divs

I wanted to get the exact distance between :
#main div left border to first div with class="b"
between first div with class="b" to second div with class = "b"
Note that the divs can be randomly placed and divs can be fixed positions, so there can be gaps between two divs. Calculations like width of all the number of divs with class= a wont be a solution in that case.
<div class="main">
<div class="a"></div>
<div class="b"></div>
<div class="a"></div>
<div class="a"></div>
<div class="a"></div>
<div class="b"></div>
<div class="a"></div>
<div class="a"></div>
<div class="b"></div>
</div>
What I tried is this:
$(".main").children(".a").each(function() {
$(this).nextUntil(".b").length /* basically this width I need I guess */
console.log($(this).siblings(".b").prev(".a").html());
var diff = $(this).offset().top - $(this).nextUntil(".b").offset().top
// here both values are same so result is zero
console.log('diff' + diff);
});
Here you can use offsetTop property of the DOM element.
code should be,
$(".main b")[0].offsetTop
or pure jQuery would look like
$(".main b").offset().top // This will return top offset of the first selector matching element
Now to get distance between consecutive divs, you can write a simple for loop over $(".main b") elements
var elements = $(".main .b");
var offsets = []; // Array which saves offsets of elements
var distance = []; // Array which saves distance between each elements
for (var i = 0; i < elements.length; i++) {
var offset = $(elements[i]).offset().top;
offsets.push(offset);
if (i == 0) {
distance.push(offset);
} else {
distance.push(offset - distance[i - 1]);
}
}
console.log(offsets);
console.log(distance);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<div class="a">some</div>
<div class="b">some</div>
<div class="a">some</div>
<div class="a">some</div>
<div class="a">some</div>
<div class="b">some</div>
<div class="a">some</div>
<div class="a">some</div>
<div class="b">some</div>
</div>
Also fiddle

window.scroll to activate class one at a time

I incorporated a window.scroll function to activate when animations start on my page. I have three different images, that look like this:
image
image
image
I am wanting them to appear once I scroll to their div. However, for some reason right now, if I go over one of them, the entire sequence starts for all of them.
My window scroll function looks like this:
$(function() {
var oTop = $('.home-img-block', this).offset().top - window.innerHeight;
$(window).scroll(function() {
var pTop = $('body').scrollTop();
console.log(pTop + ' - ' + oTop);
if (pTop > oTop) {
imgDelaysSlide();
}
});
});
The HTML looks like this:
<div id="home-img-block-section">
<div id="home-img-blocks">
<div class="home-img-block fadeBlock1">
<div data-content="FIND OUT MORE" class='home-img-container'>
<img src="/images/test1.jpg">
<div class="overlay"></div>
</div>
<div class="home-img-wording-blocks">
<div class="home-img-wording-block-title">WEB DESIGN</div>
<div class="home-img-wording-block-description">The OD team can see your web design visions brought
to life, creating a site that promotes your uniqueness through specific functionalities and features.</div>
</div>
</div>
<div class="home-img-block fadeBlock2">
<div data-content="FIND OUT MORE" class='home-img-container'>
<img src="/images/test2new.jpg">
<div class="overlay"></div>
</div>
<div class="home-img-wording-blocks">
<div class="home-img-wording-block-title">ECOMMERCE</div>
<div class="home-img-wording-block-description">Custom built solutions catered towards you end goal.
gfdgfdsg greg reg regrfesg fdsg gretswtgy tgreswt treswt trgegfd gsvbd fbgre greasgv drfdg greaag gredr</div>
</div>
</div>
<div class="home-img-block fadeBlock3">
<div data-content="FIND OUT MORE" class='home-img-container'>
<img src="/images/test3new.jpg">
<div class="overlay"></div>
</div>
<div class="home-img-wording-blocks">
<div class="home-img-wording-block-title">MARKETING STRATEGIES</div>
<div class="home-img-wording-block-description">MARKETING STRATEGIES gfdgf fdggs gfsg gfsg gf sgf g
gfdsg sdfggfs gfdsgssdfg fdggfds gfdsg gfds gfdgs gf dsgfdsgfgs gfdgfs gtrg resg reg rgesgresrgrg</div>
</div>
</div>
</div>
Should the this in my window.scroll function make these animations start when I hover over the current div class?
var oTop = $('.home-img-block', this).offset().top - window.innerHeight;
$(window).scroll(function() {
Is there anything else I could try to do to call out that specific div, rather than the entire class?
UPDATE adding imgDelaysSlide function
function imgDelaysSlide() {
$('.fadeBlock1').delay(300).animate({
'left': '0%'
}, 700);
$('.fadeBlock2').delay(800).animate({
'left': '0%'
}, 700);
$('.fadeBlock3').animate({
'left': '0%'
}, 700);
}

How to make thumbnails slide show only the thumbnails pic

I need to make some simple JavaScript gallery with Thumbnail slider.
I made the slider and when I click on the left or the right arrow the margin-right change and add or remove 570px. But I want to make it better, and when the gallery loads, cancel the Scroll right option because there's actually pictures, the same also for last images.
HTML Structure look like this:
<div class="tumbNavigation">
<div class="right_nav"></div>
<div class="thumbnails">
<div class="thumbnailsWrapper">
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
<div class="thumbItem"></div>
</div>
</div>
<div class="left_nav"></div>
</div>
JavaScript code look like this:
var pos = 0;
var width = 570;
$('.left_nav').click(function(){
pos = pos - width;
$('.thumbnailsWrapper').stop(true).animate({ marginRight: pos + "px"}, 500);
});
$('.right_nav').click(function(){
pos = pos + width;
$('.thumbnailsWrapper').stop(true).animate({ marginRight: pos + "px"}, 500);
});
You're on the right track, but there's no need to reinvent the wheel here. Carousels such as this are one of the most commonly developed widgets, so much so that you're bound to find something that's better, more stable, and has more features than anything you could quickly build. Here's a list of 55 carousel javascript plugins: http://www.tripwiremagazine.com/2012/12/jquery-carousel.html . I'm sure that one of them will work great for you, or it will be close enough that you can modify it to be perfect.

Sorting DIVs inside other DIVs [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to sort divs according to their id using jQuery?
Well I'm having a really hard time trying to solve this and I actually had no sucess until now, I'm trying to sort DIVs inside Other DIVs by ID.
So here's how my DIVs are distribuited in my page
<div id="products" >
<div class="line">
<div id="Album2">[there are images and even other divs here in each Album]</div>
<div id="Album1"></div>
<div id="Album10"></div>
<div id="Album16"></div>
</div>
<div class="line">
<div id="Album9"></div>
<div id="Album3"></div>
<div id="Album4"></div>
<div id="Album7"></div>
</div>
<div class="line">
<div id="Album5"></div>
<div id="Album11"></div>
<div id="Album6"></div>
<div id="Album13"></div>
</div>
<div class="line">
<div id="Album8"></div>
<div id="Album14"></div>
<div id="Album12"></div>
<div id="Album15"></div>
</div>
</div>
and this should be my output:
<div id="products" >
<div class="line">
<div id="Album1"></div>
<div id="Album2"></div>
<div id="Album3"></div>
<div id="Album4"></div>
</div>
<div class="line">
<div id="Album5"></div>
<div id="Album6"></div>
<div id="Album7"></div>
<div id="Album8"></div>
</div>
<div class="line">
<div id="Album9"></div>
<div id="Album10"></div>
<div id="Album11"></div>
<div id="Album12"></div>
</div>
<div class="line">
<div id="Album13"></div>
<div id="Album14"></div>
<div id="Album15"></div>
<div id="Album16"></div>
</div>
</div>
But I have one more problem, all my products are listed and there are more than one page, I was actually able to track them and made a sorted Array of Strings but I didn't had the same luck doing it with the DIVs.
This is my page:
http://biscoitofino.jumpseller.com/catalogo
Any suggestions?
Thanks in advance.
Something like this should do it, at least within the context of a single page:
var lines = $("#products .line");
var elems = $("#products .line div");
for (var index = 1; index <= elems.length; index++) {
var elemId = "Album" + index;
var containerIndex = parseInt((index - 1) / 4);
var container = lines[containerIndex];
var elem = document.getElementById(elemId);
elem.parentNode.removeChild(elem);
container.appendChild(elem);
}
Here's an example: http://jsfiddle.net/dpHyn/
Although I think the real answer is, since presumably you've got a server that's providing the list of albums dynamically already, why not just have the server sort the elements properly when it loads them from the database (or whatever other datasource you are using)? That would save you all this trouble, and work properly with pagination as well.
​
var lines = $("#products > .line"),
albums = lines.children().toArray(),
line = -1;
albums.sort(function(a, b) {
return a.id.replace("Album", "") - b.id.replace("Album", "");
});
$.each(albums, function(i, el) {
if (!(i % lines.length))
line += 1;
lines.eq(line).append(el);
});
or without jquery
var lines = document.querySelectorAll("#products > .line"),
line = -1;
[].slice.call(document.querySelectorAll("#products > .line > div"))
.sort(function(a,b) {
return a.id.replace("Album", "") - b.id.replace("Album", "");
})
.forEach(function(el, i) {
if (!(i % lines.length))
line += 1;
lines[line].appendChild(el);
});

Categories