Vue-router's route transformation only has "before" and "after transform", there is no "in transition" state, so do not most apps (that) in the sliding process to let the interface follow the finger movement. However, the sliding event can still be monitored, and we can then trigger the routed fallback event after sliding.
The slide return of Weibo is basically the principle: slide first, then trigger return event, but it is very strange to use, there is a serious lag sense. Quark browser do better: First, although the interface is not moving, but there are small icons on the interface to allow users to receive feedback, and second, the return process is very fast, there is no unnecessary transition animation.
The App.vue file is as follows:
?
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 6667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611 7118119120 |
<template>
<div id=
"app" v-on:touchstart=
"bodyTouchStart" v-on:touchmove=
"bodyTouchMove" v-on:touchend=
"bodyTouchEnd"
>
<transition :name=
"direction"
>
<keep-alive include=
"home"
>
<router-view class=
"appView"
></router-view>
</keep-alive>
</transition>
</div>
</template>
<script>
var swidth = document.documentElement.clientWidth;
export
default {
name:
‘app‘
,
data: () => ({
// direction 页面切换的过渡动画,配合transition组件使用
direction:
"slide-left"
,
// touchLeft 划动起点界限,起点在靠近屏幕左侧时才有效
touchLeft: swidth*2/5,
// touchStartPoint 记录起始点X坐标
touchStartPoint: 0,
// distance 记录划动的距离
distance: 0,
// 回退按钮的dom,根据页面上是否存在此dom来判断该路由是否可回退
backBtn:
null
}),
watch: {
// 监听路有变化,决定页面过渡动画
$route(to, from) {
if (from.name ==
"login" || from.path.indexOf(
"home"
) > -1) {
this
.direction =
"slide-left"
;
}
else if (to.path.indexOf(
"home"
) > -1) {
this
.direction =
"slide-right"
;
}
else {
const toDepth = to.path.split(
"/"
).length;
const fromDepth = from.path.split(
"/"
).length;
this
.direction = toDepth < fromDepth ?
"slide-right" :
"slide-left"
;
}
}
},
methods: {
bodyTouchStart:
function
(event) {
this
.backBtn = document.getElementById(
"navback"
);
if (
this
.backBtn) {
// 获得起点X坐标,初始化distance为0
this
.touchStartPoint = event.targetTouches[0].pageX;
this
.distance = 0;
}
},
bodyTouchMove:
function
(event) {
if (
this
.backBtn &&
this
.touchStartPoint <
this
.touchLeft) {
// 只监听单指划动,多指划动不作响应
if (event.targetTouches.length > 1) {
return
;
}
// 实时计算distance
this
.distance = event.targetTouches[0].pageX -
this
.touchStartPoint;
// 根据distance在页面上做出反馈。这里演示通过返回按钮的背景变化作出反馈
if (
this
.distance > 0 &&
this
.distance < 100) {
this
.backBtn.style.backgroundPosition = ((
this
.distance - 100) / 100) * 50 +
"px 0"
;
}
else if (
this
.distance >= 100) {
this
.backBtn.style.backgroundPosition =
"0 0"
;
}
else {
this
.backBtn.style.backgroundPosition =
"-50px 0"
;
}
}
},
bodyTouchEnd:
function
(event) {
if (
this
.backBtn &&
this
.touchStartPoint <
this
.touchLeft) {
// 划动结束,重置数据
this
.touchStartPoint = 0;
this
.backBtn.style.backgroundPosition =
"-50px 0"
;
// 当划动距离超过100px时,触发返回事件
if (
this
.distance > 100) {
// 返回前修改样式,让过渡动画看起来更快
document.getElementById(
"app"
).classList.add(
"quickback"
);
this
.$router.back();
setTimeout(
function
(){
document.getElementById(
"app"
).classList.remove(
"quickback"
);
},250)
}
}
}
}
}
</script>
<style>
#app {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 100%;
overflow-x: hidden;
}
.appView {
position: absolute;
width: 100%;
background: #fff;
min-height: 100vh;
transition: transform 0.24s ease-out;
}
#app.quickback .appView{
transition-duration: 0.1s;
}
.slide-left-enter {
transform: translate(100%, 0);
}
.slide-left-leave-active {
transform: translate(-50%, 0);
}
.slide-right-enter {
transform: translate(-50%, 0);
}
.slide-right-leave-active {
transform: translate(100%, 0);
}
</style>
|
Here's a look at the Vue picture left and right swipe and gesture zoom
Introducedvue-awesome-swiperimport ‘swiper/dist/css/swiper.css‘;
?
123456789101112131415161718 |
import { swiper, swiperSlide } from
‘vue-awesome-swiper‘
;components: {
swiper,
swiperSlide,
},data() {
return {
swiperOption: {
width: window.innerWidth,
zoom :
true
,
initialSlide: 0,
},
};
},<swiper :options=
"swiperOption" ref=
"imgOverview" style=
"height: 100%;"
>
<swiper-slide v-
for
=
"(img, index) in previewImg"
>
<div class=
"swiper-zoom-container"
>
"img" alt=
""
>
</div>
</swiper-slide>
</swiper>
|
Vue-router gesture Swipe trigger return function