25 changed files with 1361 additions and 1452 deletions
@ -1,65 +1,67 @@
@@ -1,65 +1,67 @@
|
||||
//布局常用类 |
||||
|
||||
.d-none{ |
||||
display: none!important; |
||||
.d-none { |
||||
display: none !important; |
||||
} |
||||
|
||||
//flex 布局常用类 |
||||
.d-flex { |
||||
display: flex !important; |
||||
display: flex !important; |
||||
} |
||||
|
||||
.justify-content-center { |
||||
justify-content: center !important; |
||||
justify-content: center !important; |
||||
} |
||||
|
||||
.justify-content-between { |
||||
justify-content: space-between !important; |
||||
justify-content: space-between !important; |
||||
} |
||||
|
||||
.justify-content-around { |
||||
justify-content: space-around !important; |
||||
justify-content: space-around !important; |
||||
} |
||||
|
||||
.align-items-center { |
||||
align-items: center !important; |
||||
align-items: center !important; |
||||
} |
||||
|
||||
.align-items-start { |
||||
align-items: flex-start !important; |
||||
align-items: flex-start !important; |
||||
} |
||||
|
||||
.align-items-end { |
||||
align-items: flex-end !important; |
||||
align-items: flex-end !important; |
||||
} |
||||
|
||||
.flex-wrap-wrap { |
||||
flex-wrap: wrap; |
||||
flex-wrap: wrap; |
||||
} |
||||
.flex-direction-column{ |
||||
flex-direction: column; |
||||
|
||||
.flex-direction-column { |
||||
flex-direction: column; |
||||
} |
||||
|
||||
|
||||
.pull-left { |
||||
float: left; |
||||
float: left; |
||||
} |
||||
|
||||
.pull-right { |
||||
float: right; |
||||
float: right; |
||||
} |
||||
|
||||
.block { |
||||
display: block; |
||||
display: block; |
||||
} |
||||
|
||||
.oh { |
||||
overflow: hidden; |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.tac { |
||||
text-align: center; |
||||
text-align: center; |
||||
} |
||||
|
||||
.fb{ |
||||
font-weight: bold; |
||||
.fb { |
||||
font-weight: bold; |
||||
} |
||||
|
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
||||
@footer-height: 5rem; |
||||
@header-height: 6rem; |
||||
@indicator-height: 5rem; |
||||
@footer-height: 50rem; |
||||
@header-height: 60rem; |
||||
@indicator-height: 50rem; |
||||
|
||||
@padding-page: 1.5rem; |
||||
@padding-page: 15rem; |
@ -0,0 +1,106 @@
@@ -0,0 +1,106 @@
|
||||
<script setup> |
||||
import {ref, onMounted, reactive} from "vue"; |
||||
import GM from '../../utils' |
||||
import bus from "../../utils/bus"; |
||||
import Common from "../../utils"; |
||||
import {slideReset, slideTouchStart} from "./common"; |
||||
|
||||
const props = defineProps({ |
||||
index: { |
||||
type: Number, |
||||
default: () => { |
||||
return 0 |
||||
} |
||||
}, |
||||
}) |
||||
const emit = defineEmits(['update:index']) |
||||
|
||||
const judgeValue = 20 |
||||
const wrapperEl = ref(null) |
||||
const wrapper = reactive({width: 0, height: 0, childrenLength: 0}) |
||||
const state = reactive({ |
||||
name: 'SlideVertical', |
||||
localIndex: 0, |
||||
needCheck: true, |
||||
next: false, |
||||
start: {x: 0, y: 0, time: 0}, |
||||
move: {x: 0, y: 0}, |
||||
}) |
||||
|
||||
onMounted(() => { |
||||
wrapper.width = GM.$getCss(wrapperEl.value, 'width') |
||||
wrapper.height = GM.$getCss(wrapperEl.value, 'height') |
||||
wrapper.childrenLength = wrapperEl.value.children.length |
||||
}) |
||||
|
||||
function touchStart(e) { |
||||
slideTouchStart(e, wrapperEl.value, state) |
||||
} |
||||
|
||||
function touchMove(e) { |
||||
state.move.x = e.touches[0].pageX - state.start.x |
||||
state.move.y = e.touches[0].pageY - state.start.y |
||||
|
||||
let isNext = state.move.x < 0 |
||||
if ((state.localIndex === 0 && !isNext) || (state.localIndex === wrapper.childrenLength - 1 && isNext)) return |
||||
|
||||
checkDirection(e) |
||||
|
||||
if (state.next) { |
||||
bus.emit(state.name + '-moveX', state.move.x) |
||||
GM.$stopPropagation(e) |
||||
GM.$setCss(wrapperEl.value, 'transform', |
||||
`translate3d(${getDistance() |
||||
+ state.move.x |
||||
+ (isNext ? judgeValue : -judgeValue) |
||||
}px, 0, 0)`) |
||||
} |
||||
} |
||||
|
||||
function touchEnd(e) { |
||||
let isRight = state.move.x < 0 |
||||
if ((state.localIndex === 0 && !isRight) || (state.localIndex === wrapper.childrenLength - 1 && isRight)) state.next = false |
||||
|
||||
let endTime = Date.now() |
||||
let gapTime = endTime - state.start.time |
||||
if (Math.abs(state.move.x) < 20) gapTime = 1000 |
||||
if (Math.abs(state.move.x) > (wrapper.width / 4)) gapTime = 100 |
||||
if (gapTime < 150 && state.next) { |
||||
if (isRight) { |
||||
state.localIndex++ |
||||
} else { |
||||
state.localIndex-- |
||||
} |
||||
} |
||||
slideReset(wrapperEl.value, getDistance(), state, emit) |
||||
} |
||||
|
||||
function checkDirection(e) { |
||||
if (!state.needCheck) return |
||||
if (Math.abs(state.move.x) > judgeValue || Math.abs(state.move.y) > judgeValue) { |
||||
let angle = (Math.abs(state.move.x) * 10) / (Math.abs(state.move.y) * 10) |
||||
state.next = angle > 1; |
||||
// console.log(angle) |
||||
return state.needCheck = false |
||||
} |
||||
return state.needCheck = true |
||||
} |
||||
|
||||
function getDistance() { |
||||
return -state.localIndex * wrapper.width |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="slide"> |
||||
<div class="slide-wrapper" |
||||
ref="wrapperEl" |
||||
@touchstart="touchStart" |
||||
@touchmove="touchMove" |
||||
@touchend="touchEnd" |
||||
> |
||||
<slot></slot> |
||||
</div> |
||||
</div> |
||||
</template> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
<template> |
||||
<div class="slide-item"> |
||||
<slot></slot> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup> |
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
.slide-item { |
||||
height: 100%; |
||||
width: 100%; |
||||
flex-shrink: 0; |
||||
} |
||||
</style> |
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
<script setup> |
||||
import {ref, onMounted, reactive} from "vue"; |
||||
import Common from '../../utils' |
||||
import bus from "../../utils/bus"; |
||||
|
||||
const props = defineProps({ |
||||
list: { |
||||
type: Array, |
||||
default: () => { |
||||
return [] |
||||
} |
||||
}, |
||||
}) |
||||
|
||||
const judgeValue = 20 |
||||
const wrapperEl = ref(null) |
||||
const wrapper = reactive({width: 0, height: 0, childrenLength: 0}) |
||||
const start = reactive({x: 0, y: 0, time: 0}) |
||||
const move = reactive({x: 0, y: 0}) |
||||
const state = reactive({ |
||||
localIndex: 0, |
||||
needCheck: true, |
||||
next: false, |
||||
}) |
||||
|
||||
onMounted(() => { |
||||
checkChildren() |
||||
}) |
||||
|
||||
function checkChildren() { |
||||
wrapper.width = Common.$getCss(wrapperEl.value, 'width') |
||||
wrapper.height = Common.$getCss(wrapperEl.value, 'height') |
||||
wrapper.childrenLength = wrapperEl.value.children.length |
||||
} |
||||
|
||||
function touchStart(e) { |
||||
Common.$setCss(wrapperEl.value, 'transition-duration', `0ms`) |
||||
start.x = e.touches[0].pageX |
||||
start.y = e.touches[0].pageY |
||||
start.time = Date.now() |
||||
} |
||||
|
||||
function touchMove(e) { |
||||
move.x = e.touches[0].pageX - start.x |
||||
move.y = e.touches[0].pageY - start.y |
||||
|
||||
let isNext = move.x < 0 |
||||
checkDirection(e) |
||||
|
||||
if (state.localIndex === 0 && !isNext && state.next) { |
||||
// bus.emit(this.name + '-moveY', this.moveY) |
||||
} |
||||
if ((state.localIndex === 0 && !isNext) || (state.localIndex === props.list.length- 1 && isNext)) return |
||||
if (state.next) { |
||||
Common.$stopPropagation(e) |
||||
Common.$setCss(wrapperEl.value, 'transform', |
||||
`translate3d(${getDistance() |
||||
+ move.y |
||||
+ (isNext ? judgeValue : -judgeValue) |
||||
}px, 0)`) |
||||
} |
||||
} |
||||
|
||||
function touchEnd(e) { |
||||
let isRight = move.x < 0 |
||||
if ((state.localIndex === 0 && !isRight) || (state.localIndex === wrapper.childrenLength - 1 && isRight)) state.next = false |
||||
|
||||
let endTime = Date.now() |
||||
let gapTime = endTime - start.time |
||||
if (Math.abs(move.x) < 20) gapTime = 1000 |
||||
if (Math.abs(move.x) > (wrapper.width / 4)) gapTime = 100 |
||||
if (gapTime < 150 && state.next) { |
||||
if (isRight) { |
||||
state.localIndex++ |
||||
} else { |
||||
state.localIndex-- |
||||
} |
||||
} |
||||
reset() |
||||
} |
||||
|
||||
function checkDirection(e) { |
||||
if (!state.needCheck) return |
||||
if (Math.abs(move.x) > judgeValue || Math.abs(move.y) > judgeValue) { |
||||
let angle = (Math.abs(move.x) * 10) / (Math.abs(move.y) * 10) |
||||
state.next = angle <= 1; |
||||
// console.log(angle) |
||||
return state.needCheck = false |
||||
} |
||||
return state.needCheck = true |
||||
} |
||||
|
||||
function reset() { |
||||
Common.$setCss(wrapperEl.value, 'transition-duration', `300ms`) |
||||
Common.$setCss(wrapperEl.value, 'transform', |
||||
`translate3d(${getDistance()}px, 0, 0)`) |
||||
|
||||
move.x = 0 |
||||
state.next = false |
||||
state.needCheck = true |
||||
start.time = null |
||||
// this.$emit('update:index', state.localIndex) |
||||
// bus.emit(this.name + '-end', state.localIndex) |
||||
} |
||||
|
||||
function getDistance() { |
||||
return -state.localIndex * wrapper.height |
||||
} |
||||
|
||||
</script> |
||||
|
||||
<template> |
||||
<div class="slide"> |
||||
<div class="slide-wrapper flex-direction-column" |
||||
ref="wrapperEl" |
||||
@touchstart="touchStart" |
||||
@touchmove="touchMove" |
||||
@touchend="touchEnd" |
||||
> |
||||
<slot></slot> |
||||
</div> |
||||
</div> |
||||
</template> |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
import bus from "../../utils/bus"; |
||||
import Utils from '../../utils' |
||||
import GM from "../../utils"; |
||||
|
||||
export function slideReset(el, distance, state, emit) { |
||||
Utils.$setCss(el, 'transition-duration', `300ms`) |
||||
Utils.$setCss(el, 'transform', `translate3d(${distance}px, 0, 0)`) |
||||
state.start.x = state.start.y = state.start.time = state.move.x = state.move.y = 0 |
||||
state.next = false |
||||
state.needCheck = true |
||||
emit('update:index', state.localIndex) |
||||
bus.emit(state.name + '-end', state.localIndex) |
||||
} |
||||
|
||||
export function slideTouchStart(e, el, state) { |
||||
GM.$setCss(el, 'transition-duration', `0ms`) |
||||
state.start.x = e.touches[0].pageX |
||||
state.start.y = e.touches[0].pageY |
||||
state.start.time = Date.now() |
||||
} |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
<template> |
||||
<div class="slide2"> |
||||
<H class="h" v-model:index="state.index"> |
||||
<SlideItem class="slide-item"> |
||||
<!-- <V>--> |
||||
<!-- <SlideItem class="slide-item"></SlideItem>--> |
||||
<!-- <SlideItem class="slide-item"></SlideItem>--> |
||||
<!-- </V>--> |
||||
</SlideItem> |
||||
<SlideItem class="slide-item"> |
||||
<!-- <V></V>--> |
||||
</SlideItem> |
||||
</H> |
||||
<span>{{ state.index }}</span> |
||||
<Footer v-bind:init-tab="1"/> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup> |
||||
import H from './H' |
||||
import V from './V' |
||||
import SlideItem from './SlideItem' |
||||
import {reactive} from "vue"; |
||||
|
||||
const state = reactive({ |
||||
index: 0 |
||||
}) |
||||
|
||||
</script> |
||||
|
||||
<style scoped lang="less"> |
||||
.slide2 { |
||||
width: 100%; |
||||
height: 100%; |
||||
|
||||
span { |
||||
color: white; |
||||
font-size: 24rem; |
||||
} |
||||
} |
||||
|
||||
.h { |
||||
width: 90vw; |
||||
height: 80vh; |
||||
overflow: hidden; |
||||
|
||||
.slide-item { |
||||
background-color: red; |
||||
|
||||
&:last-child { |
||||
background-color: gray; |
||||
} |
||||
} |
||||
} |
||||
|
||||
</style> |
Loading…
Reference in new issue