How to Create a Slide Presentation with JavaScript
Recently a client needed a website that could be used both as a presentation tool (like a Keynote or PowerPoint presentation) and as a stand-alone website to be sent to possible investors to scroll through.
There are a lot of great libraries out there that help you mimic the functionality of a Keynote presentation. I took a look at flowtime, reveal.js, and impress.js. But, these libraries are big and seemed like overkill for what I needed to do. Also, I really wanted to see if I could build this on my own.
(If you want to jump ahead to the finished product, here’s an example of what I built along with the code on github.)
First I made my panels. I broke up the site into sections (literally — using <section></section> tags) and made each section height = 100vh. Actually, I had to make room for my fixed nav up top, so it was really height = calc(100vh - 102). Now that I had things looking the way they should, I needed to make them act the way they should.
I soon realized that my biggest challenge was to designate which section was the current panel so we could find the previous and next panels. I found this stackoverflow answer that seemed like it could be a solution. It used the jquery-visible plugin to tell if a section was in view and then found next and previous based on that. However, after the better part of a day going down that path, I realized it wouldn’t work for my needs. Before giving up, I asked another engineer if he had any idea how I could make this work (shout out, Kevin!). He said, “Why don’t you try using waypoints?” YES! Why didn’t I think of that?
Waypoints is a great library that lets you trigger a function on scroll. I could make each section have its own waypoint where it gets the class ‘currentPanel’ as soon as it’s almost to the top of the screen.
In that function, I’m looping through all the sections and assigning a waypoint to each based on its index. As you’re scrolling down, a section will get the class ‘currentPanel’ when it’s 200px from the top. On the way back up, a section would get that class as soon as it hits the nav. I’m also making sure that as the ‘currentPanel’ class is added to one section, it is removed from the section that just had it.
Now that I could find the current panel, I needed to designate next and previous panels and animate the scroll.
Now I needed that scroll to happen in response to a presentation clicker. We had this one in the office, so I connected it to my computer and console logged the keyCodes to find which it simulated. It was using 33 and 34 (page up and page down). I also added a few more keyCodes in case the client forgot his clicker and needed to use the keyboard to move through the site.
Thanks to my ‘getCurrentPanel’ function, I knew that the panel with the class ‘currentPanel’ was my current panel, and could fire my ‘findNext’ or ‘findPrev’ functions based on whether the keyCodes called for up or down movement. Yay!
On to what I call ‘fragmented’ panels. By this I mean sections that call for a halt in the movement up and down and instead move through the content inside the panel itself. We’re also looking out for a fragment-subnav if it has one. All the fragmented examples in my demo site have subnavs. They give a great visual cue that there are other fragments and lets the user easily navigate them. But a subnav is not required.
For the code in your fragmented sections to work, you need to set up your HTML with certain classes. The ‘section’ will need to get the classes ‘fragmented’ and ‘first-fragment’. The fragments within your fragmented section need to get the class ‘fragmented-part’. The subnav items should get the class ‘fragment-subnav’. And the first fragment item and first subnav item should always get the ‘active’ class.
Here’s an example of how to set up the HTML:
1234567891011121314151617
<sectionclass="fragmented first-fragment"><!-- this is a slide with fragments --><divclass="fragmented-part active"></div><divclass="fragmented-part"></div><divclass="fragmented-part"></div></section><sectionclass="fragmented first-fragment"><!-- this is a slide with fragments and a subnav--><divclass="fragment-subnav active"></div><divclass="fragment-subnav"></div><divclass="fragment-subnav"></div><divclass="fragmented-part active"></div><divclass="fragmented-part"></div><divclass="fragmented-part"></div></section>
A big thing in the fragmentedPanel function is to know when you’re reaching the end of the fragmented-parts so you can move on to the next slide. That’s why I have the ‘checkForLast’ and ‘checkForFirst’ variables. With every movement, I’m checking to see if an element exists in the next slot.
Great, now we need to update our slider function to halt movement if we see a ‘fragmented’ section.