Mitch
Mitch

Reputation: 1173

Slide show with different slide times

EDIT:

I'm currently working with the anwser of Louys Patrice Besette, and i'm almost done with putting all the slides in. However sometimes when i refresh the page. The video becomes black and does not play. And this goes on for all the next upcomming videos. And then a few refreshes later it works again.

Why does this happen?

I get this error in the console when the error (black videos) happen: index.html:1 Uncaught (in promise) DOMException: The play() request was interrupted by a call to pause().

Also one more question. Is the a way to make like a waiting line for the things to be loaded? I'm on about 60-70% now of being finished with the site. However, i notice that my laptop has to work very very very hard in order to load all the videos and images for the first time.

End of EDIT

Right now i'm trying to make a kind of slide show to display Images and Videos one by one.

My code so far looks like this:

Html:

<div id="div1" class="hidden">
    <video autoplay>
        <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
    </video>
</div>
<div id="div2" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
<div id="div3" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
<div id="div4" class="hidden">
    <video autoplay>
        <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
    </video>
</div>
<div id="div5" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
<div id="div6" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
<div id="div7" class="hidden">
    <video autoplay>
        <source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
    </video>
</div>
<div id="div8" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
<div id="div9" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>

This code collects 9 "slides". 3 videos and 7 images. I want to show these one by one on the web page (each displaying for a different time).

I do this by:

Script:

<script type="text/javascript">
    //show first slide
    function showIt() {
        document.getElementById("div1").className = "shown";
    }
    setTimeout("showIt()", 0000);

    //Start fading first slide
    function hideIt() {
        document.getElementById("div1").className = "fade";
    }
    setTimeout("hideIt()", 16000);

    //Start showing 2nd slide
    function showIt2() {
        document.getElementById("div2").className = "shown";
    }
    setTimeout("showIt2()", 16500);

    //Remove the first slide
    function removeIt() {
        document.getElementById("div1").className = "hidden";
    }
    setTimeout("removeIt()", 17000);

    //Start fading second slide
    function hideIt2() {
        document.getElementById("div2").className = "fade";
    }
    setTimeout("hideIt2()", 27000);

    //Remove the second slide
    function removeIt2() {
        document.getElementById("div1").className = "hidden";
    }
    setTimeout("removeIt2()", 28000);

    //When end is reached, reload page
    setTimeout(window.location.reload.bind(window.location), 28000);
</script>

And the Css:

img {
    max-width: 78%;
    position:absolute;
    margin-left: 10.5%;
}

video {
    max-width: 78%;
    position:absolute;
    margin-left: 10.5%;
}

.hidden{
    visibility: hidden;
}

.fade{
    -webkit-animation: fadeout 1s; /* Safari, Chrome and Opera > 12.1 */
       -moz-animation: fadeout 1s; /* Firefox < 16 */
        -ms-animation: fadeout 1s; /* Internet Explorer */
         -o-animation: fadeout 1s; /* Opera < 12.1 */
            animation: fadeout 1s;
}

@keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Firefox < 16 */
@-moz-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Internet Explorer */
@-ms-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Opera < 12.1 */
@-o-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}


.shown{
    -webkit-animation: fadein 1s; /* Safari, Chrome and Opera > 12.1 */
       -moz-animation: fadein 1s; /* Firefox < 16 */
        -ms-animation: fadein 1s; /* Internet Explorer */
         -o-animation: fadein 1s; /* Opera < 12.1 */
            animation: fadein 1s;
}

@keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Firefox < 16 */
@-moz-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Internet Explorer */
@-ms-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Opera < 12.1 */
@-o-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

As you can see, i'm only displaying 2 slides right now. while i have 9 ready. (in total i have got 40+). If i keep going the way i go right now. i will get tons and tons of code...

Question:

Is there a way to make this more compact/smaller?

I searched the internet for slideshows and find things. However i want to set the time to be seen for each slide. Since some slides need to be displayed 20 seconds and other 10.

Also i made a fiddle, but it is not working in there... https://jsfiddle.net/a10yarxj/

Upvotes: 1

Views: 2276

Answers (4)

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33933

I understand, in your question, that you want to have full control over the slideshow timings.
The display time...
And I added the possibility for fade in/out times to be different aswell.

The slides will contain image or video, wich may be longer than your timing... Letting the sound continue while other slides are displayed.

I suppose that the image/video order may (and will!) change over time...
And that the slide amount is variable.

So I made this small script that you will not have to modify each time you change the slideshow content.
All params are provided in the HTML:

  • data-timing (time in seconds)
  • data-fadein (time in seconds)
  • data-fadeout (time in seconds)
  • data-videopause (true/false)

For the 3 first parameters, if the value is missing, default time is applyed and a «NOTICE» is shown in console.log().
For the last, if it is missing, it will be considered false.

I used jQuery .animate() instead of CSS @keyframes because the effect is easier to achieve this way, since only the opacity is affected.

The slideshow is looping... So no need for a new page load at the end.

Here it is, in the below snippet and on CodePen:

EDIT
I added a setTimeout "bugfix" on lines 8 to 12 and on line 54.
As per below comments, it appears that a setTimeout may remain in DOM on page refresh [F5].
To prevent that, we clear it if it exist.

var slides = $(".slide");
var lastSlideIndex = slides.length-1;
var currentSlideIndex = 0;
var defaultTiming = 1000;
var defaultFadeInTime = 1000;
var defaultFadeOutTime = 1000;

// Prevents a setTimeout to remain in browser cache on page refresh.
if (typeof slideTimer !== 'undefined') {
  clearTimeout(slideTimer);
}
var slideTimer;

// Show slide function
function showSlide() {
    
	var thisSlide = slides.eq(currentSlideIndex);
	
	// Delays
	var timing = parseFloat(thisSlide.attr("data-timing")) * 1000;	// Transform seconds in milliseconds
	if(isNaN(timing)){timing=defaultTiming; console.log("NOTICE: ----------- data-timing is missing, using default.");}
	var fadeInTime = parseFloat(thisSlide.attr("data-fadein")) * 1000;
	if(isNaN(fadeInTime)){fadeInTime=defaultFadeInTime; console.log("NOTICE: ----------- data-fadein is missing, using default.");}
	var fadeOutTime = parseFloat(thisSlide.attr("data-fadeout")) * 1000;
	if(isNaN(fadeOutTime)){fadeOutTime=defaultFadeOutTime; console.log("NOTICE: ----------- data-fadeout is missing, using default.");}
	
    console.log("Slide: "+currentSlideIndex+":\n Display time: "+timing+" millisec.\n Fadein: "+fadeInTime+" millisec.\n Fadeout: "+fadeOutTime+" millisec.");
    thisSlide.animate({"opacity":1},fadeInTime);
    
	// If this slide contains a video
	if(slides.eq(currentSlideIndex).find("video").length > 0){
		
		// Prevents more than 1 video to play at the same time
		$("video").each(function(){
			console.log("All video paused.")
			$(this)[0].pause();
		});
		
		// Play this video from the start
		var thisVideo = slides.eq(currentSlideIndex).find("video")[0];
		thisVideo.currentTime = 0;
		console.log("Video playing.");
		thisVideo.play()
	}
	
    // Prepare for next slide
    currentSlideIndex++;
	
	// Reset to slide 0 if last was reached
    if(currentSlideIndex>lastSlideIndex){
        currentSlideIndex=0;
    }
    
    slideTimer = setTimeout(function(){
        // Fade out previous slide
		var previousSlideIndex = currentSlideIndex-1;
		
		
		// If previous was last slide
		if(previousSlideIndex == -1){
			previousSlideIndex = lastSlideIndex;
		}
		
		// If previous slide was set to pause
		if(slides.eq(previousSlideIndex).attr("data-videopause")=="true"){
			console.log("Video has been paused.");
			slides.eq(previousSlideIndex).find("video")[0].pause();
		}
		
		slides.eq(previousSlideIndex).animate({"opacity":0},fadeOutTime);
        showSlide();
    }, timing);
}

// Init
showSlide();
img {
    max-width: 78%;
    position:absolute;
    margin-left: 10.5%;
}

video {
    max-width: 78%;
    position:absolute;
    margin-left: 10.5%;
}

.slide{
    opacity:0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slide" data-timing=4 data-fadein=0.5 data-fadeout=1 data-videopause=false>
    <video>
        <source src="https://www.bessetteweb.com/SO/39920322/video-1.mp4" type="video/mp4">
    </video>
</div>
<div class="slide" data-timing=4 data-fadein=0.5 data-fadeout=0.5><img src="https://upload.wikimedia.org/wikipedia/commons/3/30/Fritz_von_Wille_0071.jpg" /></div>
<div class="slide" data-timing=2 data-fadein=0.5 data-fadeout=1><img src="https://upload.wikimedia.org/wikipedia/commons/f/f3/Truncated_View_of_the_Broekzijdse_Molen_on_the_Gein_by_Piet_Mondrian.jpg" /></div>
<div class="slide" data-timing=6 data-fadein=0.5 data-fadeout=2 data-videopause=true>
    <video>
        <source src="https://www.bessetteweb.com/SO/39920322/video-2.mp4" type="video/mp4">
    </video>
</div>
<div class="slide" data-timing=2 data-fadein=0.5 data-fadeout=3><img src="https://upload.wikimedia.org/wikipedia/commons/0/01/Walter_Leistikow_-_Liebesinsel_(1905).jpg" /></div>
<div class="slide" data-timing=4 data-fadein=0.5 data-fadeout=1><img src="https://upload.wikimedia.org/wikipedia/commons/e/ee/%D0%92%D0%B5%D1%87%D0%B0%D1%80_%D0%90._%D0%93%D0%B0%D1%80%D0%B0%D1%9E%D1%81%D0%BA%D1%96.jpg" /></div>
<div class="slide" data-timing=6 data-fadein=0.5 data-fadeout=0.5 data-videopause=true>
    <video>
        <source src="https://www.bessetteweb.com/SO/39920322/video-3.mp4" type="video/mp4">
    </video>
</div>
<div class="slide" data-timing=3 data-fadein=0.5 data-fadeout=1><img src="https://upload.wikimedia.org/wikipedia/commons/8/88/Morris21.jpg" /></div>
<div class="slide" data-timing=2 data-fadein=0.5 data-fadeout=2><img src="https://upload.wikimedia.org/wikipedia/commons/3/30/Fritz_von_Wille_0071.jpg" /></div>



<!-- ---------------------------
Copyright issues:
Images used here are labelled for reuse and videos were made by me for this example.

The Google image search I used: https://www.google.ca/search?q=paysage&espv=2&biw=1600&bih=1110&tbs=islt:svga,isz:ex,iszw:500,iszh:400&tbm=isch&source=lnt#tbs=islt:svga%2Cisz:ex%2Ciszw:500%2Ciszh:400%2Csur:fc&tbm=isch&q=landscape+-flickr&imgrc=pqMMLvfhjtbSuM%3A

 -->

Upvotes: 2

P. Frank
P. Frank

Reputation: 5745

I have add only one function call with timeout. You can add time of your slide directly in table. Please try

var totalSlide =[0,2000,2000,2000,2000,2000,2000,2000,2000];
var slideStart = 0;
showIt();

function showIt() {
  setTimeout(function(){
    var idNow = document.getElementById("div"+(slideStart+1));
    idNow.className = "shown";
    
    slideStart++;
    
    setTimeout(function(){
      idNow.className = "fade";
      setTimeout(function(){idNow.className = "hidden";},500)
    	if(slideStart == totalSlide.length-1 ){
          slideStart = 0;
        }
        showIt()
    },totalSlide[slideStart])
  }, 0)
}
img {
	max-width: 78%;
	position:absolute;
	margin-left: 10.5%;
}

video {
	max-width: 78%;
	position:absolute;
	margin-left: 10.5%;
}

.hidden{
	visibility: hidden;
}

.fade{
	-webkit-animation: fadeout 1s; /* Safari, Chrome and Opera > 12.1 */
       -moz-animation: fadeout 1s; /* Firefox < 16 */
        -ms-animation: fadeout 1s; /* Internet Explorer */
         -o-animation: fadeout 1s; /* Opera < 12.1 */
            animation: fadeout 1s;
}

@keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Firefox < 16 */
@-moz-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Internet Explorer */
@-ms-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}

/* Opera < 12.1 */
@-o-keyframes fadeout {
    from { opacity: 1; }
    to   { opacity: 0; }
}


.shown{
	-webkit-animation: fadein 1s; /* Safari, Chrome and Opera > 12.1 */
       -moz-animation: fadein 1s; /* Firefox < 16 */
        -ms-animation: fadein 1s; /* Internet Explorer */
         -o-animation: fadein 1s; /* Opera < 12.1 */
            animation: fadein 1s;
}

@keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Firefox < 16 */
@-moz-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Safari, Chrome and Opera > 12.1 */
@-webkit-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Internet Explorer */
@-ms-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Opera < 12.1 */
@-o-keyframes fadein {
    from { opacity: 0; }
    to   { opacity: 1; }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1" class="hidden">
			<video autoplay>
				<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
			</video>
		</div>
		<div id="div2" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
		<div id="div3" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
		<div id="div4" class="hidden">
			<video autoplay>
				<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
			</video>
		</div>
		<div id="div5" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
		<div id="div6" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
		<div id="div7" class="hidden">
			<video autoplay>
				<source src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" type="video/mp4">
			</video>
		</div>
		<div id="div8" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>
		<div id="div9" class="hidden"><img src="http://www.w3schools.com/css/trolltunga.jpg" /></div>

UPDATE

var video = $(".div7").find("video");

function playVid() {
    video .play();
}

function pauseVid() {
    video .pause();
}

Upvotes: 2

Artur Filipiak
Artur Filipiak

Reputation: 9157

UPDATE

[...] However i want to set the time to be seen for each slide. Since some slides need to be displayed 20 seconds and other 10.

You can use data attribute to store duration time of each slide:

<div id="div1" data-duration="3500" class="hidden">
    <img src="..." />
</div>

Then (using jQuery), you could combine setTimeout's for each action (each class toggle). Use class instead of id:

var durations = 0;
var play = function(){
  var that = $(this), i = that.index(), duration = that.data('duration'), l = $('.hidden').length;
  setTimeout(function(){
    that.toggleClass('hidden shown');
    setTimeout(function(){
      that.toggleClass('shown fade');
      setTimeout(function(){
        that.toggleClass('fade hidden');
        if(i+1 === l){
          // No need to reload page. If you want to loop over again, uncomment this:
          // $('.hidden').each(play);
        }
      }, 500);
    }, duration);
  }, durations);
  durations += duration+500;
}

$('.hidden').each(play);

JSFiddle

Upvotes: 0

Pat
Pat

Reputation: 5911

Yes, there is. From a pure javascript perspective, this is a quick solution but it can be improved further (that can be your job):

(function() {
    var currentDivNumber = 1;
    function removeIt() {
        document.getElementById("div"+currentDivNumber).className = "hidden";
        currentDivNumber++;
        if ( currentDivNumber > maxSlides) {
            currentDivNumber=1;
        }
        setTimeout(showIt, 500);
    }

    function hideIt() {
        document.getElementById("div"+currentDivNumber).className = "fade";
        setTimeout(removeIt, 500);
    }
    function showIt() {
        document.getElementById("div"+currentDivNumber).className = "shown";
        setTimeout(hideIt, 500);
    }

    setTimeout(showIt, 16000);
})();

This is not optimal it can be further improved. Plus maybe better CSS can be used to remove additional if not all javascript?

see : https://jsfiddle.net/0mvpfthL/1/

Upvotes: 0

Related Questions