This commit is contained in:
hhh 2023-01-25 03:53:45 +08:00
parent 881eb98bc1
commit 1b3e7cf7a9
11 changed files with 219 additions and 308 deletions

View File

@ -191,4 +191,68 @@ p {
display: flex;
position: relative;
}
}
}
.love-dbclick {
position: absolute;
@width: 90rem;
width: @width;
height: @width;
&.left {
animation: loveLeft 1.1s linear;
}
&.right {
animation: loveRight 1.1s linear;
}
@scale: scale(1.2);
@start-scale: scale(2.2);
@rotate: 10deg;
@keyframes loveLeft {
0% {
opacity: 0;
transform: @start-scale rotate(0-@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0-@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0-@rotate);
opacity: 0;
}
}
@keyframes loveRight {
0% {
opacity: 0;
transform: @start-scale rotate(0+@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0+@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0+@rotate);
opacity: 0;
}
}
}

View File

@ -51,7 +51,7 @@ export default {
// },
pause() {
this.isStop = true
this.musicBg.css('webkitAnimationPlayState', 'paused')
this.musicBg.css('webkitAnimationPlayState', 'isZooming.value')
},
stop() {
this.isStop = true

View File

@ -1,7 +1,7 @@
<template>
<div class="video-wrapper" ref="videoWrapper" :class="name">
<Loading v-if="loading" style="position: absolute"/>
<!-- <video :src="video.video + '?v=123'"-->
<!-- <video :src="video.video + '?v=123'"-->
<video :src="video.video"
:poster="video.video + videoPoster"
ref="video"
@ -13,70 +13,17 @@
<img src="../../assets/img/icon/play-white.png" class="pause" v-if="paused">
<div class="float" :style="{opacity: isUp?0:1}">
<div :style="{opacity:isMove ? 0:1}" class="normal">
<div class="toolbar mb1r">
<div class="avatar-ctn mb4r">
<img class="avatar" :src="lVideo.author.avatar" alt=""
@click.stop="$emit('goUserInfo')">
<transition name="fade">
<div v-if="!isAttention" @click.stop="attention" class="options" ref="attention-option">
<img class="no" src="../../assets/img/icon/add-light.png" alt="">
<img class="yes" src="../../assets/img/icon/ok-red.png" alt="">
</div>
</transition>
<ItemToolbar :item="video"
:index="0"
prefix="sadfa"
/>
<ItemDesc
:item="video"
:index="0"
prefix="sadfa"
</div>
<div class="love mb2r" @click.stop="loved($event)">
<div>
<img src="../../assets/img/icon/love.svg" class="love-image" v-if="!lVideo.isLoved">
<img src="../../assets/img/icon/loved.svg" class="love-image" v-if="lVideo.isLoved">
</div>
<span>{{ formatNumber(lVideo.digg_count) }}</span>
</div>
<div class="message mb2r" @click.stop="$emit('showComments')">
<!-- <div class="message mb15p" @click.stop="showComment">-->
<img src="../../assets/img/icon/message.svg" alt="" class="message-image">
<span>{{ formatNumber(lVideo.comment_count) }}</span>
</div>
<div v-if="!isMy" class="share mb4r" @click.stop="$emit('showShare')">
<img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image">
<span>{{ formatNumber(lVideo.share_count) }}</span>
</div>
<div v-else class="share mb4r" @click.stop="$emit('showShare')">
<img src="../../assets/img/icon/share-white-full.png" alt="" class="share-image">
</div>
<BaseMusic
:cover="lVideo.music.cover"
:key="name"
:name="name"
:isPlay="isPlay"
@click.stop="$emit('goMusic')"
/>
</div>
<div class="content ml1r mb1r" v-if="!isMy">
<div class="location-wrapper" v-if=" lVideo.city || lVideo.address">
<div class="location">
<img src="../../assets/img/icon/location.webp" alt="">
<span>{{ lVideo.city }}</span>
<template v-if="lVideo.address && lVideo.address">
<div class="gang"></div>
</template>
<span>{{ lVideo.address }}</span>
</div>
</div>
<div class="name mb1r fb" @click.stop="$emit('goUserInfo')">@{{ lVideo.author.nickname }}</div>
<div class="description mb1r">
{{ lVideo.desc }}
</div>
<div class="music" @click.stop="$nav('/music')">
<img src="../../assets/img/icon/music.svg" alt="" class="music-image">
<BaseMarquee :key="name"
:name="name"
:isPlay="isPlay"
:text="lVideo.music.title"
@click.stop="$emit('goMusic')"/>
</div>
</div>
<div v-else class="comment-status">
/>
<div v-if="isMy" class="comment-status">
<div class="comment">
<div class="type-comment">
<img src="../../assets/img/icon/head-image.jpeg" alt="" class="avatar">
@ -98,36 +45,38 @@
</div>
</div>
<div class="progress"
v-if="duration > 60"
:class="progressClass"
@touchmove="move"
@touchend="end"
ref="progress"
@click="null"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
>
<div class="time" v-if="isMove">
<span class="currentTime">{{ $duration(currentTime) }}</span>
<span class="duration"> / {{ $duration(duration) }}</span>
</div>
<div class="line" :style="durationStyle" ref="line"></div>
<div class="point" :style="durationStyle" ref="point"></div>
<div class="bg"></div>
<div class="progress-line" :style="durationStyle"></div>
<div class="point"></div>
</div>
</div>
</div>
</template>
<script>
import globalMethods from '../../utils'
import BaseMarquee from "../BaseMarquee";
import Utils from '../../utils'
import Dom from "../../utils/dom";
import BaseMusic from "../BaseMusic";
import {mapState} from "vuex";
import Loading from "../Loading";
import ItemToolbar from "./ItemToolbar";
import ItemDesc from "./ItemDesc";
export default {
name: "BVideo",
components: {
BaseMarquee,
BaseMusic,
Loading
Loading,
ItemToolbar,
ItemDesc
},
props: {
video: {
@ -142,7 +91,7 @@ export default {
return -1
}
},
prefix: {
tag: {
type: String,
default: () => {
return ''
@ -170,11 +119,11 @@ export default {
},
computed: {
durationStyle() {
return {left: this.pageX + 'px'}
return {width: this.pageX + 'px'}
},
progressClass() {
if (this.isMove) {
return 'stop'
return 'move'
} else {
return this.isPlaying ? '' : 'stop'
}
@ -184,22 +133,22 @@ export default {
return {
loading: false,
paused: false,
name: `v-${this.prefix}-${this.index}-video`,
globalMethods: globalMethods,
name: `v-${this.tag}-item`,
duration: 0,
step: 0,
currentTime: -1,
pageX: 0,
start: {x: 0},
last: {x: 0, time: 0},
height: 0,
width: 0,
isPlaying: this.isPlay,
isAttention: false,
line: null,
point: null,
isMove: false,
isSingleClick: false,
test: [1, 2],
lVideo: this.video,
progressBarRect: {},
videoScreenHeight: 0,
videoPoster: `?vframe/jpg/offset/0/w/${document.body.clientWidth}`
@ -208,20 +157,19 @@ export default {
mounted() {
this.height = document.body.clientHeight
this.width = document.body.clientWidth
this.line = this.$refs.line
this.point = this.$refs.point
let video = this.$refs.video
video.currentTime = 0
let fun = e => {
this.currentTime = Math.ceil(e.target.currentTime)
this.pageX = this.currentTime * this.step
this.pageX = (this.currentTime - 1) * this.step
}
video.addEventListener('loadedmetadata', e => {
this.videoScreenHeight = video.videoHeight / (video.videoWidth / this.width)
this.duration = video.duration
if (this.duration > 60) {
// if (this.duration > 6) {
this.step = this.width / Math.floor(this.duration)
// if (this.duration > 60) {
if (this.duration > 6) {
this.progressBarRect = this.$refs.progress.getBoundingClientRect()
this.step = this.progressBarRect.width / Math.floor(this.duration)
video.addEventListener('timeupdate', fun)
}
})
@ -311,10 +259,10 @@ export default {
this.isPlaying = false
},
formatNumber(v) {
return globalMethods.formatNumber(v)
return Utils.formatNumber(v)
},
$duration(v) {
return globalMethods.$duration(v)
return Utils.$duration(v)
},
attention() {
let option = this.$refs['attention-option']
@ -327,28 +275,31 @@ export default {
this.lVideo.isLoved = !this.lVideo.isLoved
this.$emit('update:video', this.lVideo)
},
start(e) {
this.pageX = e.touches[0].pageX
touchstart(e) {
this.start.x = e.touches[0].pageX
this.last.x = this.pageX
this.last.time = this.currentTime
},
move(e) {
touchmove(e) {
// console.log('move',e)
// if (this.isPlaying) return
this.isMove = true
this.pause()
this.pageX = e.touches[0].pageX
// console.log(this.step)
this.currentTime = Math.ceil(Math.ceil(e.touches[0].pageX) / this.step)
globalMethods.$stopPropagation(e)
let dx = e.touches[0].pageX - this.start.x
this.pageX = this.last.x + dx
this.currentTime = this.last.time + Math.ceil(Math.ceil(dx) / this.step)
if (this.currentTime <= 0) this.currentTime = 0
if (this.currentTime >= this.duration) this.currentTime = this.duration
Utils.$stopPropagation(e)
},
end(e) {
touchend(e) {
if (this.isPlaying) return
console.log('end', e)
// console.log('end', e)
setTimeout(() => {
this.isMove = false
}, 1000)
this.currentTime = Math.ceil(Math.ceil(e.changedTouches[0].pageX) / this.step)
this.play()
globalMethods.$stopPropagation(e)
Utils.$stopPropagation(e)
}
}
}
@ -639,12 +590,16 @@ export default {
}
.progress {
bottom: -1px;
z-index: 10;
@w: 90%;
position: absolute;
height: 7px;
width: 100vw;
background: black;
bottom: -1rem;
height: 10rem;
left: calc((100% - @w) / 2);
width: @w;
display: flex;
align-items: flex-end;
margin-bottom: 2rem;
.time {
position: absolute;
@ -661,53 +616,78 @@ export default {
}
}
&:before {
z-index: 9;
content: ' ';
height: 1.5px;
width: 100vw;
background: gray;
@radius: 10rem;
@h: 1rem;
@tr: height .3s;;
.bg {
transition: @tr;
position: absolute;
top: 0;
width: 100%;
height: @h;
background: rgba(#000, .3);
border-radius: @radius;
}
.line {
z-index: 999;
content: '';
position: absolute;
top: 0;
height: 1px;
width: 200vw;
transform: translate3d(-200vw, 0, 0);
background: gray;
@p: 50px;
.progress-line {
transition: @tr;
height: @h;
width: @p;
border-radius: @radius 0 0 @radius;
background: rgba(#000, .8);
z-index: 1;
}
.point {
z-index: 10;
position: absolute;
left: 10vw;
top: -1px;
height: 4px;
width: 4px;
transition: all .2s;
width: @h+2;
height: @h+2;
border-radius: 50%;
background: gray;
z-index: 2;
transform: translate(-1rem, 1rem);
}
}
& .move {
@h: 10rem;
.bg {
height: @h;
background: @active-main-bg;
}
.progress-line {
height: @h;
background: @second-text-color;
}
.point {
width: @h+2;
height: @h+2;
background: white;
}
}
& .stop {
&:before {
height: 3.5px;
@h: 4rem;
.bg {
height: @h;
background: rgba(#000, .8);
}
.line {
height: 3px;
.progress-line {
height: @h;
background: white;
}
.point {
top: -2px;
height: 8px;
width: 8px;
width: @h+2;
height: @h+2;
background: white;
}
}

View File

@ -99,7 +99,7 @@ function attention() {
:cover="item.music.cover"
:key="state.name"
:name="state.name"
:isPlay="state.isPlay"
:isPlay="isPlay"
@click.stop="$emit('goMusic')"
/>
</div>

View File

@ -468,6 +468,7 @@ function canNext(isNext, e) {
@import "@/assets/less/index";
#SlideAlbum {
transition: height .3s;
position: relative;
width: 100%;
height: 100%;

View File

@ -292,69 +292,6 @@ export default {
}
}
.love-dbclick {
position: absolute;
@width: 8rem;
width: @width;
height: @width;
&.left {
animation: loveLeft 1.1s linear;
}
&.right {
animation: loveRight 1.1s linear;
}
@scale: scale(1.2);
@rotate: 10deg;
@keyframes loveLeft {
0% {
opacity: 0;
transform: scale(2) rotate(0-@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0-@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0-@rotate);
opacity: 0;
}
}
@keyframes loveRight {
0% {
opacity: 0;
transform: scale(2) rotate(0+@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0+@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0+@rotate);
opacity: 0;
}
}
}
.nav-one {
height: 14rem;
box-sizing: border-box;

View File

@ -12,7 +12,7 @@ const props = defineProps({
return 0
}
},
prefix: {
tag: {
type: String,
default: () => {
return ''
@ -106,11 +106,10 @@ function insertContent(list = props.list) {
function getInsEl(item, index, play = false) {
// console.log('index',index,play)
let slideVNode = props.render(item, index, play, props.prefix)
let slideVNode = props.render(item, index, play, props.tag)
const app = createApp({
render() {
return <SlideItem>{slideVNode}</SlideItem>
// return slideVNode
}
})
const parent = document.createElement('div')

View File

@ -1,5 +1,5 @@
<template>
<div class="test-slide-wrapper" id="slideHook">
<div class="test-slide-wrapper" id="slideHook" v-love="'slideHook'">
<H v-model:index="state.baseIndex">
<SlideItem class=" gray">
<H class="h" v-model:index="state.navIndex">
@ -20,10 +20,10 @@
</SlideItem>
<SlideItem class="">
<VInfinite
v-model:index="state.index"
v-model:index="state.itemIndex"
:render="render"
:list="state.recommendVideos"
:prefix="state.videoPrefix[0]"
tag="0-5"
>
</VInfinite>
</SlideItem>
@ -58,22 +58,24 @@ import SlideImgs from "../../components/slide/SlideAlbum";
import BVideo from "../../components/slide/BVideo";
import resource from "../../assets/data/resource.js";
import {reactive} from "vue";
import {onMounted, reactive} from "vue";
import enums from "../../utils/enums";
import bus from "../../utils/bus";
import Dom from "../../utils/dom";
const state = reactive({
baseIndex: 0,
navIndex: 5,
index: 0,
itemIndex: 0,
recommendVideos: [
// {
// type: 'img',
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
// },
{
type: 'imgs',
src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
},
// {
// type: 'imgs',
// src: `http://douyin.ttentau.top/0.mp4?vframe/jpg/offset/0/w/${document.body.clientWidth}`
// },
{
type: 'recommend-video',
"id": "034ae83b-ca0a-401a-b7c6-cf78361bae7b",
@ -161,7 +163,6 @@ const state = reactive({
}
},
],
videoPrefix: ['one', 'two', 'three'],
isCommenting: false,
isSharing: false,
@ -181,7 +182,13 @@ const state = reactive({
shareToFriend: false,
})
function render(item, itemIndex, play,prefix) {
onMounted(() => {
bus.on('singleClick', () => {
new Dom(`.v-${state.baseIndex}-${state.navIndex}-${state.itemIndex}-item`).trigger('singleClick')
})
})
function render(item, itemIndex, play, tag) {
let node
if (item.type === 'img') {
node = <img src={item.src} style="height:100%;"/>
@ -193,8 +200,7 @@ function render(item, itemIndex, play,prefix) {
node = <BVideo
isPlay={play}
video={item}
prefix={prefix}
index={itemIndex}
tag={tag + '-' + itemIndex}
onShowComments={e => state.isCommenting = true}
onShowShare={e => state.isSharing = true}
onGoUserInfo={e => state.baseActiveIndex = 1}

View File

@ -400,69 +400,5 @@ if (import.meta.hot) {
.content {
padding-top: 6rem;
}
.love-dbclick {
position: absolute;
@width: 9rem;
width: @width;
height: @width;
&.left {
animation: loveLeft 1.1s linear;
}
&.right {
animation: loveRight 1.1s linear;
}
@scale: scale(1.2);
@rotate: 10deg;
@keyframes loveLeft {
0% {
opacity: 0;
transform: scale(2) rotate(0-@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0-@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0-@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0-@rotate);
opacity: 0;
}
}
@keyframes loveRight {
0% {
opacity: 0;
transform: scale(2) rotate(0+@rotate);
}
10% {
opacity: 1;
transform: scale(1) rotate(0+@rotate);
}
15% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
40% {
opacity: 1;
transform: @scale rotate(0+@rotate);
}
100% {
transform: translateY(-12rem) scale(2) rotate(0+@rotate);
opacity: 0;
}
}
}
}
</style>

View File

@ -331,7 +331,7 @@ export default {
}
},
$duration(v) {
if (!v) return
if (!v) return '00:00'
let m = Math.floor(v / 60)
// let s = v % 60
let s = Math.round(v % 60)

View File

@ -16,6 +16,7 @@ import BaseButton from "../components/BaseButton";
import CONST_VAR from "./const_var";
import Dom from "./dom";
import bus from "./bus";
import {random} from "lodash";
export default {
components: {
@ -118,59 +119,46 @@ export default {
let clickTimer = null
let dbClickTimer = null
let lastClickTime = null
let checkTime = 200
let dbCheckCancelTime = 500
let dbClick = (e) => {
// console.log('dbClick')
let id = 'a' + Date.now()
let elWidth = 80
let rotate = randomNum(0, 1)
let rotate = random(1)
let template = `<img class="${rotate ? 'left love-dbclick' : 'right love-dbclick'}" id="${id}" src="${new URL('../assets/img/icon/loved.svg', import.meta.url).href}">`
let el = new Dom().create(template)
el.css({top: e.y - elWidth, left: e.x - elWidth / 2,})
el.css({top: e.y - elWidth - 40, left: e.x - elWidth / 2,})
new Dom(`#${binding.value}`).append(el)
setTimeout(() => {
new Dom(`#${id}`).remove()
}, 1000)
}
let randomNum = (minNum, maxNum) => {
switch (arguments.length) {
case 1:
return parseInt(Math.random() * minNum + 1, 10);
case 2:
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
default:
return 0;
}
}
let check = (e) => {
let checkTime = 300
if (isDbClick) {
dbClick(e)
clearTimeout(dbClickTimer);
dbClickTimer = setTimeout(() => {
isDbClick = false
}, checkTime);
dbClick(e)
dbClickTimer = setTimeout(() => isDbClick = false, dbCheckCancelTime);
return
}
let nowTime = new Date().getTime();
if (nowTime - lastClickTime < checkTime) {
clearTimeout(clickTimer);
dbClick(e)
lastClickTime = 0;
clickTimer && clearTimeout(clickTimer);
isDbClick = true
dbClickTimer = setTimeout(() => {
isDbClick = false
}, checkTime);
dbClickTimer = setTimeout(() => isDbClick = false, dbCheckCancelTime);
} else {
lastClickTime = nowTime;
clickTimer = setTimeout(() => {
// console.log('单击')
console.log('单击')
bus.emit('singleClick')
}, checkTime);
}
lastClickTime = nowTime;
}
el.addEventListener('click', check)
},
},
},
}