【JS】公共鼠标滚动事件(从下进入,从上进入),可vue做指令使用

unilateralScroll 方法是动画主事件
enterFromBelow 方法是鼠标从上向下滚动事件
enterFromAbove 方法是鼠标从下向上滚动事件
Action[“事件名”] 是使用自定事件

// index.js 文件

/** 从下进入事件 -- FromLeftToRight 默认动画 */
const enterFromBelow = (el, event) => Action[event && event.length ? event[0] : 'FromLeftToRight'](el);

/** 从上进入事件 -- FromRightToLeft 默认动画 */
const enterFromAbove = (el, event) => Action[event && event.length ? event[1] : 'FromRightToLeft'](el);

/** 鼠标滚动事件 */
export const unilateralScroll = (el, event) => {
    if (event.value && event.value.length != 0 && event.value.length != 2) throw new Error('Event value must be an array with two elements or without any value');
    if (event.value && event.value.length == 2) {
        if (Action[event.value[0]] == undefined) throw new Error(event.value[0] + ' Action must be a valid method action name');
        if (Action[event.value[1]] == undefined) throw new Error(event.value[1] + ' Action must be a valid method action name');
    }
    /** 进入方式 0:未进入 1:进入 2:离开 */
    let way = 0;
    /** 定义滚动条滚动方向 */
    let scrollType = true;
    /** 获取初始滚动位置 */
    let scrollPos = window.scrollY || document.documentElement.scrollTop;
    /** 监听滚动条事件 */
    window.addEventListener("scroll", function () {
        /** 确定新的滚动位置 */
        const newScrollPos = window.scrollY || document.documentElement.scrollTop;
        newScrollPos > scrollPos ? scrollType = true : scrollType = false;
        /** 更新滚动位置 */
        scrollPos = newScrollPos;
        /** 不同方向进入可视区域 */
        if (scrollType && way != 0) way == 1 ? enterFromBelow(el, event.value) : '离开事件';
        else if (!scrollType && way != 0) way == 1 ? enterFromAbove(el, event.value) : '离开事件';
    });

    /** 观察元素 */
    const callback = (entries) => entries.forEach((entry) => entry.isIntersecting ? way = 1 : way = 2);

    /** 创建一个观察者 */
    new IntersectionObserver(callback, { threshold: 0 }).observe(el);
}

这里是默认事件处理,可自定义内容事件

// action.js 文件

export default class Action {
    /** 从下方进入可视窗口后,左边先滚动,右边固定,
     * 左边滚动结束,固定左边,右边开始滚动,
     * 到达盒子底边,左右固定在盒子底边 
     */
    static FromLeftToRight = (el) => {
        if (el.children.length < 2) throw new Error('Element must have at least two children');
        let dom1 = el.children[0];
        let dom2 = el.children[1];
        el.style.height = dom1.offsetHeight + dom2.offsetHeight - window.innerHeight + 20 + "px";
        /** 判断父元素距离顶部可视窗口的距离是否小于等于0 */
        if (el.getBoundingClientRect().top <= 0 && el.getBoundingClientRect().top >= -500) {
            dom1.style.top = 0;
            dom2.style.top = 0;
            dom2.style.position = "fixed";
        }

        let bottom = window.innerHeight - dom1.getBoundingClientRect().bottom;
        /** 判断左侧元素距离底部可视窗口的距离是否大于等于0 */
        if (bottom >= 0 && bottom < 500) {
            dom1.style.top = '';
            dom1.style.bottom = 0;
            dom1.style.position = "fixed";
            dom2.style.position = "absolute";
            dom2.style.top = dom1.offsetHeight - window.innerHeight + 20 + "px";
        }

        let pb = window.innerHeight - el.getBoundingClientRect().bottom;
        /** 判断父元素距离底部可视区域的距离 */
        if (pb >= 0 && pb < 500) {
            dom1.style.position = "absolute";
        }
    };

    /** 从上方进入可视窗口后,右边先滚动,左边固定,
     * 右边滚动结束,固定右边,、左边开始滚动,
     * 到达盒子顶边,左右固定在盒子顶边 
     */
    static FromRightToLeft = (el) => {
        if (el.children.length < 2) throw new Error('Element must have at least two children');
        let dom1 = el.children[0];
        let dom2 = el.children[1];
        /** 判断父元素距离顶部可视窗口的距离是否大于等于0 */
        if (el.getBoundingClientRect().bottom >= 0 && el.getBoundingClientRect().bottom < 500) {
            dom1.style.top = '';
            dom1.style.bottom = 0;
            dom1.style.position = "absolute";
            dom2.style.top = '';
            dom2.style.bottom = 0;
            dom2.style.position = "absolute";
        }

        let pb = window.innerHeight - el.getBoundingClientRect().bottom;
        /** 判断父元素距离底部可视区域的距离 */
        if (pb <= 0 && pb > -500) {
            dom1.style.top = "";
            dom1.style.bottom = 0;
            dom1.style.position = "fixed";
        }

        let top = dom2.getBoundingClientRect().top;
        /** 判断右侧元素距离顶部可视窗口的距离是否大于等于0 */
        if (top >= 0 && top < 500) {
            dom1.style.top = 0;
            dom1.style.bottom = '';
            dom1.style.position = "absolute";
            dom2.style.top = 0;
            dom2.style.position = "fixed";
        }
        /** 判断父元素距离顶部可视窗口的距离是否小于等于0 */
        let ct = el.getBoundingClientRect().top;
        if (ct >= 0 && ct < 500) {
            dom2.style.top = 0;
            dom2.style.position = "absolute";
        }
    };
	
	// 自定义事件
	static “事件名” = () => {};
}

这里通过 vue 指令,在 vue 中使用。

// main.js 文件

import Vue from 'vue'
import App from './App.vue'
import router from './router'

import { unilateralScroll } from "./utils/index";
Vue.config.productionTip = false;


// 设置指令, binding, vnode
Vue.directive('unilateralScroll', { inserted(el, binding) { unilateralScroll(el, binding) }});

new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app');

// app.vue 文件

<template>
    <div id="app">
        <div class="box"></div>
		
		<!-- v-unilateralScroll="['从上向下滚动事件', '从下向上滚动事件']" -->
		<div class="container" v-unilateralScroll>
			<div class="c1">
				<div>···内容1</div>
			</div>
			<div class="c2">
				<div>···内容2</div>
			</div>
		</div>

		<div class="flooter"></div>
    </div>
</template>

<style lang="scss">
* {
    margin: 0;
    padding: 0;
}

html,
body {
    width: 100%;
    height: 100%;
    box-sizing: border-box;
}
body {
    overflow-y: auto;
}
.box {
    width: 100%;
    height: 120vh;
    background-color: #b1ffb1;
}
.container {
    width: 100%;
    overflow: hidden;
    position: relative;
    background-color: #4787e7b9;
}

.c1 {
    left: 0;
    width: 50%;
    position: absolute;
    background-color: #cf7bcf;
}
.c2 {
    right: 0;
    width: 50%;
    position: absolute;
    background-color: #cfad7b;
}

.flooter {
    width: 100%;
    height: 130vh;
    overflow: hidden;
    background-color: black;
}
</style>

这里展示vue实现视频

左右分屏滚动

> html 版本

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端小袁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值