I'm trying to create different transition times for each slide in an impress.js presentation.
I found the code below in a book about impress.js. But checking it on JSLint it shows errors. I am not good enough with javascript to correct this myself. Anybody willing to help me out?
Edit: I need a solution without jQuery. This is because impress.js allows you to navigate through the presentation with spacebar and arrow keys and I don't want to lose that functionality.
I found that when navigating with the keys (while jQuery is timing the auto-advance) it does not respect the position where you navigated to, but forces you away from where you are. I would like instead that if you navigate to a slide (position) the auto-advance starts running the custom set time for that particular slide and advances to the next slide when the set amount of time has passed. This would be an awesome addition to impress.js. I hope this can be done. Thanks for your effort!
JSFiddle: http://jsfiddle.net/5sSE5/8/ (script added at the end of impress.js)
var step_transitions = [
{ "slide": 1, "duration": 2000 },
{ "slide": 2, "duration": 4000 },
{ "slide": 3, "duration": 1000 }
];
$(document).ready(function () {
var time_frame = 0;
step_transitions.filter(function (steps) {
time_frame = time_frame + steps.duration;
setTimeout(function () {
api.goto(steps.slide);
}); time_frame;
});
});
Addition: below script respects keyboard navigation, but all the slides have the same transition time.
var impress = impress();
impress.init();
document.addEventListener('impress:stepenter', function(e){
if (typeof timing !== 'undefined') clearInterval(timing);
var duration = (e.target.getAttribute('data-transition-duration') ? e.target.getAttribute('data-transition-duration') : 10000); // in ms
timing = setInterval(impress.next, duration);
});
There is an error in your code in the setTimeout:
setTimeout(function () {
api.goto(steps.slide);
}, time_frame);
It seems that the time_frame variable should be second argument of the setTimeout method.
Update
You also forgot to initialize the api variable before using it:
var api = impress();
You also need the jQuery library to be able to use the $ function.
See updated fiddle
Update 2
I reworked your code to make it continue from the first slide after the last is reached:
var step_transitions = [
{ "slide": 0, "duration": 3000 },
{ "slide": 1, "duration": 4000 },
{ "slide": 2, "duration": 2000 }
];
$(document).ready(function () {
var time_frame = 0,
api = impress(),
current_step_index = 0,
do_transition = function (){
var step = step_transitions[current_step_index];
api.goto(step.slide);
current_step_index++;
if(current_step_index >= step_transitions.length){
current_step_index = 0;
}
setTimeout(do_transition, step.duration);
};
//initial run
do_transition();
});
Note, that slides must start from 0, not 1.
See updated fiddle
Related
I want to set up a block with a number of questions (and page breaks), which after exactly 2 minutes will progress to the next block, regardless of what the subject has accomplished / clicked / performed in that block.
I set variables in the embedded data: TimeLeft1 = 120, TimeFlag1 = 0, and wrote the following code in each question in the block-
Qualtrics.SurveyEngine.addOnload(function()
{
var timeleft1 = parseInt("${e://Field/TimeLeft1}");
var timeflag1 = parseInt("${e://Field/TimeFlag1}");
var timer = setInterval(function(){
if (timeleft1<=0){
clearInterval(timer);
timeflag1 = 1;
$('NextButton').click();
}
timeleft1--;
}, 1000);
$('NextButton').onclick = function(event){
Qualtrics.SurveyEngine.setEmbeddedData('TimeLeft1',timeleft1);
Qualtrics.SurveyEngine.setEmbeddedData("TimeFlag1",timeflag1);
}
});
after that, I insert display logic, which display "if flag = 1".
Unfortunately, the survey doesn't proceed after 2 minutes, and the block that should appear, not appear..
If anyone can help, I would be very grateful!
I have a jQuery-based scrolling news ticker that uses a set interval in milliseconds to control the delay between the reveal of each new section of text. I'd like to randomize the delay so that it more closely mimics the way a realtime news feed would look.
I've tried experimenting with some Math.random javascript where the newsTickerInterval parameter is, but JS is not my native language and I'm having trouble making it work.
Here's the jQuery function my scroller uses to config the display:
$(function () {
$(".demo2").bootstrapNews({
newsPerPage: 4,
autoplay: true,
pauseOnHover: true,
navigation: false,
direction: 'down',
newsTickerInterval: 3000,
onToDo: function () {
//console.log(this);
}
});
});
Any hints or suggestions would be greatly appreciated!
Instead of using newsTickerInterval, make a function getNewsTickerDelay that generates a random delay interval and call it using a setTimeout whenever needed.
$(function () {
$(".demo2").bootstrapNews({
newsPerPage: 4,
autoplay: true,
pauseOnHover: true,
navigation: false,
direction: 'down',
getNewsTickerDelay: function() {
var minimumInterval = 2000;
var maximumInterval = 5000;
var additionalInterval = Math.floor(
Math.random() * (maximumInterval - minimumInterval)
);
return minimumInterval + additionalInterval;
},
onToDo: function () {
//console.log(this);
}
});
});
So, every time your timeout is called, set another one with a random delay using getNewsTickerDelay
--EDIT--
As pointed out by #Barmar, you might need to tweak the implementation of the plugin in your case and implement its internal animate method to use your defined random interval instead of a fixed value. You'll just need to replace the self.options.newsTickerInterval in that plugin's JS to self.options.getNewsTickerDelay(). That is if you are willing to mutate the plugin's implementation.
So basically I have a page with a few sections. Each sections contains 5-30 image icons that are fairly small in size but large enough that I want to manipulate the load order of them.
I'm using a library called collagePlus which allows me to give it a list of elements which it will collage into a nice image grid. The idea here is to start at the first section of images, load the images, display the grid, then move on to the next section of images all the way to the end. Once we reach the end I pass a callback which initializes a gallery library I am using called fancybox which simply makes all the images interactive when clicked(but does not modify the icons state/styles).
var fancyCollage = new function() { /* A mixed usage of fancybox.js and collagePlus.js */
var collageOpts = {
'targetHeight': 200,
'fadeSpeed': 2000,
'allowPartialLastRow': true
};
// This is just for the case that the browser window is resized
var resizeTimer = null;
$(window).bind('resize', function() {
resetCollage(); // resize all collages
});
// Here we apply the actual CollagePlus plugin
var collage = function(elems) {
if (!elems)
elems = $('.Collage');
elems.removeWhitespace().collagePlus(collageOpts);
};
var resetCollage = function(elems) {
// hide all the images until we resize them
$('.Collage .Image_Wrapper').css("opacity", 0);
// set a timer to re-apply the plugin
if (resizeTimer) clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
collage(elems);
}, 200);
};
var setFancyBox = function() {
$(".covers").fancybox({/*options*/});
};
this.init = function(opts) {
if (opts != null) {
if (opts.height) {
collageOpts.targetHeight = opts.height;
}
}
$(document).ready(function() {
// some recursive functional funk
// basically goes through each section then each image in each section and loads the image and recurses onto the next image or section
function loadImage(images, imgIndex, sections, sectIndex, callback) {
if (sectIndex == sections.length) {
return callback();
}
if (imgIndex == images.length) {
var c = sections.eq(sectIndex);
collage(c);
images = sections.eq(sectIndex + 1).find("img.preload");
return loadImage(images, 0, sections, sectIndex + 1, callback);
}
var src = images.eq(imgIndex).data("src");
var img = new Image();
img.onload = img.onerror = function() {
images[imgIndex].src = src; // once the image is loaded set the UI element's source
loadImage(images, imgIndex + 1, sections, sectIndex, callback)
};
img.src = src; // load the image in the background
}
var firstImgList = $(".Collage").eq(0).find("img.preload");
loadImage(firstImgList, 0, $(".Collage"), 0, setFancyBox);
});
}
}
From my galleries I then call the init function.
It seems like my recursive chain being triggered by img.onload or img.onerror is not working properly if the images take a while to load(on slow networks or mobile). I'm not sure what I'm missing here so if anyone can chip in that would be great!
If it isn't clear what is going wrong from the code I posted you can see a live example here: https://www.yuvalboss.com/albums/olympic-traverse-august-2017
It works quite well on my desktop, but on my Nexus 5x it does not work and seems like the finally few collage calls are not happening. I've spent too long on this now so opening this up to see if I can get some help. Thanks everyone!
Whooooo I figured it out!
Was getting this issue which I'm still unsure about what it means
[Violation] Forced reflow while executing JavaScript took 43ms
Moved this into the callback that happens only once all images are loaded
$(window).bind('resize', function() {
resetCollage(); // resize all collages
});
For some reason it was getting called early even if the browser never resized causing collage to get called when no elements existed yet.
If anyone has any informative input as to why I was getting this js violation would be great to know so I can make a better fix but for now this works :):):)
I want to repeat the animation of the myDoughnut animation every 5 seconds. At the moment it only animates on page load.
<script>
var doughnutData = [
{
value: 80,
color:"#74cfae"
},
{
value : 20,
color : "#3c3c3c"
}
];
var myDoughnut = new Chart(document.getElementById("CSS3").getContext("2d")).Doughnut(doughnutData);
</script>
I have tried using
setInterval("Chart();", 500);
I am still learning Javascript so a little unsure as to if I am referencing the correct function and where to place the setInterval code.
The animation can be viewed at the bottom of this website: http://www.chartjs.org/
Many thanks for any guidance and direction!
You should pass a proper function to setInterval.
I looked for a way to replay the animation of Chart object but i couldn't find any directive in ChartJS documentation.
Here is how you function should look like:
setInterval(function () {
myDoughnut = new Chart(document.getElementById("CSS3").getContext("2d")).Doughnut(doughnutData);
}, 2000);
Here is working JSFiddle.
setInterval takes a function as parameter.
Try:
setInterval(function(){ Chart(); }, 500);
I am making a simple slider that works by changing the src attribute of an img tag and the attributes of anchor tags. This is what I have come up with so far:
(function($){
var slides = [
'http://placehold.it/801x350',
'http://placehold.it/802x350',
'http://placehold.it/803x350'
],
titles = [
'Title 1',
'Title 2',
'Title 3'
],
links = [
'http://test1.com',
'http://test2.com',
'http://test3.com'
],
image = $('#stretch-img'),
anchor = $('.featured-title>h2>a');
var interval = setInterval(function() {
image.attr('src', slides[0]);
anchor.attr('href', links[0]);
anchor.html(titles[0]);
}, 3000);
})(jQuery);
I want the interval to loop through the arrays continuously with a simple fade effect. What can be the best way to do this or any way to do this really, coz I've got none.
Thanks!
I appreciate all the help.
To loop through your array you can set a current-position-variable and a variable that saves the length of the array:
var current = 0,
length = slides.length,
interval = setInterval(function() {
image.attr('src', slides[current]);
anchor.attr('href', links[current]).html(titles[current]);
current++;
if (current >= length) {
current = 0;
}
}, 3000);
Then to fade you can fade-out, change the source, then fade-back-in:
image.fadeOut(500, function () {
image.attr('src', slides[current]).fadeIn(500);
anchor.attr('href', links[current]).html(titles[current]);
current++;
if (current >= length) {
current = 0;
}
});
This can lead to the image not quite being loaded when the fadeIn(500) kicks-in, which can be fixed by using an event handler attached to the load event for the image element:
var image = $('#stretch-img').on('load', function () {
image.fadeIn(500);
});
Then you can remove the fadeIn(500) from the interval function since it will fire when the image has loaded. The load event will fire whenever the source of the image changes and the new source finishes loading.
Note that .on() is new in jQuery 1.7 and is the same as .bind() in this case.