Browse Source

save

pull/40/head
zyronon 1 year ago
parent
commit
96a45de840
  1. 32
      src/assets/less/custom.less
  2. 33
      src/components/slide/BVideo.vue
  3. 180
      src/components/slide/SlideAlbum.vue
  4. 35
      src/components/slide/SlideVerticalInfinite.vue
  5. 1
      src/utils/const_var.js
  6. 7
      src/utils/hooks/useSlideListItemRender.jsx

32
src/assets/less/custom.less

@ -205,3 +205,35 @@ p {
} }
} }
} }
.pause-icon {
width: 60rem;
height: 60rem;
opacity: 0.3;
position: absolute;
margin: auto;
left: 0;
top: 0;
bottom: 0;
right: 0;
color: white;
animation: pause-animation 1.1s linear;
@scale: scale(1.2);
@keyframes pause-animation {
0% {
opacity: 0;
transform: scale(2);
}
10% {
opacity: 0.3;
transform: @scale;
}
100% {
transform: @scale;
opacity: 0.3;
}
}
}

33
src/components/slide/BVideo.vue

@ -12,7 +12,7 @@
:autoplay="isPlay" loop> :autoplay="isPlay" loop>
<p> 您的浏览器不支持 video 标签</p> <p> 您的浏览器不支持 video 标签</p>
</video> </video>
<Icon icon="fluent:play-28-filled" class="pause" v-if="!isPlaying"/> <Icon icon="fluent:play-28-filled" class="pause-icon" v-if="!isPlaying"/>
<div class="float" :style="{opacity: isUp?0:1}"> <div class="float" :style="{opacity: isUp?0:1}">
<div :style="{opacity:isMove ? 0:1}" class="normal"> <div :style="{opacity:isMove ? 0:1}" class="normal">
<template v-if="!commentVisible"> <template v-if="!commentVisible">
@ -373,37 +373,6 @@ export default {
/*position: absolute;*/ /*position: absolute;*/
} }
.pause {
width: 60rem;
height: 60rem;
opacity: 0.3;
position: absolute;
margin: auto;
left: 0;
top: 0;
bottom: 0;
right: 0;
color: white;
animation: pause-animation 1.1s linear;
@scale: scale(1.2);
@keyframes pause-animation {
0% {
opacity: 0;
transform: scale(2);
}
10% {
opacity: 0.3;
transform: @scale;
}
100% {
transform: @scale;
opacity: 0.3;
}
}
}
.float { .float {
position: absolute; position: absolute;
left: 0; left: 0;

180
src/components/slide/SlideAlbum.vue

@ -12,7 +12,9 @@
</div> </div>
</div> </div>
</div> </div>
<template v-if=" state.operationStatus === SlideAlbumOperationStatus.Normal"> <Icon icon="fluent:play-28-filled" class="pause-icon" v-if="state.status === SlideItemPlayStatus.Pause"/>
<template v-if="state.operationStatus === SlideAlbumOperationStatus.Normal">
<ItemToolbar <ItemToolbar
class="mb3r" class="mb3r"
v-model:item="state.localItem" v-model:item="state.localItem"
@ -59,7 +61,14 @@
</div> </div>
<div class="right"> <div class="right">
<Icon icon="heroicons-outline:menu-alt-1" @click="Utils.$no"/> <Icon icon="heroicons-outline:menu-alt-1" @click="Utils.$no"/>
<Icon icon="fluent:play-28-filled" class="pause" @click="Utils.$no"/> <Icon icon="fluent:play-28-filled"
v-if="state.status === SlideItemPlayStatus.Pause"
class="pause"
@click="startPlay"/>
<Icon icon="bi:pause-fill"
v-else
class="pause"
@click="stopPlay"/>
<Icon icon="system-uicons:push-down" @click="Utils.$no"/> <Icon icon="system-uicons:push-down" @click="Utils.$no"/>
</div> </div>
</div> </div>
@ -72,7 +81,7 @@ import enums from "../../utils/enums";
import Utils from '../../utils' import Utils from '../../utils'
import {mat4} from 'gl-matrix' import {mat4} from 'gl-matrix'
import {Icon} from "@iconify/vue"; import {Icon} from "@iconify/vue";
import {onMounted, onBeforeUpdate, reactive, ref, watch, computed, provide, nextTick} from "vue"; import {onMounted, onBeforeUpdate, reactive, ref, watch, computed, provide, nextTick, onUnmounted} from "vue";
import { import {
getSlideDistance, getSlideDistance,
slideInit, slideInit,
@ -81,7 +90,7 @@ import {
slideTouchMove, slideTouchMove,
slideTouchStart slideTouchStart
} from "./common"; } from "./common";
import {SlideAlbumOperationStatus, SlideType} from "../../utils/const_var"; import {SlideAlbumOperationStatus, SlideItemPlayStatus, 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";
@ -112,6 +121,9 @@ const props = defineProps({
return { return {
type: 'imgs', type: 'imgs',
imgs: [ imgs: [
'https://cdn.seovx.com/ha/?mom=302',
'https://imgapi.cn/bing.php',
'https://www.dmoe.cc/random.php',
new URL('../../assets/img/poster/6.jpg', import.meta.url).href, new URL('../../assets/img/poster/6.jpg', import.meta.url).href,
new URL('../../assets/img/poster/0.jpg', import.meta.url).href, new URL('../../assets/img/poster/0.jpg', import.meta.url).href,
new URL('../../assets/img/poster/1.jpg', import.meta.url).href, new URL('../../assets/img/poster/1.jpg', import.meta.url).href,
@ -209,13 +221,19 @@ const props = defineProps({
position: { position: {
type: Object, type: Object,
default: () => { default: () => {
return {} return {
uniqueId: '',
index: '',
}
} }
}, },
}) })
const judgeValue = 20 const judgeValue = 20
const wrapperEl = ref(null) const wrapperEl = ref(null)
//touchstartPlay,clickstopLoop
let lockDatetime = 0
const state = reactive({ const state = reactive({
name: 'SlideHorizontal', name: 'SlideHorizontal',
localIndex: 0, localIndex: 0,
@ -239,18 +257,29 @@ const state = reactive({
move: {x: 0, y: 0}, move: {x: 0, y: 0},
itemRefs: [], itemRefs: [],
previewImgs: [], previewImgs: [],
status: 'play',//stop,custom
cycleFn: -1, cycleFn: -1,
status: SlideItemPlayStatus.Play,
isAutoPlay: true, isAutoPlay: true,
localItem: props.item, localItem: props.item,
}) })
function stopPlay() { function stopPlay() {
state.status = SlideItemPlayStatus.Pause
stopLoop()
}
function startPlay() {
state.isAutoPlay = true
state.status = SlideItemPlayStatus.Play
startLoop()
}
function stopLoop() {
clearInterval(state.cycleFn) clearInterval(state.cycleFn)
state.cycleFn = -1 state.cycleFn = -1
} }
function startPlay() { function startLoop() {
if (state.cycleFn !== -1) return if (state.cycleFn !== -1) return
if (!state.isAutoPlay) return if (!state.isAutoPlay) return
state.cycleFn = setInterval(() => { state.cycleFn = setInterval(() => {
@ -265,12 +294,44 @@ function startPlay() {
onMounted(async () => { onMounted(async () => {
await nextTick(); await nextTick();
slideInit(wrapperEl.value, state, SlideType.HORIZONTAL) slideInit(wrapperEl.value, state, SlideType.HORIZONTAL)
// startPlay() // startLoop()
setTimeout(() => { setTimeout(() => {
state.operationStatus = SlideAlbumOperationStatus.Zooming state.operationStatus = SlideAlbumOperationStatus.Zooming
}, 1000) }, 1000)
bus.on(EVENT_KEY.SINGLE_CLICK_BROADCAST, click)
}) })
onUnmounted(() => {
bus.off(EVENT_KEY.SINGLE_CLICK_BROADCAST, click)
})
function click({uniqueId, index, type}) {
// console.log('position,', type, Date.now() - lockDatetime)
if (props.position.uniqueId === uniqueId && props.position.index === index) {
// if (type === EVENT_KEY.ITEM_TOGGLE) {
// if (state.status === SlideItemPlayStatus.Play) {
// stopLoop()
// } else {
// state.isAutoPlay = true
// startLoop()
// }
// }
if (type === EVENT_KEY.ITEM_STOP) {
stopPlay()
setTimeout(() => {
state.localIndex = 0
}, 500)
}
if (type === EVENT_KEY.ITEM_PLAY) {
state.localIndex = 0
state.isAutoPlay = true
state.status = SlideItemPlayStatus.Play
startLoop()
}
}
}
// ref // ref
onBeforeUpdate(() => { onBeforeUpdate(() => {
state.itemRefs = [] state.itemRefs = []
@ -296,10 +357,6 @@ watch(
} }
) )
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
@ -333,30 +390,35 @@ function progressBarTouchMEnd(e) {
} }
function touchStart(e) { function touchStart(e) {
lockDatetime = Date.now()
// Utils.$showNoticeDialog('start'+e.touches.length) // Utils.$showNoticeDialog('start'+e.touches.length)
// console.log('start', e.touches.length) console.log('start', e.touches.length)
if (e.touches.length === 1) { if (e.touches.length === 1) {
isZooming.value = false
slideTouchStart(e, wrapperEl.value, state) slideTouchStart(e, wrapperEl.value, state)
} else { } else {
if (isZooming.value) return 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)
return
}
state.operationStatus = SlideAlbumOperationStatus.Zooming 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};
state.start.center = Utils.getCenter(state.start.point1, state.start.point2) state.start.center = Utils.getCenter(state.start.point1, state.start.point2)
} }
} }
function touchMove(e) { function touchMove(e) {
// Utils.$showNoticeDialog('move'+e.touches.length) // Utils.$showNoticeDialog('move'+e.touches.length)
// 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}
stopPlay() stopLoop()
// //
if (e.touches.length === 1) { if (e.touches.length === 1) {
if (isZooming.value) { if (state.operationStatus === SlideAlbumOperationStatus.Zooming) {
// console.log('m1') // console.log('m1')
Utils.$stopPropagation(e) Utils.$stopPropagation(e)
@ -399,21 +461,8 @@ function touchMove(e) {
// //
let currentRatio = Utils.getDistance(current1, current2) / Utils.getDistance(state.start.point1, state.start.point2); let currentRatio = Utils.getDistance(current1, current2) / Utils.getDistance(state.start.point1, state.start.point2);
let center = Utils.getCenter(current1, current2)
center.x -= rect.x
center.y -= rect.y
//ratioov[0]
let zoom = currentRatio / ov[0]
const x = center.x * (1 - zoom);
const y = center.y * (1 - zoom);
const t = new Float32Array([zoom, 0, 0, 0, 0, zoom, 0, 0, 0, 0, 1, 0, x, y, 0, 1,]);
//zoomx
//zoom0.15ov
ov = mat4.multiply(out, t, ov);
let movementRatio = currentRatio - ov[0] let movementRatio = currentRatio - ov[0]
// console.log('movementRatio',movementRatio)
//0.02 //0.02
if (Math.abs(movementRatio) <= 0.02) { if (Math.abs(movementRatio) <= 0.02) {
let movementX = current1.x - state.last.point1.x let movementX = current1.x - state.last.point1.x
@ -423,8 +472,30 @@ function touchMove(e) {
let minX = Math.min(movementX, movement2X) let minX = Math.min(movementX, movement2X)
let minY = Math.min(movementY, movement2Y) let minY = Math.min(movementY, movement2Y)
const t1 = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, minX, minY, 0, 1,]); const t1 = new Float32Array([
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
minX, minY, 0, 1
]);
ov = mat4.multiply(out, t1, ov); ov = mat4.multiply(out, t1, ov);
} else {
let center = Utils.getCenter(current1, current2)
center.x -= rect.x
center.y -= rect.y
//ratioov[0]
let zoom = currentRatio / ov[0]
const x = center.x * (1 - zoom);
const y = center.y * (1 - zoom);
const t = new Float32Array([
zoom, 0, 0, 0,
0, zoom, 0, 0,
0, 0, 1, 0,
x, y, 0, 1
]);
//zoomx
//zoom0.15ov
ov = mat4.multiply(out, t, ov);
} }
state.itemRefs[state.localIndex].style.transform = `matrix3d(${ov.toString()})`; state.itemRefs[state.localIndex].style.transform = `matrix3d(${ov.toString()})`;
@ -434,17 +505,37 @@ function touchMove(e) {
} }
function touchEnd(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) {
if (state.status === SlideItemPlayStatus.Play) {
stopPlay()
} else {
startPlay()
}
return
}
state.isPreview = false state.isPreview = false
//0 //touches10
// console.log('end', e.touches.length, state.operationStatus) //touches0
// Utils.$showNoticeDialog('1' + e.touches.length) console.log('end', e.touches.length)
// e.touches.length === 1
if (e.touches.length === 1) { if (e.touches.length === 1) {
// //
if (isZooming.value) { if (state.operationStatus === SlideAlbumOperationStatus.Zooming) {
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}
startPlay() startLoop()
}
} else {
if (state.operationStatus === SlideAlbumOperationStatus.Zooming) {
Utils.$stopPropagation(e)
ov = origin
state.itemRefs[state.localIndex].style['transition-duration'] = '300ms';
state.itemRefs[state.localIndex].style.transform = `matrix3d(${origin.toString()})`;
startLoop()
state.operationStatus = SlideAlbumOperationStatus.Look
} else { } else {
slideTouchEnd(e, state, canNext, slideTouchEnd(e, state, canNext,
() => { () => {
@ -452,19 +543,11 @@ function touchEnd(e) {
}, },
() => { () => {
console.log('doNotNextCb') console.log('doNotNextCb')
state.operationStatus = SlideAlbumOperationStatus.Normal startLoop()
startPlay()
} }
) )
slideReset(wrapperEl.value, state, SlideType.HORIZONTAL, null) slideReset(wrapperEl.value, state, SlideType.HORIZONTAL, null)
} }
} else {
state.operationStatus = SlideAlbumOperationStatus.Detail
ov = origin
Utils.$stopPropagation(e)
state.itemRefs[state.localIndex].style['transition-duration'] = '300ms';
state.itemRefs[state.localIndex].style.transform = `matrix3d(${origin.toString()})`;
startPlay()
} }
} }
@ -484,6 +567,7 @@ function canNext(isNext, e) {
return res return res
} }
</script> </script>
<style scoped lang="less"> <style scoped lang="less">

35
src/components/slide/SlideVerticalInfinite.vue

@ -189,24 +189,27 @@ function getInsEl(item, index, play = false) {
// console.log('index', index, play) // console.log('index', index, play)
let slideVNode = props.render(item, index, play, props.uniqueId) let slideVNode = props.render(item, index, play, props.uniqueId)
const parent = document.createElement('div') const parent = document.createElement('div')
parent.classList.add('slide-item') //TODO 线
parent.setAttribute('data-index', index) if (import.meta.env.PROD) {
render(slideVNode, parent) parent.classList.add('slide-item')
// const app = createApp({ parent.setAttribute('data-index', index)
// render() { render(slideVNode, parent)
// return <SlideItem data-index={index}>{slideVNode}</SlideItem> appInsMap.set(index, {
// } unmount: () => {
// }) render(null, parent)
// const ins = app.mount(parent) parent.remove()
// appInsMap.set(index, ins) }
// return ins.$el })
appInsMap.set(index, { return parent
unmount: () => { }
render(null, parent) const app = createApp({
parent.remove() render() {
return <SlideItem data-index={index}>{slideVNode}</SlideItem>
} }
}) })
return parent const ins = app.mount(parent)
appInsMap.set(index, ins)
return ins.$el
} }
function touchStart(e) { function touchStart(e) {

1
src/utils/const_var.js

@ -28,6 +28,7 @@ export const SlideType = {
export const SlideAlbumOperationStatus = { export const SlideAlbumOperationStatus = {
Normal: 'Normal', Normal: 'Normal',
Zooming: 'Zooming', Zooming: 'Zooming',
Look: 'Look',
Detail: 'Detail', Detail: 'Detail',
} }
/*图集播放状态*/ /*图集播放状态*/

7
src/utils/hooks/useSlideListItemRender.jsx

@ -10,7 +10,12 @@ export function useSlideListItemRender(props) {
node = <img src={item.src} style="height:100%;"/> node = <img src={item.src} style="height:100%;"/>
} }
if (item.type === 'imgs') { if (item.type === 'imgs') {
node = <SlideAlbum/> node = <SlideAlbum
isPlay={play}
index={index}
position={{uniqueId, index}}
{...props}
/>
} }
if (item.type === 'user') { if (item.type === 'user') {
node = <SlideUser {...props}/> node = <SlideUser {...props}/>

Loading…
Cancel
Save