This commit is contained in:
zyronon 2024-03-05 03:03:43 +08:00
parent 71ff88a52e
commit 420e3f7ba8
14 changed files with 132 additions and 93 deletions

View File

@ -7,4 +7,5 @@
# TODO
- 双指缩放
- 双指缩放
- AutoInput组件在真机上无法输入

View File

@ -42,6 +42,8 @@
<script crossorigin="anonymous"
integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js"></script>
<script src="//cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
</head>
<body>
<div id="app"></div>

View File

@ -7,7 +7,7 @@
.global-notice {
position: fixed;
z-index: 999;
z-index: 9999;
color: white;
background: black;
left: 50%;

View File

@ -36,7 +36,7 @@ export default {
<style scoped lang="less">
.auto-input {
font-size: 12rem;
font-size: 14rem;
width: 100%;
max-height: 70rem;
overflow-y: scroll;

View File

@ -32,12 +32,16 @@
<div class="time">{{ $time(item.time) }} · 上海</div>
<div class="reply-text">回复</div>
</div>
<div class="love" @click="loved(item)">
<img v-show="item.isLoved" src="../assets/img/icon/components/like-red-small.png" alt=""
class="love-image">
<img v-show="!item.isLoved" src="../assets/img/icon/components/like-gray-small.png" alt=""
class="love-image">
<span>{{ formatNumber(item.loveNum) }}</span>
<div class="right d-flex" style="gap: 10rem">
<div class="love" :class="item.isLoved && 'loved'" @click="loved(item)">
<Icon icon="icon-park-solid:like" v-show="item.isLoved" class="love-image"/>
<Icon icon="icon-park-outline:like" v-show="!item.isLoved" class="love-image"/>
<span>{{ formatNumber(item.loveNum) }}</span>
</div>
<div class="love" @click="$no(item)">
<Icon icon="icon-park-outline:dislike" class="love-image"/>
<span>{{ formatNumber(item.loveNum) }}</span>
</div>
</div>
</div>
</div>
@ -60,11 +64,9 @@
<div class="time">{{ $time(item.time) }} · 上海</div>
<div class="reply-text">回复</div>
</div>
<div class="love" @click="loved(item)">
<img v-show="item.isLoved" src="../assets/img/icon/components/like-red-small.png" alt=""
class="love-image">
<img v-show="!item.isLoved" src="../assets/img/icon/components/like-gray-small.png" alt=""
class="love-image">
<div class="love" :class="item.isLoved && 'loved'" @click="loved(item)">
<Icon icon="icon-park-solid:like" v-show="item.isLoved" class="love-image"/>
<Icon icon="icon-park-outline:like" v-show="!item.isLoved" class="love-image"/>
<span>{{ formatNumber(item.loveNum) }}</span>
</div>
</div>
@ -74,7 +76,7 @@
<div class="more">
<div class="gang"></div>
<span>展开更多回复</span>
<div class="arrow"></div>
<Icon icon="ep:arrow-down-bold"/>
</div>
</div>
</div>
@ -100,10 +102,10 @@
<div class="toolbar">
<div class="input-wrapper">
<AutoInput v-model="comment"></AutoInput>
<AutoInput v-model="comment" placeholder="善语结善缘,恶言伤人心"></AutoInput>
<div class="right">
<img src="../assets/img/icon/message/call.png" @click="isCall = !isCall">
<img src="../assets/img/icon/message/emoji-black.png">
<img src="../assets/img/icon/message/emoji-black.png" @click="$no">
</div>
</div>
<img v-if="comment" src="../assets/img/icon/message/up.png" @click="send">
@ -127,6 +129,7 @@ import {mapState} from "vuex";
import FromBottomDialog from "./dialog/FromBottomDialog";
import Loading from "./Loading";
import Search from "./Search";
import {$no} from "@/utils";
export default {
name: "Comment",
@ -185,6 +188,7 @@ export default {
this.getData()
},
methods: {
$no,
send() {
this.comments.push({
id: '2',
@ -411,7 +415,7 @@ export default {
}
.more {
font-size: 12rem;
font-size: 13rem;
margin: 5rem;
display: flex;
align-items: center;
@ -424,13 +428,8 @@ export default {
height: 1px;
}
.arrow {
margin-left: 5rem;
margin-top: 8rem;
width: 0;
height: 0;
border: 5rem solid transparent;
border-top: 6rem solid @second-text-color;
span {
margin-right: 5rem;
}
}
}
@ -469,7 +468,7 @@ export default {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12rem;
font-size: 13rem;
.left {
display: flex;
@ -489,13 +488,16 @@ export default {
display: flex;
align-items: center;
&.loved {
color: rgb(231, 58, 87);
}
.love-image {
width: 18rem;
border-radius: 50%;
font-size: 17rem;
margin-right: 4rem;
}
span {
font-size: 10rem;
word-break: keep-all;
}
}

View File

@ -151,8 +151,8 @@ export default {
}
.badge {
right: 12rem;
top: 9rem;
right: 10rem;
top: 6rem;
position: absolute;
}
}

View File

@ -6,13 +6,14 @@
@touchstart.passive="touchStart"
@touchmove="touchMove"
@touchend="touchEnd">
<div class="img-slide-item" v-for="img in item.imgs">
<div class="img-slide-item" v-for="(img,index) in item.imgs">
<img :ref="e=>setItemRef(e,'itemRefs')"
:src="img">
:src="img+'&d='+index">
</div>
</div>
</div>
<Icon icon="fluent:play-28-filled" class="pause-icon" v-if="state.status === SlideItemPlayStatus.Pause"/>
<Icon icon="fluent:play-28-filled" class="pause-icon"
v-if="state.status === SlideItemPlayStatus.Pause && state.operationStatus === SlideAlbumOperationStatus.Normal"/>
<template v-if="state.operationStatus === SlideAlbumOperationStatus.Normal">
<ItemToolbar
@ -43,10 +44,11 @@
<Teleport to="#home-index" 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.item.imgs"
:ref="e=>setItemRef(e,'previewImgs')"
<img
:src="img+'&d='+index"
:class="{'preview-img':index === state.localIndex}"
v-for="(img,index) in props.item.imgs"
:ref="e=>setItemRef(e,'previewImgs')"
>
</div>
<div class="indicator">
@ -69,7 +71,7 @@
v-else
class="pause"
@click="stopPlay"/>
<Icon icon="system-uicons:push-down" @click="Utils.$no"/>
<Icon icon="system-uicons:push-down" @click="$notice('已保存到系统相册')"/>
</div>
</div>
</Teleport>
@ -78,7 +80,7 @@
<script setup lang="jsx">
import enums from "../../utils/enums";
import Utils from '../../utils'
import Utils, {$no, $notice} from '../../utils'
import {mat4} from 'gl-matrix'
import {Icon} from "@iconify/vue";
import {onMounted, onBeforeUpdate, reactive, ref, watch, computed, provide, nextTick, onUnmounted} from "vue";
@ -281,12 +283,13 @@ function startLoop() {
if (state.cycleFn !== -1) return
if (!state.isAutoPlay) return
state.cycleFn = setInterval(() => {
state.status = SlideItemPlayStatus.Play
if (state.localIndex < props.item.imgs.length - 1) {
state.localIndex++
} else {
state.localIndex = 0
}
}, 1500)
}, 2000)
}
onMounted(async () => {
@ -296,7 +299,6 @@ onMounted(async () => {
// setTimeout(() => {
// state.operationStatus = SlideAlbumOperationStatus.Zooming
// }, 1000)
bus.on(EVENT_KEY.SINGLE_CLICK_BROADCAST, click)
})
@ -319,13 +321,13 @@ function click({uniqueId, index, type}) {
stopPlay()
setTimeout(() => {
state.localIndex = 0
state.status = SlideItemPlayStatus.Play
state.operationStatus = SlideAlbumOperationStatus.Normal
}, 500)
}
if (type === EVENT_KEY.ITEM_PLAY) {
state.localIndex = 0
state.isAutoPlay = true
state.status = SlideItemPlayStatus.Play
startLoop()
startPlay()
}
}
}
@ -395,22 +397,21 @@ function touchStart(e) {
if (e.touches.length === 1) {
slideTouchStart(e, wrapperEl.value, state)
} else {
state.last.point2 = state.start.point2 = {x: e.touches[1].pageX, y: e.touches[1].pageY};
if (state.operationStatus === SlideAlbumOperationStatus.Zooming) {
state.start.center = Utils.getCenter(state.start.point1, state.start.point2)
// state.start.center = Utils.getCenter(state.start.point1, state.start.point2)
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};
state.last.point2 = state.start.point2 = {x: e.touches[1].pageX, y: e.touches[1].pageY};
state.start.center = Utils.getCenter(state.start.point1, state.start.point2)
}
}
function touchMove(e) {
// Utils.$showNoticeDialog('move'+e.touches.length)
console.log('move', e.touches.length,state.operationStatus )
// console.log('move', e.touches.length, state.operationStatus)
let current1 = {x: e.touches[0].pageX, y: e.touches[0].pageY}
stopLoop()
@ -433,12 +434,22 @@ function touchMove(e) {
state.isAutoPlay = false
slideTouchMove(e, wrapperEl.value, state, judgeValue, canNext,
() => {
// console.log('move-nextcb')
}, SlideType.HORIZONTAL,
() => {
if (state.operationStatus === SlideAlbumOperationStatus.Detail) {
if (state.operationStatus !== SlideAlbumOperationStatus.Normal) {
Utils.$stopPropagation(e)
}
})
// console.log('move-notNextcb')
// state.operationStatus = SlideAlbumOperationStatus.Normal
},
() => {
if (state.operationStatus !== SlideAlbumOperationStatus.Normal) {
Utils.$stopPropagation(e)
}
}
)
}
} else {
// console.log('m3')
@ -503,8 +514,10 @@ function touchMove(e) {
}
function touchEnd(e) {
console.log('Date.now() - lockDatetime', Date.now() - lockDatetime,)
if (Date.now() - lockDatetime < 300 && state.move.x === 0 && state.move.y === 0) {
// console.log('Date.now() - lockDatetime', Date.now() - lockDatetime,)
if (Date.now() - lockDatetime < 300
&& state.move.x === 0 && state.move.y === 0
&& state.operationStatus !== SlideAlbumOperationStatus.Zooming) {
if (state.status === SlideItemPlayStatus.Play) {
stopPlay()
} else {
@ -516,7 +529,7 @@ function touchEnd(e) {
state.isPreview = false
//touches10
//touches0
console.log('end', e.touches.length)
console.log('end', e.touches.length, state.operationStatus)
// e.touches.length === 1
if (e.touches.length === 1) {
@ -540,6 +553,9 @@ function touchEnd(e) {
console.log('nextCb')
},
() => {
if (state.operationStatus !== SlideAlbumOperationStatus.Normal) {
state.operationStatus = SlideAlbumOperationStatus.Normal
}
console.log('doNotNextCb')
startLoop()
}
@ -559,9 +575,6 @@ function setItemRef(el, key) {
function canNext(isNext, e) {
let res = !((state.localIndex === 0 && !isNext) || (state.localIndex === props.item.imgs.length - 1 && isNext));
if (!res && state.operationStatus === SlideAlbumOperationStatus.Detail && e) {
Utils.$stopPropagation(e)
}
return res
}
@ -626,7 +639,7 @@ function canNext(isNext, e) {
flex: 1;
margin: 0 2rem;
height: @h;
background: rgba(#000, .5);
background: #75757580;
position: relative;
overflow: hidden;
@ -635,7 +648,7 @@ function canNext(isNext, e) {
position: absolute;
left: 0;
height: @h;
background: white;
background: #e5e5e587;
}
}
}
@ -657,16 +670,17 @@ function canNext(isNext, e) {
.preview-wrapper {
img {
transition: width .3s;
transition: all .3s;
margin: 0 5rem;
width: 30rem;
height: 50rem;
height: 45rem;
background-color: black;
border-radius: 3rem;
overflow: hidden;
object-fit: cover;
&.preview-img {
margin: 0 15rem;
width: 40rem;
}
}

View File

@ -50,7 +50,7 @@ watch(
if (props.changeActiveIndexUseAnim) {
GM.$setCss(wrapperEl.value, 'transition-duration', `300ms`)
}
GM.$setCss(wrapperEl.value, 'transform', `translate3d(${getSlideDistance(state, SlideType.HORIZONTAL)}px, 0, 0)`)
GM.$setCss(wrapperEl.value, 'transform', `translate3d(${getSlideDistance(state, SlideType.HORIZONTAL,wrapperEl.value)}px, 0, 0)`)
}
}
)

View File

@ -208,7 +208,7 @@ function getInsEl(item, index, play = false) {
}
})
const ins = app.mount(parent)
appInsMap.set(index, ins)
appInsMap.set(index, app)
return ins.$el
}

View File

@ -23,12 +23,13 @@ export function slideTouchStart(e, el, state) {
state.start.time = Date.now()
}
//检测能否滑动
export function canSlide(state, judgeValue, type = SlideType.HORIZONTAL) {
if (state.needCheck) {
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 = type === SlideType.HORIZONTAL ? angle > 1 : angle <= 1;
// console.log(angle)
console.log('angle', angle, state.next)
state.needCheck = false
} else {
return false
@ -37,7 +38,10 @@ export function canSlide(state, judgeValue, type = SlideType.HORIZONTAL) {
return state.next
}
export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type = SlideType.HORIZONTAL, notNextCb) {
/**
* @param slideOtherDirectionCb 滑动其他方向时的回调目前用于图集进于放大模式后上下滑动推出放大模式
* */
export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type = SlideType.HORIZONTAL, notNextCb, slideOtherDirectionCb = null) {
state.move.x = e.touches[0].pageX - state.start.x
state.move.y = e.touches[0].pageY - state.start.y
@ -48,26 +52,29 @@ export function slideTouchMove(e, el, state, judgeValue, canNextCb, nextCb, type
if (canSlideRes && state.localIndex === 0 && !isNext && type === SlideType.VERTICAL) {
bus.emit(state.name + '-moveY', state.move.y)
}
if (!canNextCb?.(isNext, e)) return
if (canSlideRes) {
nextCb?.()
if (type === SlideType.HORIZONTAL) {
bus.emit(state.name + '-moveX', state.move.x)
}
Utils.$stopPropagation(e)
let t = getSlideDistance(state, type, el) + (isNext ? judgeValue : -judgeValue)
let dx1 = 0
let dx2 = 0
if (type === SlideType.HORIZONTAL) {
dx1 = t + state.move.x
if (canNextCb?.(isNext, e)) {
nextCb?.()
if (type === SlideType.HORIZONTAL) {
bus.emit(state.name + '-moveX', state.move.x)
}
Utils.$stopPropagation(e)
let t = getSlideDistance(state, type, el) + (isNext ? judgeValue : -judgeValue)
let dx1 = 0
let dx2 = 0
if (type === SlideType.HORIZONTAL) {
dx1 = t + state.move.x
} else {
dx2 = t + state.move.y
}
Utils.$setCss(el, 'transition-duration', `0ms`)
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
} else {
dx2 = t + state.move.y
notNextCb?.()
}
Utils.$setCss(el, 'transition-duration', `0ms`)
Utils.$setCss(el, 'transform', `translate3d(${dx1}px, ${dx2}px, 0)`)
} else {
notNextCb?.()
slideOtherDirectionCb?.(e)
}
}

View File

@ -50,7 +50,7 @@ let t = [
}
},
]
allRecommendVideos.unshift(...t)
// allRecommendVideos.unshift(...t)
// {
// type: 'imgs',
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`,

View File

@ -8,7 +8,7 @@
<Icon
icon="tabler:menu-deep"
class="search"
@click="$nav('/home/live')"
@click="$emit('showSlidebar')"
style="transform: rotateY(180deg)"/>
<div class="tab-ctn">
<div class="tabs" ref="tabs">

View File

@ -2,7 +2,7 @@
<div class="test-slide-wrapper" id="home-index">
<SlideHorizontal v-model:index="state.baseIndex">
<SlideItem class="sidebar">
<div class="sidebar1">
<div class="card">
</div>
</SlideItem>
@ -11,6 +11,7 @@
v-if="!state.fullScreen"
:loading="loading"
name="main"
@showSlidebar="state.baseIndex = 0"
v-model:index="state.navIndex"
/>
<div class="slide-content">
@ -30,6 +31,9 @@
</SlideHorizontal>
</div>
<Footer v-bind:init-tab="1"/>
<Mask v-if="state.baseIndex === 0"
@click="state.baseIndex = 1"
mode="white" style="position: absolute"/>
</SlideItem>
<SlideItem>
<UserPanel
@ -135,7 +139,7 @@ const bodyHeight = computed(() => store.state.bodyHeight)
const bodyWidth = computed(() => store.state.bodyWidth)
const state = reactive({
baseIndex: 1,
baseIndex: 0,
navIndex: 4,
test: '',
recommendList: [
@ -245,7 +249,7 @@ function dislike() {
overflow: hidden;
.sidebar {
width: 70vw;
width: 75vw;
height: 100vh;
overflow: auto;
background: red;

View File

@ -10,7 +10,7 @@ import bus from "./bus";
import {cloneDeep} from "lodash";
import {EVENT_KEY} from "./bus";
export default {
const Utils = {
require2(url) {
return new URL(url, import.meta.url).href
},
@ -74,12 +74,12 @@ export default {
const app = Vue.createApp({
render() {
return <SimpleConfirmDialog
onCancel={tempCancelCb}
onDismiss={remove}
title={title}
okText={okText}
cancelText={cancelText}
onOk={tempOkCb}/>
onCancel={tempCancelCb}
onDismiss={remove}
title={title}
okText={okText}
cancelText={cancelText}
onOk={tempOkCb}/>
},
})
let parent = document.createElement('div')
@ -238,7 +238,7 @@ export default {
params: (function () {
const ret = {}
const seg = a.search.replace(/^\?/, '')
.split('&')
.split('&')
const len = seg.length
let i = 0
let s
@ -424,3 +424,12 @@ export default {
document.body.removeChild(input);
}
}
export default Utils
export function $no() {
Utils.$no(arguments)
}
export function $notice(val) {
Utils.$notice(val)
}