
Full screen pages are always a great way to catch your audience attention. Do you want to make a presentation that sharpens your ideas and articulates your points? Do you want to design a portfolio page that showcases your awesome works? Focus, a full-screen scrolling website component offers just that. Learn how we built Focus, and the functionality behind it.
Focus mainly functions on the following variables:
We start with the initializing functions to set some primitive values.
It's used to initialize the side navigation dots, that show a list of dots, one for each slide, with an indicator to the current active slide.
initDots() {
this.fragment = document.createDocumentFragment();
const focusNav = document.createElement('ul');
focusNav.classList.add('focus-nav');
focusNav.insertAdjacentHTML('afterbeing', '<li><a class="focus-dit"></a></li>'.repeat(this.sections.length));
this.fragment.appendChild(focusNav);
document.body.appendChild(this.fragment);
this.dots = Array.from(document.querySelectorAll('.focus-dot'));
this.dots.forEach((dot, index) => {
dot.addEventListener('click', () => {
this.goToSection(index);
}, false);
});
}
A function that makes Focus keyboard-enabled, allowing the user to navigate through slides, both horizontally and vertically, using arrow buttons.
initKeyboard() {
window.addEventListener('keydown', (event) => {
if(event.defaultPrevented) {
return;
}
switch(event.key) {
case 'ArrowDown':
this.nextSection();
break;
case 'ArrowUp':
this.previousSection();
break;
case 'ArrowRight':
this.slideRight();
break;
case 'ArrowLeft':
this.slideLeft();
break;
default:
return;
}
// Cancel the default action to avoid it being handled twice
event.preventDefault();
}, true)
}
This one handles the mouse wheel for scrolling through different slides.
initScroll() {
function handler(e) {
event.preventDefault();
// get scrolling value
const value = e.wheelDelta || -e.deltaY || -e.detail;
//get scrolling direction
const delta = Math.max(-1, Math.min(1, value));
if(this.scrollingValues.length < 99) {
this.scrollingValues.shift();
}
this.scrollingValues.push(Math.abs(value));
const scrollingStart = getAverage(this.scrollingValues, 50);
const scrollingEnd = getAverage(this.scrollingValues, 10);
if(scrollingEnd < scrollingStart) return;
if(delta === 1) {
this.previousSection();
return false;
}
if(delta === -1) {
this.nextSection();
// Cancel default browser behavior
return false;
}
}
window.addEventListener('mousewheel', handler.bind(this), false);
// firefox
window.addEventListener('DOMMouseScroll', handler.bind(this), false);
}
Those are two methods that return the array of slides, and their length. They come in handy in navigation methods.
It returns an array of slides.
getSlides() {
return this.sections.map((section) => {
return Array.from(section.querySelectorAll('.slide'));
});
}
It returns the length of the array of slides.
getSlidesCount() {
return this.sections.map((section) => {
return Array.from(section.querySelectorAll('.slide')).length;
})
}
Here we define the methods that are responsible for actually navigating through different slides and sections.
takes us to the next section, vertically.
nextSection() {
if(this.currentSection >= (this.sections.length - 1)) return;
this.goToSection(this.currentSection + 1);
}
It takes us to the previous section.
previousSection() {
if(this.currentSection <= 0) return;
this.goToSection(this.currentSection - 1);
}
This method takes an index as its argument, and navigates the user to the slide specified by that index.
goToSection(index) {
if(this.isSliding) return;
this.isSliding = true;
this.el.style.transform = `translate3d(0, -${index * window.innerHeight}px, 0)`;
this.sections[this.currentSection].classList.remove('is-active');
this.dots[this.currentSection].classList.remove('is-active');
this.currentSection = index;
this.sections[this.currentSection].classList.add('is-active');
this.dots[this.currentSection].classList.add('is-active');
setTimeout(() => {
this.isSliding = false;
}, 500);
}
It navigates to the next slide to the right.
slideRight() {
const currentSlideCount = this.slidesCount[this.currentSection];
const currentSlide = this.currentSlides[this.currentSection];
if(currentSlide < currentSlideCount - 1) {
this.goToSlide(currentSlide + 1)
}
}
It navigates to the next slide to the left.
slideLeft() {
const currentSlide = this.currentSlides[this.currentSection];
if(currentSlide > 0) {
this.goToSlide(currentSlide - 1);
}
}
It navigates to a certain horizontal slide, specified by its index argument.
goToSlide(index) {
const currentSlideCount = this.slidesCount[this.currentSection];
if(currentSlideCount === 0) return;
if(this.activeSlide) this.activeSlide.classList.remove('is-acitve');
this.activeSlide = this.slides[this.currentSection][index];
this.activeSlide.classList.add('is-active');
this.currentSlides[this.currentSection] = index;
this.sections[this.currentSection].style.,marginLeft = `-${index * 100}%`
}
You’ve probably noticed some methods that were not defined, those reusable methods were put in a different file, for better organization of code.
It's a simple method for selecting a DOM element.
export function select(element) {
if(typeof element === 'string') {
return document.querySelector(element);
}
return element;
}
It calculates and returns the mathematical average of an array of values.
export function getAverage(array, length) {
let sum = 0;
const elements = array.slice(Math.max(array.length - length, 1));
elements.forEach((value) => sum = sum + value);
return Math.ceil(sum / length);
}
It's a method that returns an array with certain length and fills it with the value argument passed to it.
export function getArray(length, value) {
return new Array(length).fill(value);
}
You can download Focus, and go through the whole repository on Github.