I try to implement a javascript function that animate an image sequence while scrolling.
I try to create the animation with the script from this link: https://www.jqueryscript.net/animation/jQuery-Plugin-To-Create-Image-Sequence-Animation-On-Scroll-Sequencer.html
My problem is that this script is already three years old and does not work with jQuery 3.2.1. But I have to use this much newer jQuery version.
The code of the script looks like this:
/**
* jQuery-Sequencer
* https://github.com/skruf/jQuery-sequencer
*
* Created by Thomas Låver
* http://www.laaver.com
*
* Version: 2.0.0
* Requires: jQuery 1.6+
*
*/
(function($) {
$.fn.sequencer = function(options, cb) {
var self = this,
paths = [],
load = 0,
sectionHeight,
windowHeight,
currentScroll,
percentageScroll,
index;
if(options.path.substr(-1) === "/") {
options.path = options.path.substr(0, options.path.length - 1)
}
for (var i = 0; i <= options.count; i++) {
paths.push(options.path + "/" + i + "." + options.ext);
}
$("<div class='jquery-sequencer-preload'></div>").appendTo("body").css("display", "none");
$(paths).each(function() {
$("<img>").attr("src", this).load(function() {
$(this).appendTo("div.jquery-sequencer-preload");
load++;
if (load === paths.length) {
cb();
}
});
});
$(window).scroll(function() {
sectionHeight = $(self).height();
windowHeight = $(this).height();
currentScroll = $(this).scrollTop();
percentageScroll = 100 * currentScroll / (sectionHeight - windowHeight);
index = Math.round(percentageScroll / 100 * options.count);
if(index < options.count) {
$("img.sequencer").attr("src", paths[index]);
}
});
return this;
};
}(jQuery));
So I already changed the line 37 from
$("<img>").attr("src", this).load(function() {
to
$("<img>").attr("src", this).on("load", function() {
With this change all my images are loaded but I still get the error message: Uncaught TypeError: cb is not a function
What do I have to change as well, so the script is working again?
Thanks for any tip.
cb() is a Callback function will be called once the preloader is done fetching images.
From the example you have linked to, the callback is:
function() {
$("div#preload").hide();
}
which quite simply hides the preloader message.
In context, the plugin is initialised as:
$("div#images").sequencer({
count: 128,
path: "./images",
ext: "jpg"
}, function() {
$("div#preload").hide();
});
As you have not supplied how you are calling this function, I suspect you are missing this function callback.
Related
Hi a have created a code that adds a class when the element comes in view, parallax if you like. however i want the items to come in at different speeds the next slower than the one before. I however cant seem to make this code reusable using the 'this' property so that I don't have to rewrite it for each instance I want to use it.
if (!jQuery('#thumbnail-section-1 #thumbnail-preview.thumbnail-preview-fade-in').hasClass("is-showing")) {
if(wScroll > $('#thumbnail-section-1').offset().top - ($(window).height() / 1.2)) {
$('#thumbnail-section-1 #thumbnail-preview.thumbnail-preview-fade-in').each(function(i){
setTimeout(function(){
$('#thumbnail-preview.thumbnail-preview-fade-in').eq(i).addClass('is-showing');
}, (700 * (Math.exp(i * 0.35))) - 700);
setTimeout(function(){
$('#thumbnail-section-1 .overlay2 h2').eq(i).addClass('showing');
}, (700 * (Math.exp(i * 0.35))) - 700);
});
}
}
There's no real need to use this since your .each call can also pass the current element:
var $sect = $('#thumbnail-section-1');
var $sel = $sect.find('#thumbnail-preview.thumbnail-preview-fade-in');
var $h2 = $sect.find('.overlay2 h2');
if (!$sel.hasClass('is-showing')) {
if (wScroll > $sect.offset().top - ($(window).height() / 1.2)) {
$sel.each(function(i, el) { // <-- here
var delay = 700 * (Math.exp(i * 0.35) - 1);
setTimeout(function() {
$(el).addClass('is-showing');
$h2.eq(i).addClass('showing');
}, delay);
});
}
}
This is plugin's jquery code.in this code one image move in one scroll but my problem is i have to move 4 image one by one in one scroll in this sequencer.
and add specific time interval when one image move to another image please help me out of this problem.
Plugin Demo:https://www.jqueryscript.net/animation/jQuery-Plugin-To-Create-Image-Sequence-Animation-On-Scroll-Sequencer.html
(function($) {
$.fn.sequencer = function(options, cb) {
var self = this,
paths = [],
load = 0,
sectionHeight,
windowHeight,
currentScroll,
percentageScroll,
index;
if(options.path.substr(-1) === "/") {
options.path = options.path.substr(0, options.path.length - 1)
}
for (var i = 0; i <= options.count; i++) {
paths.push(options.path + "/" + i + "." + options.ext);
}
$("<div class='jquery-sequencer-preload'></div>").appendTo("body").css("display", "none");
$(paths).each(function() {
$("<img>").attr("src", this).load(function() {
$(this).appendTo("div.jquery-sequencer-preload");
load++;
if (load === paths.length) {
cb();
}
});
});
$(window).scroll(function() {
sectionHeight = $(self).height();
windowHeight = $(this).height();
currentScroll = $(this).scrollTop();
percentageScroll = 100 * currentScroll / (sectionHeight - windowHeight);
index = Math.round(percentageScroll / 100 * options.count);
if(index < options.count) {
$("img.sequencer").attr("src", paths[index]);
}
});
return this;
};
}(jQuery));
I think what you want here is setInterval().
You can write a function to change the image which should be pretty simple, and call that function as a parameter in setInterval().
So something along the lines of this at the end of your code:
setInterval(changeImage, 60000);
//executes the changeImage() function every 60 seconds
You can read more about setInterval() here.
I hope that helps!
The below is the source code of a simple parallax plugin:
/*
Plugin: jQuery Parallax
Version 1.1.3
Author: Ian Lunn
Twitter: #IanLunn
Author URL: http://www.ianlunn.co.uk/
Plugin URL: http://www.ianlunn.co.uk/plugins/jquery-parallax/
Dual licensed under the MIT and GPL licenses:
http://www.opensource.org/licenses/mit-license.php
http://www.gnu.org/licenses/gpl.html
*/
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
console.log(firstTop + " " + pos);
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
Now suppose i call the plugin , like so , on multiple elements.
$('#intro').parallax("50%", .8);
$('#second').parallax("50%", 0.1);
$('.bg').parallax("50%", 0.4);
$('#third').parallax("50%", 0.3);
What am i really doing ? creating multiple instances of the plugin ?
A demo of the plugin itself can be seen HERE.
No, you are not creating multiple instances of the plugin.
What you are doing is that you are calling this function multiple times:
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
This is perfectly fine to do.
What you really are looking at is a jQuery extension method. This method merges the contents of an object onto the jQuery prototype to provide new jQuery instance methods.
Whenever you see the fn property, you are looking at an alias to the prototype property of jQuery.
Lets examine some lines in the parallax script you are embedding:
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
This line is the start of a new jQuery prototype extension method that takes three arguments
Here is a more simple example that extends jQuery with a new method
$(function () {
// declare the new method greenify
$.fn.greenify = function() {
// The element that this method is used on will have the color green by using jQuery .css();
this.css( "color", "green" );
};
// Then to use your brand new jQuery extension method simply do this
$( "a" ).greenify();
$('.myElem').greenify();
$('#someElemId').greenify();
});
What is happening is that we are using the same method and applying it to different elements in the dom.
I hope this made it clearer what is really going on and how extension methods work.
I have been struggling to get Isotope to work. I have an application where after clicking a button I load some more images by getting their URLs from JSON. The issue I am having is that when I add the images to the 'galleryContainer' div (my div that I am holding all the images in) the images overlap. That or nothing happens and the whole page seems to freeze. Apparently this is a frequent problem but I still have not been able to get it working for my project. I try to use 'imagesLoaded' but it never seems to work for me.
Here is the relevant code:
// Get more images and add them to the galleryContainer
function getMoreImages() {
for (var i = 0; i < 3; i++) {
var newImage = $('<div class="objects"></div>');
var x = Math.floor((Math.random() * 750) + 750);
var y = Math.floor((Math.random() * 750) + 750);
newImage.append($('<img width="750" src="http://lorempixel.com/' + x + '/' + y + '">'));
$container.append(newImage).imagesLoaded(function() {
$container.isotope('appended', newImage);
});
}
}
Here is a (JSFiddle)[http://codepen.io/dirtshell/pen/emdjGv] demonstrating my problem.
It is totally possible that I am simply making a simple mistake JS wise (like not using the imagesLoaded plugin correctly), since I am sort of new to it.
Thanks =)
One issue is that your codepen is using isotope v2 but your js and CSS are for isotope v1.5.
You need imagesLoaded to prevent the overlap but it is not included as part of isotope v2 as it was in v1.5. You need to load it separately.
Is the getMoreImages() function what you are actually using on your site to load new images?
Also there is no longer "animationOptions" in isotope v2:
This
animationOptions: {
duration: 750,
easing: 'linear',
queue: false
}
is now this:
transitionDuration: '0.4s'
and in v2, you can remove any v1.5 isotope CSS
ADDENDUM
Here is an update to you Codepen
here is the relevant code (altered):
var $container = $('.galleryContainer');
// Initialize isotope on window load and image load
$(window).load(function() {
$container.isotope({
itemSelector: '.objects',
masonry: {
columnWidth: 780
},
transitionData: '0.4s'
});
});
// Get more images and add them to the galleryContainer
$('.loadButton').on( 'click', function() {
var x = Math.floor((Math.random() * 750) + 750);
var y = Math.floor((Math.random() * 750) + 750);
for (var i = 0; i < 3; i++) {
var newImage = $('<div class="objects"><img width="750" src="http://lorempixel.com/' + x + '/' + y + '"></div>');
}
$container.append(newImage).imagesLoaded(function() {
$container.isotope('appended', newImage);
});
});
Here is excerpt from my larger JavaScript file:
function dashboardConfig()
{
$(window).on('resize', function () {
var viewport = {
width : $(this).width(),
height : $(this).height()
};
el.siteContainer.css(
{
marginTop : (viewport.height - 652) / 2
});
el.dashboardSlide.css(
{
marginLeft : (viewport.width - 1024) / 2,
marginRight : (viewport.width - 1024) / 2
});
//Calculate how many nav elements
el.navElements.each(function(i)
{
el.dashboard.css(
{
width : viewport.width * (i + 1)
});
$(this).click(function()
{
//HERE IS THE VARIABLE I WOULD LIKE TO USE
var dashboardSlidePosition = viewport.width * i;
el.navElements.removeClass('active');
$(this).addClass('active');
el.dashboard.animate(
{
left : -dashboardSlidePosition
},500, function()
{
el.dashboard.css(
{
left : -dashboardSlidePosition
});
});
});
});
//I WANT TO PERFORM ANOTHER FUNCTION HERE AND HAVE IT USE THE VALUE OF dashboardSlidePosition
}).trigger('resize');
}
I want to know how I can pass the value of the variable, dashboardSlidePosition, to another function. Please can anyone explain how?
Many thanks in advance.
You can declare it at the outer edge of your scope. Make sure to give it an initial value so that you don't try to use it before it has been set properly.
function dashboardConfig()
{
var dashboardSlidePosition = null;
function anotherFunction() {
if (dashboardSlidePosition != null) {
// ...
}
}
$(this).click(function()
{
dashboardSlidePosition = viewport.width * i;
}
}
Put it into the proper scope:
function dashboardConfig()
{
var dashboardSlidePosition = 0;
Next, remove var when redefining it.
Now you can use it because it's in the scope of the function.