This commit is contained in:
hhh 2023-01-23 03:54:35 +08:00
parent 6b0731fff0
commit 881eb98bc1
12 changed files with 220 additions and 133 deletions

View File

@ -16,7 +16,7 @@ specifiers:
pinyin: 2.11.1
vconsole: ^3.15.0
vite: 4.0.4
vue: ^3.2.45
vue: 3.2.45
vue-router: 4.0.14
vue-switches: 2.0.1
vuex: 4.0.2

View File

@ -5,6 +5,7 @@
@second-btn-color-tran: rgba(58, 58, 70, .4);
@line-color: rgb(37, 45, 66);
@line-color2: rgb(56, 54, 67);
@footer-color:#020202;
@primary-btn-color: rgb(252, 47, 86);
@disable-primary-btn-color: rgba(252, 47, 86, .5);

View File

@ -1,5 +1,5 @@
<template>
<div class="footer">
<div v-if="visible" class="footer">
<div class="l-button" @click="refresh(1)">
<span v-if="!isRefresh1" :class="{active:currentTab===1}">首页</span>
<img v-if="isRefresh1 " src="../assets/img/icon/refresh1.png" alt="" class="refresh">
@ -26,6 +26,8 @@
</template>
<script>
import bus from "../utils/bus";
export default {
name: "Footer",
props: ['initTab'],
@ -34,8 +36,14 @@ export default {
isRefresh1: false,
isRefresh2: false,
currentTab: this.initTab,
visible: true
}
},
created() {
bus.on('setFooterVisible', (e) => this.visible = e)
bus.on('enterFullscreen', (e) => this.visible = false)
bus.on('exitFullscreen', (e) => this.visible = true)
},
methods: {
tab(index) {
switch (index) {
@ -84,7 +92,7 @@ export default {
// 使footerbottom0
top: calc(100vh - @footer-height);
//bottom: 0;
background: #020202;
background: @footer-color;
color: white;
display: flex;
//justify-content: space-between;

View File

@ -52,7 +52,7 @@ const state = reactive({
</script>
<template>
<div class="item-desc">
<div class="content ml1r mb2r" v-if="!isMy">
<div class="content ml1r mb1r" v-if="!isMy">
<div class="location-wrapper" v-if=" item.city || item.address">
<div class="location">
<img src="../../assets/img/icon/location.webp" alt="">

View File

@ -1,6 +1,5 @@
<template>
<!--不知为啥touch事件在下部20px的空间内不触发加上click事件不好了 -->
<div id="SlideImgs">
<div id="SlideAlbum">
<div class="img-slide-wrapper">
<div class="img-slide-list"
ref="wrapperEl"
@ -13,42 +12,54 @@
</div>
</div>
</div>
<template v-if="!state.isPreview">
<template v-if="false">
<ItemToolbar :item="props.modelValue"
:index="0"
prefix="sadfa"
/>
<ItemDesc
:item="props.modelValue"
:index="0"
prefix="sadfa"
/>
</template>
<div class="progress-bar"
@touchstart="progressBarTouchStart"
@touchmove="progressBarTouchMove"
@touchend="progressBarTouchMEnd"
>
<div class="bar" v-for="(img,index) in modelValue.imgs">
<div class="progress"
:style="getProgressWidth(index)"></div>
</div>
</div>
<template v-if=" state.operationStatus === SlideAlbumOperationStatus.Normal">
<ItemToolbar :item="props.modelValue"
:index="0"
prefix="sadfa"
/>
<ItemDesc
:item="props.modelValue"
:index="0"
prefix="sadfa"
/>
</template>
<div class="preview" v-if="state.isPreview">
<div class="preview-wrapper">
<img :src="img"
:class="{'preview-img':index === state.localIndex}"
v-for="(img,index) in props.modelValue.imgs"
:ref="e=>setItemRef(e,'previewImgs')"
>
</div>
<div class="indicator">
<span class="index">{{ state.localIndex + 1 }}</span>&nbsp;/&nbsp;{{ props.modelValue.imgs.length }}
<!--不知为啥touch事件在下部20px的空间内不触发加上click事件不好了 -->
<div class="progress-bar"
v-if="!state.isPreview && state.operationStatus!== SlideAlbumOperationStatus.Zooming"
@click="null"
@touchstart="progressBarTouchStart"
@touchmove="progressBarTouchMove"
@touchend="progressBarTouchMEnd"
>
<div class="bar" v-for="(img,index) in modelValue.imgs">
<div class="progress"
:style="getProgressWidth(index)"></div>
</div>
</div>
<Teleport to="#slideHook" v-if="state.isPreview">
<div class="preview">
<div class="preview-wrapper">
<img :src="img"
:class="{'preview-img':index === state.localIndex}"
v-for="(img,index) in props.modelValue.imgs"
:ref="e=>setItemRef(e,'previewImgs')"
>
</div>
<div class="indicator">
<span class="index">{{ state.localIndex + 1 }}</span>&nbsp;/&nbsp;{{ props.modelValue.imgs.length }}
</div>
</div>
</Teleport>
<Teleport to="#slideHook" v-if="state.operationStatus === SlideAlbumOperationStatus.Detail">
<div class="album-toolbar">
<div class="left">关闭</div>
<div class="right">
<div class="option">评论</div>
<div class="option">切换</div>
<div class="option">下载</div>
</div>
</div>
</Teleport>
</div>
</template>
@ -56,7 +67,7 @@
import enums from "../../utils/enums";
import Utils from '../../utils'
import {mat4} from 'gl-matrix'
import {onMounted, onBeforeUpdate, reactive, ref, watch} from "vue";
import {onMounted, onBeforeUpdate, reactive, ref, watch, computed} from "vue";
import {
getSlideDistance,
slideInit,
@ -65,15 +76,12 @@ import {
slideTouchMove,
slideTouchStart
} from "../../pages/slideHooks/common";
import {SlideType} from "../../utils/const_var";
import {SlideAlbumOperationStatus, SlideType} from "../../utils/const_var";
import ItemToolbar from "./ItemToolbar";
import ItemDesc from "./ItemDesc";
import GM from "../../utils";
import {cloneDeep} from "lodash";
function c() {
console.log('console.log()')
}
import bus from "../../utils/bus";
let out = new Float32Array([
0, 0, 0, 0,
@ -199,7 +207,8 @@ const state = reactive({
localIndex: 0,
needCheck: true,
isPreview: false,
isTwo: true,
isZoom: false,
operationStatus: SlideAlbumOperationStatus.Normal,
next: false,
wrapper: {width: 0, height: 0, childrenLength: 0},
last: {
@ -258,6 +267,21 @@ watch(
}
)
watch(
() => state.operationStatus,
(newVal) => {
if (newVal === SlideAlbumOperationStatus.Zooming) {
bus.emit('enterFullscreen')
} else {
bus.emit('exitFullscreen')
}
}
)
const isZooming = computed(() => {
return state.operationStatus === SlideAlbumOperationStatus.Zooming
})
function calcCurrentIndex(e) {
state.isPreview = true
let x = e.touches[0].pageX
@ -277,39 +301,26 @@ function calcCurrentIndex(e) {
}
function progressBarTouchStart(e) {
console.log('progressBarTouchStart')
Utils.$stopPropagation(e)
}
function progressBarTouchMove(e) {
console.log('progressBarTouchMove')
let current1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
// let rect = wrapperEl.value.getBoundingClientRect()
// if (rect.height - 15 < current1.y && current1.y < rect.height) {
// console.log('')
// state.isPreview = true
// // Utils.$stopPropagation(e)
// }
// calcCurrentIndex(e)
Utils.$stopPropagation(e)
calcCurrentIndex(e)
}
function progressBarTouchMEnd(e) {
console.log('progressBarTouchEnd')
if (state.isPreview){
Utils.$stopPropagation(e)
}
Utils.$stopPropagation(e)
state.isPreview = false
}
function touchStart(e) {
console.log('start', e.touches.length)
if (e.touches.length === 1) {
state.isTwo = false
slideTouchStart(e, wrapperEl.value, state)
} else {
if (state.isTwo) return
state.isTwo = true
if (isZooming.value) return
state.operationStatus = SlideAlbumOperationStatus.Zooming
state.itemRefs[state.localIndex].style['transition-duration'] = '0ms';
state.last.point1 = state.start.point1 = {x: e.touches[0].pageX, y: e.touches[0].pageY};
state.last.point2 = state.start.point2 = {x: e.touches[1].pageX, y: e.touches[1].pageY};
@ -318,9 +329,10 @@ function touchStart(e) {
}
function touchMove(e) {
console.log('move', e.touches.length)
console.log('move', e.touches.length,)
let current1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
if (state.isTwo && e.touches.length === 1) {
if (isZooming.value && e.touches.length === 1) {
console.log('m1')
state.status = 'pause'
Utils.$stopPropagation(e)
@ -334,16 +346,19 @@ function touchMove(e) {
state.last.point1 = current1
} else {
if (e.touches.length === 1) {
state.isTwo = false
if (state.isPreview) {
// Utils.$stopPropagation(e)
}else {
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext, () => {
state.status = 'pause'
}, SlideType.HORIZONTAL)
}
console.log('m2')
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext,
() => {
state.status = 'pause'
}, SlideType.HORIZONTAL,
() => {
if (state.operationStatus === SlideAlbumOperationStatus.Detail) {
Utils.$stopPropagation(e)
}
})
} else {
state.isTwo = true
console.log('m3')
state.operationStatus = SlideAlbumOperationStatus.Zooming
Utils.$stopPropagation(e)
state.status = 'pause'
@ -398,13 +413,14 @@ function touchMove(e) {
function touchEnd(e) {
state.isPreview = false
// console.log('end', e.touches.length, state.isTwo)
console.log('end', e.touches.length, state.operationStatus)
//
if (state.isTwo && e.touches.length === 1) {
if (isZooming.value && e.touches.length === 1) {
Utils.$stopPropagation(e)
state.last.point1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
} else {
if (state.isTwo) {
if (isZooming.value) {
state.operationStatus = SlideAlbumOperationStatus.Detail
ov = origin
Utils.$stopPropagation(e)
state.itemRefs[state.localIndex].style['transition-duration'] = '300ms';
@ -416,6 +432,8 @@ function touchEnd(e) {
state.progress = (state.localIndex + 1) * 100
},
() => {
console.log('notNextCb')
state.operationStatus = SlideAlbumOperationStatus.Normal
if (state.status !== 'custom') {
state.status = 'play'
requestAnimationFrame(state.cycleFn)
@ -436,16 +454,21 @@ function setItemRef(el, key) {
el && state[key].push(el)
}
function canNext(isNext) {
return !((state.localIndex === 0 && !isNext) || (state.localIndex === props.modelValue.imgs.length - 1 && isNext));
function canNext(isNext, e) {
let res = !((state.localIndex === 0 && !isNext) || (state.localIndex === props.modelValue.imgs.length - 1 && isNext));
if (!res && state.operationStatus === SlideAlbumOperationStatus.Detail && e) {
Utils.$stopPropagation(e)
}
return res
}
</script>
<style scoped lang="less">
#SlideImgs {
@import "@/assets/less/index";
#SlideAlbum {
position: relative;
background: blue;
width: 100%;
height: 100%;
overflow: hidden;
@ -488,8 +511,8 @@ function canNext(isNext) {
padding: 0 5rem;
@h: 4rem;
//height: @h;
height: 30rem;
background-color: red;
height: 10rem;
//background-color: red;
align-items: flex-end;
justify-content: space-between;
@ -498,7 +521,7 @@ function canNext(isNext) {
flex: 1;
margin: 0 2rem;
height: @h;
background: gray;
background: rgba(#000, .5);
position: relative;
overflow: hidden;
@ -512,41 +535,85 @@ function canNext(isNext) {
}
}
.preview {
transition: opacity .3s;
position: fixed;
bottom: 20rem;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
</style>
<style lang="less">
@import "@/assets/less/index";
.preview-wrapper {
img {
transition: width .3s;
margin: 0 5rem;
width: 30rem;
height: 50rem;
background-color: black;
object-fit: contain;
border-radius: 3rem;
overflow: hidden;
.preview {
transition: opacity .3s;
position: fixed;
bottom: 0;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
&.preview-img {
width: 40rem;
}
}
}
.preview-wrapper {
img {
transition: width .3s;
margin: 0 5rem;
width: 30rem;
height: 50rem;
background-color: black;
object-fit: contain;
border-radius: 3rem;
overflow: hidden;
.indicator {
margin-top: 10rem;
color: gray;
.index {
color: white;
&.preview-img {
width: 40rem;
}
}
}
.indicator {
background: @footer-color;
width: 100%;
height: @footer-height;
color: gray;
display: flex;
align-items: center;
justify-content: center;
.index {
color: white;
}
}
}
.album-toolbar {
position: absolute;
bottom: 0;
background: @footer-color;
width: 100%;
box-sizing: border-box;
height: @footer-height;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 10rem;
@padding: 12rem;
.left {
height: 34rem;
background-color: gray;
border-radius: 6rem;
padding: 0 @padding;
display: flex;
align-items: center;
justify-content: center;
}
.right {
.left;
.option {
margin: 0 5rem;
}
}
}
</style>

View File

@ -9,14 +9,13 @@ import store from "./store";
import mixin from "./utils/mixin";
import VueLazyload from '@jambonn/vue-lazyload'
import VConsole from 'vconsole';
const vConsole = new VConsole();
const app = Vue.createApp(App)
app.config.globalProperties.$api = {...api}
const loadImage = new URL('./assets/img/icon/img-loading.png', import.meta.url).href
app.provide('mitt', mitt())
app.mixin(mixin)
app.use(VueLazyload, {

View File

@ -36,13 +36,13 @@ export function canSlide(state, judgeValue, type = SlideType.HORIZONTAL) {
return state.next
}
export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type = SlideType.HORIZONTAL) {
export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type = SlideType.HORIZONTAL,notNextCb) {
state.move.x = e.touches[0].pageX - state.start.x
state.move.y = e.touches[0].pageY - state.start.y
let isNext = type === SlideType.HORIZONTAL ? state.move.x < 0 : state.move.y < 0
if (!canNextCb?.(isNext)) return
if (!canNextCb?.(isNext, e)) return
if (canSlide(state, judgeValue, type)) {
nextCb?.()
@ -58,6 +58,8 @@ export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type
}
Utils.$setCss(el, 'transition-duration', `0ms`)
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
}else {
notNextCb?.()
}
}
@ -65,7 +67,7 @@ export function slideTouchEnd(e, state, canNextCb, nextCb, notNextCb, type = Sli
let isHorizontal = type === SlideType.HORIZONTAL;
let isNext = isHorizontal ? state.move.x < 0 : state.move.y < 0
if (!canNextCb?.(isNext)) return
if (!canNextCb?.(isNext)) return notNextCb?.()
if (state.next) {
Utils.$stopPropagation(e)
let endTime = Date.now()
@ -80,11 +82,10 @@ export function slideTouchEnd(e, state, canNextCb, nextCb, notNextCb, type = Sli
} else {
state.localIndex--
}
nextCb?.()
} else {
notNextCb?.()
return nextCb?.()
}
}
notNextCb?.()
}
export function slideReset(el, state, type, emit) {

View File

@ -1,5 +1,5 @@
<template>
<div class="test-slide-wrapper">
<div class="test-slide-wrapper" id="slideHook">
<H v-model:index="state.baseIndex">
<SlideItem class=" gray">
<H class="h" v-model:index="state.navIndex">
@ -54,7 +54,7 @@ import VInfinite from './VInfinite.vue'
import SlideItem from './SlideItem'
import SlideVideo from "../../components/slide/SlideVideo";
import SlideUser from "../../components/slide/SlideUser";
import SlideImgs from "../../components/slide/SlideImgs";
import SlideImgs from "../../components/slide/SlideAlbum";
import BVideo from "../../components/slide/BVideo";
import resource from "../../assets/data/resource.js";
@ -235,6 +235,8 @@ function render(item, itemIndex, play,prefix) {
</script>
<style scoped lang="less">
@import "@/assets/less/index";
.test-slide-wrapper {
font-size: 14rem;
width: 100%;

View File

@ -15,7 +15,7 @@
import TestSlide from "./TestSlide";
import SlideUser from "../../components/slide/SlideUser";
import SlideImgs from "../../components/slide/SlideImgs";
import SlideImgs from "../../components/slide/SlideAlbum";
import TestImg from "./TestImg";
import slideHooks from '../slideHooks'
import {mat4} from "gl-matrix";

View File

@ -30,7 +30,7 @@
import Slide from "./slide.jsx";
import SlideVideo from "../../components/slide/SlideVideo";
import SlideUser from "../../components/slide/SlideUser";
import SlideImgs from "../../components/slide/SlideImgs";
import SlideImgs from "../../components/slide/SlideAlbum";
import resource from "../../assets/data/resource.js";
import CONST_VAR from "../../utils/const_var";
import Dom from "../../utils/dom";

View File

@ -67,10 +67,7 @@ import Uploader from "../pages/me/Uploader";
import Slide from "../pages/slide/Slide";
const routes = [
{
path: '/',
redirect: '/test'
},
{path: '/', redirect: '/test'},
{path: '/slide', component: Slide},
{path: '/test', component: Test},
{path: '/test4', component: Test4},

View File

@ -20,6 +20,18 @@ export default {
}
}
export const SlideType = {
HORIZONTAL:0,
VERTICAL:1,
HORIZONTAL: 0,
VERTICAL: 1,
}
/*图集操作状态*/
export const SlideAlbumOperationStatus = {
Normal: 'Normal',
Zooming: 'Zooming',
Detail: 'Detail',
}
/*图集播放状态*/
export const SlideAlbumPlayStatus = {
HORIZONTAL: 0,
VERTICAL: 1,
}