slideshow met div's dmv scriptaculous

Gepubliceerd op: 23.I.2006 10:03 CET
Categorie: javascript

Geïnspireerd door een post bij code snippets heb ik met een kopje koffie zitten klungelen met javascript. Ik wilde graag een OO versie en daarmee dus de mogelijkheid om meerdere slideshows gemakkelijk op een pagina te kunnen plaatsen. En, in tegenstelling tot de inspiratie bron wilde ik dat de foto’s inelkaar over zouden gaan. Het resultaat:

Maar hoe werkt het?

Net als de post van Peter is mijn code afhankelijk van prototype.js en effect.js van script.aculo.us. In plaats van Element.Fade en Element.Appear af te wisselen heb ik alle afbeeldingen opgestapeld (dmv z-index), laat ik de bovenste verdwijnen (met Element.Fade) en stop ik afbeeldingen die verdwenen zijn onder op.

De HTML is simpel, een div met wat “slide” @div@’s erin:

<div id="slideshow">
  <div class="slide">
    <img src="kokmeeuwen.jpg"/>
  </div>
  <div class="slide">
    <img src="binti.jpg"/>
  </div>
  <div class="slide">
    <img src="stoptrein.jpg"/>
  </div>
</div>

Met CSS worden de “slides” overelkaar heen geplaatst:

<style type="text/css">
  #slideshow {
    position: relative;
    width: 240px;
    height: 180px;
  }
  #slideshow div {
    position: absolute;
    top: 0;
    left: 0;
  }
</style>

Door middel van JavaScript krijgen de “slides” allemaal een andere z-index:

<script type="text/javascript">
  function Slideshow(slideshow, timeout) {
    this.slides = [];
    var nl = $(slideshow).getElementsByTagName('div');
    for (var i = 0; i < nl.length; i++) {
      if (Element.hasClassName(nl[i], 'slide')) {
        this.slides.push(nl[i]);
      }
    }
    for (var i = 0; i < this.slides.length; i++) {
      this.slides[i].style.zIndex = this.slides.length - i;
    }

Dan wordt de next functie getimed:

    this.timeout = timeout;
    this.current = 0;

    Element.show(slideshow);
    setTimeout((function(){this.next();}).bind(this), this.timeout + 850);
  }

Deze next functie schuift alle de z-index door:

  Slideshow.prototype = {
    next: function() {
      for (var i = 0; i < this.slides.length; i++) {
        var slide = this.slides[(this.current + i) % this.slides.length];
        slide.style.zIndex = this.slides.length - i;
      }

Laat dan de bovenste afbeelding zachtjes verdwijnen:

      Effect.Fade(this.slides[this.current], {

Gooit hem daarna onderop:

        afterFinish: function(effect) {
          effect.element.style.zIndex = 0;
          Element.show(effect.element);
          Element.setOpacity(effect.element, 1);
        }
      });

En zorgt dat de volgde “slide” getimed staan:

      this.current = (this.current + 1) % this.slides.length;
      setTimeout((function(){this.next();}).bind(this), this.timeout + 850);
    }
  }

En zo wordt nu een dia-presentatie geregistreerd:

  new Slideshow('slideshow', 3000);
</script>

Voor mij werkt dit onder Internet Explorer, Firefox, Safari, Omniweb en Opera (hoewel deze niet fade). Probeer het zelf, download de volgden javascripts en hang ze in een stukkie HTML zoals boven beschreven:

Tom @ 2 maanden later

Safari doet het ook!

Erwin @ 3 maanden later

Je script bevat een bug als er maar 2 afbeeldingen zijn, dan zijn namelijk tijdelijk de z-indexen van beide plaatjes 0 en knippert het geheel even. Dit is op te lossen met de volgende code.


for (var i = 0; i < this.slides.length; i++) {
      var slide = this.slides[(this.current + i) % this.slides.length];
      slide.style.zIndex = this.slides.length + 1 - i;
}

Dus: z-index 1 hoger dan de lengte en alle elementen veranderen zodat er nooit 2 keer 0 is.

Remco @ 3 maanden later

Dank! Het probleem zat hem in i < this.slides.length - 1 er werd steeds een slide gemist waardoor er na een hele ronde 2 elementen z-index 0 hadden. Ik ga meteen het artikel aanpassen en slideshow.js.

Eric @ 4 maanden later

This doesn’t work correctly if all images do not have the same dimensions. Is there a way around that?

Remco @ 4 maanden later

Sure. Give the “slide” @div@’s the maximum size and give them an opaque background. For instance; if you have landscape and portret pictures of sizes 400×300 and 300×400, then your CSS might look like:


#slideshow {
  position: relative;
  width: 400px;
  height: 400px;
  background: white;
}
div.slide {
  width: 400px;
  height: 400px;
  background: white;
}

Checkout the site for my newborn son for an example.

Stard @ 6 maanden later

Nice effect :)

Anoniempje @ 7 maanden later

Hi,
It’s a very nice work…
I congratulate you.
Did you solve the problem at Safari and Opera browsers ?
Best regards.
Yusuf Akyol
Istanbul / Turkey

newbie @ 8 maanden later

hoi,

ik vind het wel een mooi ding dat je daar hebt staan.
het probleem is, ik weet niet hoe ik dit in mijn joomla cms moet plaatsen.
kan iemand mij uitleggen?

hartelijk dank

Granger @ 9 maanden later

Thank you.
Greetings from Mexico.

alsi@quicknet.nl @ 11 maanden later

Hallo,
Ik ben bezig met mijn site en zou 10 slideshows op 1 pagina willen zetten, is dat mogelijk? En hoe plaats ik die bij de juiste afbeelding? Misschien iets te hoog gegrepen, maar ik wil het toch proberen….
Alvast bedankt! Groeten,Alet

Seppie @ ongeveer 1 jaar later

Remco bedankt voor je hulp!
http://www.primaveraquint.nl

groetjes
Seppie

Anoniempje @ ongeveer 1 jaar later

bedankt