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 版本