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 pinyin: 2.11.1
vconsole: ^3.15.0 vconsole: ^3.15.0
vite: 4.0.4 vite: 4.0.4
vue: ^3.2.45 vue: 3.2.45
vue-router: 4.0.14 vue-router: 4.0.14
vue-switches: 2.0.1 vue-switches: 2.0.1
vuex: 4.0.2 vuex: 4.0.2

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -30,7 +30,7 @@
import Slide from "./slide.jsx"; import Slide from "./slide.jsx";
import SlideVideo from "../../components/slide/SlideVideo"; import SlideVideo from "../../components/slide/SlideVideo";
import SlideUser from "../../components/slide/SlideUser"; 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 resource from "../../assets/data/resource.js";
import CONST_VAR from "../../utils/const_var"; import CONST_VAR from "../../utils/const_var";
import Dom from "../../utils/dom"; import Dom from "../../utils/dom";

View File

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

View File

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