Rotating an image as it approaches the footer: a step-by-step guide

I'm trying to add a navigation arrow on my website that will rotate to point to the top when it reaches the footer. When clicked on, it should scroll back up to the top.

The arrow already has a scrolling effect, but I need help figuring out how to make it rotate and change the scrolling effect when it reaches certain points on the website.

This is the link/arrow element in question:

<a href="footer" class="to-the-bottom">
    <i class="fa fa-arrow-circle-o-bottom"></i>
</a>

Answer №1

Here is a solution using pure JavaScript instead of JQuery, in case you do not have the JQuery library.

JSFiddle

HTML Code:

<i id="icon" class="fa fa-arrow-circle-o-bottom"></i>

JavaScript Code:

// Function to detect when scrollbar reaches the bottom of the page
var detectScrollBarBottom = function() {
  var windowHeight = (self.innerHeight) ? self.innerHeight : document.body.clientHeight; // Get window height

  // Get current vertical scrollbar position
  var scrollPosition = window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop;

  // Check if scrollbar reaches the bottom
  if (document.body.scrollHeight <= (scrollPosition + windowHeight)) {
    //alert('Bottom');
    var iconElement = document.getElementById("icon");
    iconElement.className = iconElement.className + " rotated";
  } else {
    var resetIcon = document.getElementById("icon");
    resetIcon.className = "fa fa-arrow-circle-o-bottom";        
  }
}

// Register event on scrollbar
window.onscroll = detectScrollBarBottom;

// Smooth scroll function
var smoothScrollTo = function(element, target, duration) {
    target = Math.round(target);
    duration = Math.round(duration);
    if (duration < 0) {
        return Promise.reject("bad duration");
    }
    if (duration === 0) {
        element.scrollTop = target;
        return Promise.resolve();
    }

    var startTime = Date.now();
    var endTime = startTime + duration;

    var startTop = element.scrollTop;
    var distance = target - startTop;

    // Smoothstep interpolation function
    var smoothStep = function(start, end, point) {
        if(point <= start) { return 0; }
        if(point >= end) { return 1; }
        var x = (point - start) / (end - start); 
        return x*x*(3 - 2*x);
    }

    return new Promise(function(resolve, reject) {
        var previousTop = element.scrollTop;

        var scrollFrame = function() {
            if(element.scrollTop != previousTop) {
                reject("interrupted");
                return;
            }

            var now = Date.now();
            var point = smoothStep(startTime, endTime, now);
            var frameTop = Math.round(startTop + (distance * point));
            element.scrollTop = frameTop;

            if(now >= endTime) {
                resolve();
                return;
            }

            if(element.scrollTop === previousTop && element.scrollTop !== frameTop) {
                resolve();
                return;
            }
            previousTop = element.scrollTop;

            setTimeout(scrollFrame, 0);
        }

        setTimeout(scrollFrame, 0);
    });
}

function scrollToTop() {
    var bodyElement = document.querySelector('body');
    smoothScrollTo(bodyElement, bodyElement.scrollTop - 2000, 600);
}

var myIcon = document.getElementById("icon");

myIcon.addEventListener('click', function() {
    scrollToTop();
}, false);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Internet Explorer experiencing off-screen menu loading issue

Currently, I am in the process of developing a website for my sister but facing challenges with cross-browser compatibility. The menu appears off-screen when using Internet Explorer, while it looks fine on Chrome. Despite various attempts to adjust alignme ...

Filtering data in Vue.js using JSON specifications

How can I display only the names in the data? I currently have cards filtered by cities <div v-for="item in stationCityData"> <div v-for="option in filteredCity" style="background:#eee;padding: 20px"> <!-- <div v-for="option ...

The output generated by grunt-contrib-handlebars differs from that of the handlebars npm task

Looking for some help with a problem similar to the one mentioned in this Stack Overflow question. Since that question hasn't been answered yet, I decided to create my own post. I'm currently attempting to precompile my handlebars template files ...

Adjust the field of view of the camera in ThreeJS

I'm currently working on adjusting the field of vision for a camera without having to create a new one. So far, I've successfully achieved this for the position using the following code: camera.position.set() Now, I'd like to implement a s ...

Display buttons when hovering with React

Seeking assistance with implementing functionality in a React application where buttons for editing and deleting display only when the mouse hovers over the corresponding row. Currently, the implemented code displays these buttons in all rows on hover. Sn ...

What is the best method to extend my borders to the very edge?

Struggling with table borders extending to the edge on a website using master pages and CSS stylesheet. This issue requires some troubleshooting, so any help would be appreciated. The problematic website is here. I need the border under the banner menu to ...

Combining Angular subscriptions to fetch multiple data streams

I am looking to retrieve the most recent subscription from a group of subscriptions. Whenever the value of my FormControl changes, I want to capture only the latest value after the user has finished typing. Below is the code snippet I am using - let cont ...

Choosing specific child elements based on their css attribute valuesUnique: "Targeting

I am attempting to customize the appearance of any child divs with the class 'header' that are within parent divs with a class of 'recipes'. I understand that I could simply target .category-recipes .header, but the parent div may vary ...

Tips on making a fresh form appear during the registration process

After clicking on a submit button labeled as "continue" within a form, a new form will appear for you to complete in order to continue the registration process. ...

After calling the use method in Express, utilizing the get method

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use((req, res, next) => { console.log("Executing first middlewar ...

Looping through an array asynchronously and returning the result

I'm having some trouble with an asynchronous loop. Here's the code I've been working with: let items = []; data.forEach(async item => { var newItem = new Item(data); newItem.options = await this.fetchOptions(data[" ...

ReactJS does not trigger a re-render when changes are made to CSS

I'm curious about the reason why ReactJS does not automatically reapply CSS to child components even when componentDidUpdate() is called. I conducted a small demo where adding a new box doesn't change the color of existing boxes, even though the ...

Save React code as a single HTML file

My current project involves creating one-page websites for a specific service that only accepts single inline HTML files. To make these webpages as modular as possible, I am utilizing React to create ready components. The challenge is exporting the final R ...

Creating a connection between a secondary jQuery anything slider and a distinct CSS style on a webpage

Currently, I am attempting to incorporate two anything sliders within the same webpage. My goal is to apply unique styling to each slider. Despite my efforts, I am encountering difficulties in calling upon a second style sheet without it completely overr ...

Using TypeScript generics to add constraints to function parameters within an object

My Goal: Imagine a configuration with types structured like this: type ExmapleConfig = { A: { Component: (props: { type: "a"; a: number; b: number }) => null }; B: { Component: (props: { type: "b"; a: string; c: number }) =& ...

The navigation bar extends beyond the container

First time diving into bootstrap and struggling with my items overflowing the container. Here's a snippet of my code: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equi ...

Updating React state via child components

Encountering a strange issue while working on a project, I managed to replicate it in this jsfiddle. The parent component's state seems to be affected when the child component updates its state. Any insights on what might be causing this? Here is the ...

Border at the Top and Text Alignment Problem

I am working on a basic navigation bar that includes a hover effect. .navip { float: left; text-decoration: none; font-weight: lighter; } .navip > a { display: block; color: black; text-decoration: none; font-size: 20px; ...

Does the Apps Script parser JSON.parse() incorrectly remove leading zeros from string object keys?

I am facing an issue with my Apps Script Web App where JSON data is being manipulated when I try to parse it. Specifically, keys with leading zeros are being altered (e.g "0123" becomes "123") during the JSON.parse() function call. It seems like the functi ...

Navigating through Index in #each in emberjs

Take a look at the code provided below: http://jsbin.com/atuBaXE/2/ I am attempting to access the index using {{@index}}, but it doesn't seem to be compiling. I believe that handlebars should support this feature: {{#each item in model}} {{@index} ...