前言
一年嗖的一下儿就过去了,最近几年很流行搞年终总结,因此也研究了一下相关的内容,主要记录一下手机端与电脑端分辨通过滑动与滚轮使得整个屏幕滚动的效果
一、基础函数
不论是使用滑动还是滚轮的方式基础的转换逻辑是相通的
1、页面部分
首先完成页面部分的搭建,@mousewheel、@DOMMouseScroll主要是为了监听滚轮的事件。@touchstart、@touchend、@touchmove为触摸事件。
<template>
<div class="fullPage" ref="fullPage">
<div
class="fullPageContainer"
ref="fullPageContainer"
@mousewheel="mouseWheelHandle"
@DOMMouseScroll="mouseWheelHandle"
@touchstart="handleTouchstart"
@touchend="handleTouchend"
@touchmove="handleTouchmove"
>
<div class="section section1">1</div>
<div class="section section2">2</div>
<div class="section section3">3</div>
<div class="section section4">4</div>
</div>
</div>
</template>
<style scoped lang="scss">
.fullPage {
height: 100vh; //一定要设置,保证占满
overflow: hidden; //一定要设置,多余的先隐藏
background-color: rgb(189, 211, 186);
}
.fullPageContainer {
width: 100%;
height: 100vh;
transition: all linear 0.5s;
}
.section {
width: 100%;
height: 100vh;
background-position: center center;
background-repeat: no-repeat;
}
//下面的只是为了区分每个页面的背景颜色
.section1 {
background-color: rgb(189, 211, 186);
}
.section2 {
background-color: rgb(44, 48, 43);
}
.section3 {
background-color: rgb(116, 104, 109);
}
.section4 {
background-color: rgb(201, 202, 157);
}
</style>
2、页面切换使用的函数
全局变量
data() {
return {
fullpage: {
current: 1, // 当前的页面编号
isScrolling: false, // 是否在滚动,是为了防止滚动多页,需要通过一个变量来控制是否滚动
deltaY: 0 // 返回鼠标滚轮的垂直滚动量,保存的鼠标滚动事件的deleteY,用来判断是往下还是往上滚
},
startTime: undefined, // 记录触摸开始的时间
startX: undefined, // 记录触摸开始的X坐标,本次主要实现的是上下滑动,所以当前坐标不做强制要求
startY: undefined, // 记录触摸开始的Y坐标
};
},
实际的滚动方法
// 滚动事件
move(index) {
this.fullpage.isScrolling = true; // 为了防止滚动多页,需要通过一个变量来控制是否滚动
this.directToMove(index); //执行滚动
setTimeout(() => {
//这里的动画是1s执行完,使用setTimeout延迟1s后解锁
this.fullpage.isScrolling = false;
}, 1010);
},
// 执行滚动
directToMove(index) {
let height = this.$refs["fullPage"].clientHeight; //获取屏幕的宽度
let scrollPage = this.$refs["fullPageContainer"]; // 获取执行tarnsform的元素
let scrollHeight; // 计算滚动的告诉,是往上滚还往下滚
scrollHeight = -(index - 1) * height + "px";
scrollPage.style.transform = `translateY(${
scrollHeight})`;
this.fullpage.current = index;
}
上下切换事件
// 往下切换
next() {
let len = 4; // 页面的个数
if (this.fullpage.current + 1 <= len) {
// 如果当前页面编号+1 小于总个数,则可以执行向下滑动
this.fullpage.current += 1; // 页面+1
this.move(this.fullpage.current); // 执行切换
}
},
// 往上切换
pre() {
if (this.fullpage.current - 1 > 0) {
// 如果当前页面编号-1 大于0,则可以执行向下滑动
this.fullpage.current -= 1;// 页面+1
this.move(this.fullpage.current);// 执行切换
}
},
二、鼠标的滚轮控制实现切换
// 监听鼠标监听
mouseWheelHandle(event) {
// 添加冒泡阻止
let evt = event || window.event;
if (evt.stopPropagation) {
evt.stopPropagation();
} else {
evt.returnValue = false;
}
if (this.fullpage.isScrolling) {
// 判断是否可以滚动
return false;
}
let e = event.originalEvent || event;
this.fullpage.deltaY = e.deltaY || e.detail; // Firefox使用detail
if (this.fullpage.deltaY > 0) {
this.next();
} else if (this.fullpage.deltaY < 0) {
this.pre();
}
},
三、移动端触摸实现切换
触摸事件相当于滚动事件来说更为复杂,首先要移除手指滑动时对屏幕的影响,否则很容易出现白边,影响视觉效果。然后需要记录移动的距离是否有效,移动的事件是否过长等等…
// 清除触摸事件
handleTouchmove(event) {
event.preventDefault()
},
//手指按下屏幕
handleTouchstart(event) {
this.startTime = Date.now()
this.startX = event.changedTouches[0].clientX
this.startY = event.changedTouches[0].clientY
},
//手指离开屏幕
handleTouchend(event) {
const endTime = Date.now()
const endX = event.changedTouches[0].clientX
const endY = event.changedTouches[0].clientY
//判断按下的时长
if (endTime - this.startTime > 2000) {
return
}
//滑动的方向
let direction = "";
//先判断用户滑动的距离,是否合法,合法:判断滑动的方向 注意 距离要加上绝对值
if (Math.abs(endY - this.startY) > 10) {
//滑动方向
direction = endY - this.startY > 0 ? "down" : "up"
} else {
return
}
//用户做了合法的滑动操作
// console.log('方向'+direction)
if (direction === 'up') {
this.next();
}
if (direction === 'down') {
this.pre();
}
}
总结
最后,将全部页面文件贴一下,方便大家搬运.
<template>
<div class="fullPage" ref="fullPage">
<div
class="fullPageContainer"
ref="fullPageContainer"
@mousewheel="mouseWheelHandle"
@DOMMouseScroll="mouseWheelHandle"
@touchstart="handleTouchstart"
@touchend="handleTouchend"
@touchmove="handleTouchmove"
>
<div class="section section1">1</div>
<div class="section section2">2</div>
<div class="section section3">3</div>
<div class="section section4">4</div>
</div>
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
fullpage: {
current: 1, // 当前的页面编号
isScrolling: false, // 是否在滚动,是为了防止滚动多页,需要通过一个变量来控制是否滚动
deltaY: 0 // 返回鼠标滚轮的垂直滚动量,保存的鼠标滚动事件的deleteY,用来判断是往下还是往上滚
},
startTime: undefined, // 记录触摸开始的时间
startX: undefined, // 记录触摸开始的X坐标,本次主要实现的是上下滑动,所以当前坐标不做强制要求
startY: undefined, // 记录触摸开始的Y坐标
};
},
methods: {
// 往下切换
next() {
let len = 4; // 页面的个数
if (this.fullpage.current + 1 <= len) { // 如果当前页面编号+1 小于总个数,则可以执行向下滑动
this.fullpage.current += 1; // 页面+1
this.move(this.fullpage.current); // 执行切换
}
},
// 往上切换
pre() {
if (this.fullpage.current - 1 > 0) { // 如果当前页面编号-1 大于0,则可以执行向下滑动
this.fullpage.current -= 1;// 页面+1
this.move(this.fullpage.current);// 执行切换
}
},
// 滚动事件
move(index) {
this.fullpage.isScrolling = true; // 为了防止滚动多页,需要通过一个变量来控制是否滚动
this.directToMove(index); //执行滚动
setTimeout(() => { //这里的动画是1s执行完,使用setTimeout延迟1s后解锁
this.fullpage.isScrolling = false;
}, 1010);
},
// 执行滚动
directToMove(index) {
let height = this.$refs["fullPage"].clientHeight; //获取屏幕的宽度
let scrollPage = this.$refs["fullPageContainer"]; // 获取执行tarnsform的元素
let scrollHeight; // 计算滚动的告诉,是往上滚还往下滚
scrollHeight = -(index - 1) * height + "px";
scrollPage.style.transform = `translateY(${scrollHeight})`;
this.fullpage.current = index;
},
// 监听鼠标监听
mouseWheelHandle(event) {
// 添加冒泡阻止
let evt = event || window.event;
if (evt.stopPropagation) {
evt.stopPropagation();
} else {
evt.returnValue = false;
}
if (this.fullpage.isScrolling) { // 判断是否可以滚动
return false;
}
let e = event.originalEvent || event;
this.fullpage.deltaY = e.deltaY || e.detail; // Firefox使用detail
if (this.fullpage.deltaY > 0) {
this.next();
} else if (this.fullpage.deltaY < 0) {
this.pre();
}
},
// 清除触摸事件
handleTouchmove(event) {
event.preventDefault()
},
//手指按下屏幕
handleTouchstart(event) {
this.startTime = Date.now()
this.startX = event.changedTouches[0].clientX
this.startY = event.changedTouches[0].clientY
},
//手指离开屏幕
handleTouchend(event) {
const endTime = Date.now()
const endX = event.changedTouches[0].clientX
const endY = event.changedTouches[0].clientY
//判断按下的时长
if (endTime - this.startTime > 2000) {
return
}
//滑动的方向
let direction = "";
//先判断用户滑动的距离,是否合法,合法:判断滑动的方向 注意 距离要加上绝对值
if (Math.abs(endY - this.startY) > 10) {
//滑动方向
direction = endY - this.startY > 0 ? "down" : "up"
} else {
return
}
//用户做了合法的滑动操作
// console.log('方向'+direction)
if (direction === 'up') {
this.next();
}
if (direction === 'down') {
this.pre();
}
}
}
};
</script>
<style scoped lang="scss">
.fullPage {
height: 100vh; //一定要设置,保证占满
overflow: hidden; //一定要设置,多余的先隐藏
background-color: rgb(189, 211, 186);
}
.fullPageContainer {
width: 100%;
height: 100vh;
transition: all linear 0.5s;
}
.section {
width: 100%;
height: 100vh;
background-position: center center;
background-repeat: no-repeat;
}
.section1 {
background-color: rgb(189, 211, 186);
}
.section2 {
background-color: rgb(44, 48, 43);
}
.section3 {
background-color: rgb(116, 104, 109);
}
.section4 {
background-color: rgb(201, 202, 157);
}
</style>