trigger functions and events based on the element position on the screen

Overview

VueWaypoint

trigger functions and events based on the element position on the screen

Latest Release

Demo

Simple demo page

Open your browser console and see what's going on while scrolling up and down

Features

  • Vue 3
  • No dependencies
  • Flexible
  • Typescript
  • Battle tested
  • Customizable
  • Solid project (3+ years)
  • Supports slots

Getting started

npm

npm i vue-waypoint

Vue component

<template>
  <Waypoint @change="onChange">
    <!-- anything you want here -->
  </Waypoint>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { Waypoint } from 'vue-waypoint'

export default defineComponent({
  name: "SomeComponent",
  components: {
    Waypoint
  },
  setup() {
    const onChange = (waypointState) => {
      // Going can be:
      // IN
      // OUT
      console.log(waypointState.going);

      // Direction can be:
      // UP
      // DOWN
      // LEFT
      // RIGHT
      console.log(waypointState.direction);
    }

    return { onChange };
  }
});
</script>

Props

active

  • Can use a reactive variable
  • Can set true/false dinamically

Usage:

  • Enable the waypoint: <Waypoint :active="true" />
  • Disable the waypoint: <Waypoint :active="false" />

options

Usage:

Options example:

const options: IntersectionObserverInit = {
  root: document,
  rootMargin: '0px 0px 0px 0px',
  threshold: [0.25, 0.75]
};

tag

  • Set your preferred tag for the element

  • Defaults to div

  • Waypoint as div: <Waypoint :tag="'div'" /> --> renders --> <div class="waypoint"></div>

  • Waypoint as span: <Waypoint :tag="'span'" /> --> renders --> <span class="waypoint"></span>

  • Waypoint as p: <Waypoint :tag="'p'" /> --> renders --> <p class="waypoint"></p>

disableCssHelpers

  • Disable automatic CSS classes on the Waypoint component
  • Defaults to false

Usage:

  • Enable helpers (default): <Waypoint :disableCssHelpers="false" />
  • Disable helpers: <Waypoint :disableCssHelpers="true" />

DOM result:

  • With CSS helpers: <Waypoint /> --> renders --> <div class="waypoint going-in direction-down"></div>
  • Without CSS helpers: <Waypoint :disableCssHelpers="true" /> --> renders --> <div></div>

CSS helpers

  • Zero configuration needed
  • Useful for simple CSS animations

The component comes with three classes:

  • waypoint: set when the waypoint is ready
  • going-in, going-out: dinamically changed when the waypoint comes in and out
  • direction-up, direction-down, direction-left, direction-right: dinamically changed when the direction changes

Examples:

  • <Waypoint class="waypoint going-in direction-up" /> - the element is visible and came from bottom and is going top (natural scroll)
  • <Waypoint class="waypoint going-in direction-down" /> - the element is visible and came from top and is going up (reverse natural scroll)
  • <Waypoint class="waypoint going-out direction-up" /> - the element is not visible and came from bottom and is going top
  • <Waypoint class="waypoint going-out direction-down" /> - the element is not visible and came from top and is going up

Events

change

Emitted every time the waypoint detects a change.

<template>
  <Waypoint @change="onChange" />
</template>
const changeFunction = (waypointState) => {..}
WaypointState {
  el: Element,
  going: 'IN' | 'OUT';
  direction: 'UP' | 'DOWN' | 'LEFT' | 'RIGHT';
};

Development

  1. Fork the repository
  2. Run the project (npm i && npm run serve)
  3. Follow Conventional Commits spec for your commits
  4. Open a pull request

LEGACY: Vue2 and Nuxt version

vue-waypoint for Vue2 repository

Issues
  • vue2js and v-waypoint.js components setup

    vue2js and v-waypoint.js components setup

    i'm new on VueJS and i want install v-waypoint.js with vue2js it's doesn't work," I can not find this problem anywhere, if someone can help me, I'll be grateful, follow my html and js

    <--------- main.js -----> var App = require('./components/Example.vue') Vue.component('v-waypoint', { name:'app', template: '

    A custom component!
    ' }) new Vue({ el: '#app', render: function (createElement) { return createElement(App) } });

    <--------- index.html ----->

    <--------- Example.vue----->

    opened by talalzaki 9
  • [Vue warn]: Failed to resolve directive: waypoint

    [Vue warn]: Failed to resolve directive: waypoint

    Hi there,

    I'm fairly new to vue.js and am just trying to see if I can use this for a project that requires some animation on scroll. The vue.js CLI was used to scaffold the project. I simply included the sample code you have in your readme, but keep getting a [Vue warn]: Failed to resolve directive: waypoint in the console. Here's my component:

    <template>
      <div class="hello">
        <h1>{{ msg }}</h1>
        <div v-waypoint="{ active: true, callback: onWaypoint, options: intersectionOptions }"></div>
      </div>
    </template>
    
    <script>
    import Vue from 'vue'
    import VueWaypoint from 'vue-waypoint'
    
    // Waypoint plugin
    Vue.use(VueWaypoint)
    
    export default {
      name: 'HelloWorld',
      data () {
        return {
          msg: 'Welcome to Your Vue.js App',
          intersectionOptions: {
            root: null,
            rootMargin: '0px 0px 0px 0px',
            thresholds: [0]
          } // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
        }
      },
      methods: {
        onWaypoint ({ going, direction }) {
          // going: in, out
          // direction: top, right, bottom, left
          if (going === this.$waypointMap.GOING_IN) {
            console.log('waypoint going in!')
          }
    
          if (direction === this.$waypointMap.DIRECTION_TOP) {
            console.log('waypoint going top!')
          }
        }
      }
    }
    </script>
    

    I may just be using Vue.use() incorrectly? Please let me know if you have any tips!

    opened by juliewongbandue 8
  • Having trouble with SSR issue Vue JS

    Having trouble with SSR issue Vue JS

    I'm having trouble getting this to build when working with Vue JS/Gridsome. I've wrapped the directive component in per the Gridsome documentation and also tried to import it into the mounted hook, but still getting the ReferenceError: window is not defined

    <ClientOnly>
                <div class="hiw-card" id="hiw-deliver"
                     v-waypoint="{active: true, callback: mobScroll, options: intersectionOptions }">
                  <h4>Deliver</h4>
                  <p>A customers’ data is available via conventional REST API, as well as via a digital wallet, as
                    frequently
                    as energy is read and CO2e offset/liability calculated (continuously), and as frequently as RECs are
                    accumulated in mWh bundles.
                  </p>
                  <b-row class="justify-content-center">
                    <b-col cols="3">
                      <i class="fas fa-database fa-3x hiw-icon"></i>
                    </b-col>
                    <b-col cols="3">
                      <i class="far fa-long-arrow-alt-right fa-3x hiw-icon"></i>
                    </b-col>
                    <b-col cols="3">
                      <i class="far fa-user fa-3x hiw-icon"></i>
                    </b-col>
                  </b-row>
                </div>
              </ClientOnly>
    
    mounted () {
                window.waypoint = require('vue-waypoint')
        }
    
    bug 
    opened by lfilipos 7
  • How to trigger callback method only when it appears on the screen

    How to trigger callback method only when it appears on the screen

    Screenshot to show issue

    screenshot_5

    Source code

    <template>
      <div>
        <header>
          <nav :class="{sticky:stickyActive}">
            <div class="container">
              <div class="row">
                <img
                  v-if="!stickyActive"
                  src="../assets/logo-white.png"
                  alt="Omnifood Logo"
                  class="logo"
                >
                <img v-else src="../assets/logo.png" alt="Omnifood Logo" class="logo-black">
                <ul class="main-nav">
                  <li>
                    <a href="#">Food Delivery</a>
                  </li>
                  <li>
                    <a href="#">How It Works</a>
                  </li>
                  <li>
                    <a href="#">Our Cities</a>
                  </li>
                  <li>
                    <a href="#">Sign Up</a>
                  </li>
                </ul>
              </div>
            </div>
          </nav>
    
          <div class="hero-text">
            <h1>Goodbye junk food
              <br>Hello super healthy meals
            </h1>
            <a href="#" class="bttn bttn-full">I'm hungry</a>
            <a href="#" class="bttn bttn-ghost">Show me more</a>
          </div>
        </header>
    
        <section
          class="section-features"
          v-waypoint="{active: true, callback: onWaypoint, options: intersectionOptions}"
        >
          <div class="container">
            <div class="row">
              <h2>get food fast &mdash; not fast food</h2>
              <p
                class="long-copy"
              >Hello, we're Omnifood, your new premium food delivery service. We know you're always busy. No time for cooking. So let us take care of that, we're really good at it, we promise!</p>
            </div>
    
            <div class="row">
              <div class="col-md-3 box">
                <i class="ion-ios-infinite-outline icon-big"></i>
                <h3>Up to 365 days/year</h3>
                <p>Never cook again! We really mean that. Our subscription plans include up to 365 days/year coverage. You can also choose to order more flexibly if that's your style.</p>
              </div>
              <div class="col-md-3 box">
                <i class="ion-ios-stopwatch-outline icon-big"></i>
                <h3>Ready in 20 minutes</h3>
                <p>You're only twenty minutes away from your delicious and super healthy meals delivered right to your home. We work with the best chefs in each town to ensure that you're 100% happy.</p>
              </div>
              <div class="col-md-3 box">
                <i class="ion-ios-nutrition-outline icon-big"></i>
                <h3>100% organic</h3>
                <p>All our vegetables are fresh, organic and local. Animals are raised without added hormones or antibiotics. Good for your health, the environment, and it also tastes better!</p>
              </div>
              <div class="col-md-3 box">
                <i class="ion-ios-cart-outline icon-big"></i>
                <h3>Order anything</h3>
                <p>We don't limit your creativity, which means you can order whatever you feel like. You can also choose from our menu containing over 100 delicious meals. It's up to you!</p>
              </div>
            </div>
          </div>
        </section>
    
        <section class="section-meals">
          <ul class="meals-showcase clearfix">
            <li>
              <figure class="meal-photo">
                <img src="../assets/1.jpg" alt="1">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/2.jpg" alt="2">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/3.jpg" alt="3">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/4.jpg" alt="4">
              </figure>
            </li>
          </ul>
    
          <ul class="meals-showcase clearfix">
            <li>
              <figure class="meal-photo">
                <img src="../assets/5.jpg" alt="5">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/6.jpg" alt="6">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/7.jpg" alt="7">
              </figure>
            </li>
    
            <li>
              <figure class="meal-photo">
                <img src="../assets/8.jpg" alt="8">
              </figure>
            </li>
          </ul>
        </section>
          .......
    </template>
    
    
    
    <script>
    export default {
      data: function() {
        return {
          intersectionOptions: {
            root: null,
            rootMargin: "0px 0px 0px 0px",
            threshold: 0 // [0.25, 0.75] if you want a 25% offset!
          }, // https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
          stickyActive: false,
          mobileAppActive: false
        };
      },
      methods: {
        onWaypoint({ going, direction }) {
          if (direction === this.$waypointMap.DIRECTION_TOP) {
            this.stickyActive = true;
          } else if (direction === this.$waypointMap.DIRECTION_BOTTOM) {
            this.stickyActive = false;
          }
        },
        onMobileAppLogo({ going, direction }) {
          if (direction === this.$waypointMap.DIRECTION_TOP)
            this.mobileAppActive = true;
        }
      }
    };
    </script>
    

    I would like to trigger callback method when scroll on the desired element and also trigger it after preveious elements are not shown on the screen. How to achieve this?

    question 
    opened by erensogut543 6
  • Any plans for making this functioning with nuxt

    Any plans for making this functioning with nuxt

    Thanks for the wonderful component. I tried to use this in nuxt application even surrounded by <no-ssr> tag but I couldn't even import thew library as it throws window object reference error. It would be a really help if you can modify this to work with nuxt applications (client side)

    opened by rasikas 6
  • can not prerender it

    can not prerender it

    I am using vue-cli webpack, and when I trying to using prerender the project, it always get error.

    WARNING: JavaScript error while prerendering: /home
    ReferenceError: Can't find variable: Symbol
    
      phantomjs://code/phantom-page-render.js:26 in onError
    

    please help, thanks

    opened by iamike 5
  • [Question] How can i load a component using waypoint?

    [Question] How can i load a component using waypoint?

    Say i have three components in a parent component, i want to make those three child components load only when its visible in viewport. how can i do that?

    invalid 
    opened by emjimadhu 4
  • Version 3.4.2 wasn't published, switching to github actions

    Version 3.4.2 wasn't published, switching to github actions

    Hello! I'm currently relying on toggling the active state in the runtime, but the latest published version on npm is 3.4.1. Could you publish the latest version so it's in-line with the state on github, please?

    opened by denisgruba 4
  • knowing last callback is possible?

    knowing last callback is possible?

    how to catch last callback for elements that appear on the screen ?

    question 
    opened by yasinakbulut 4
  • Return parent element as current target?

    Return parent element as current target?

    Hi @scaccogatto

    I'm using v-waypoints in a rendered list, and am having issues trying to access the parent element that holds each v-waypoint component with the attached handler, are there any simple ways to achieve this? -

    this.$el //returns everything.
    

    here's the template markup(pug):

    section.hero-slide(v-for="(slide, index) in slides" :id="'hero-slide-' + (index + 1)")
      v-waypoint#wp-1(@waypoint-in="heroIn(index)")
      v-waypoint#wp-2(@waypoint-out="heroOut(index)")
      article.hero-articles(@click="clickReport" :id="'hero-article-' + (index + 1)")
        h2.waypoint-text {{slide.title}}
    

    and the handler:

     methods: {
        heroIn (index, e) {
          console.log('hero ' + index + ' in')
          console.log(e.currentTarget)
          console.log(this.$el)
        },
        heroOut (index) {
          console.log('hero ' + index + ' out')
        }
      }
    

    Is there support for this currently?

    question 
    opened by dblodorn 3
Releases(v3.5.0)
Owner
Marco 'Gatto' Boffo
Marco 'Gatto' Boffo
Lightweight package for highlighting menu items as you scroll the page, also scrolling to target section when item clicked. Use as a vue component/directive or in vanilla js.

navscroll-js Installation This package is available on npm. Using npm: npm install --save navscroll Using yarn: yarn add navscroll Directly include it

Honoré Nintunze 52 Aug 12, 2021
Lightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.

vue-scrollactive This component makes it simple to highlight a menu item with an 'active' class as you scroll. Highlights items with a class as you sc

Mauricio Farias Dziedzinski 494 Oct 12, 2021
vue-check-view - A plugin that checks if element is in viewport. Fast, small, has no dependencies, live demo.

Check if element is in viewport. Vue.js 2 plugin with SSR support without dependencies. DEMO Simple plugin that checks element position on the screen

Vasily Timofeev 108 Sep 23, 2021
👁 Declarative Vue component that emits an event when scrolled into view

vue-visibility-trigger Vue component that emits an event when scrolled into view Installation Install the package from npm by running $ yarn add vue-v

William Lindvall 5 May 30, 2021
A Vue component to add intersection-observer to a Vue component or HTML element.

Vue Intersect A Vue component to add intersection-observer to a Vue component or HTML element. Table of content Introduction Demo Installation Usage P

WEAREHEAVY® 306 Sep 30, 2021
⚡️ Blazing fast scrolling for any amount of data

vue-virtual-scroller Blazing fast scrolling of any amount of data | Live demo | Video demo For Vue 3 support, see here ??️ Become a Sponsor Sponsors T

Guillaume Chau 6.1k Oct 13, 2021
Lightweight and simple to use vue component that highlights menu items as you scroll the page, also scrolling to target section when clicked.

vue-scrollactive This component makes it simple to highlight a menu item with an 'active' class as you scroll. Highlights items with a class as you sc

Mauricio Farias Dziedzinski 494 Oct 12, 2021
Adds a directive that listens for click events and scrolls to elements.

vue-scrollto DEMO Scrolling to elements was never this easy! This is for vue 2.x and vue 3.x (since v2.19.0) For vue 1.x use [email protected] (note

Igor Randjelovic 1.8k Oct 13, 2021
Vue component to easily setup scroll-driven interactions (aka scrollytelling)

Vue Scrollama A Vue component to easily setup scroll-driven interactions (aka scrollytelling). Uses Scrollama under the hood. The best way to understa

Vignesh Shenoy 351 Oct 13, 2021
Handy floating scrollbar component for Vue 3

vue-handy-scroll Handy floating scrollbar component for Vue 3. Synopsis vue-handy-scroll is a component that solves the problem of scrolling lengthy c

null 6 Oct 2, 2021
Wrapper to use the awesome scrollMonitor with [email protected]

VueScrollmonitor Handle scroll events like a boss Wrapper to use the awesome scrollMonitor with [email protected] To know more : https://github.com/stutrek/sc

Alexandre Bonaventure Geissmann 44 May 7, 2021
A simple scholar management app that helps owners manage their scholars.

axiefy An open-source software that aims to help primarily on NFT Game Managers of Axie Infinity in order for them to conveniently manage and track th

Carlo Miguel Dy 2 Oct 12, 2021
A scroll to top component for Vue 3

A scroll to top component for Vue 3

Willy Hong 4 Aug 26, 2021
Bring your scroll game to the next level!

VueNextLevelScroll - Bring your scroll game to the next level! "Click to scroll" component using the modern Browser API. ?? Features Just one tiny fil

Developmint GbR 49 Mar 2, 2021
⌨️ A Safari browser extension, use keyboard control browser jumps, scrolling, switching tabs and more. support iPadOS and macOS

Support Keyboard Key Description k Scroll up j Scroll down u Fast scroll up d Fast scroll down h Scroll left l Scroll right f Highlight shift Open lin

Haojen 8 Oct 10, 2021
A vue2 component based on Iscroll

vue-virtual-infinite-scroll a vue2 component based on Iscroll, supports big data list with high performance scroll, infinite load and pull refresh. Ba

Lei Zuo 45 Mar 4, 2021
Vue.js wrapper for perfect scrollbar

vue2-perfect-scrollbar Vue.js minimalistic but powerful wrapper for perfect scrollbar Are you looking compatible version with Vue3 ? check https://git

Adam 247 Oct 11, 2021
Vue component that provides content scrolling and zooming using mouse events or two fingers pinch on a mobile devices

vue-pinch-scroll-zoom Vue component that provides content scrolling and zooming using mouse events or two fingers pinch on a mobile devices example: h

CoddiCat 4 Aug 28, 2021
A sigle-page scroll plugin based on [email protected],support for mobile and PC .

fullpage-vue A sigle-page scroll plugin based on [email protected],support for mobile and PC . 中文版 overview To achieve sigle-page scroll in mobile, support hori

abelTO 149 Sep 13, 2021