效果图
<template>
<view v-if="info" class="all">
<video
:src="info.videoUrl"
class="video" id="video" :controls="true" object-fit="fill" :show-fullscreen-btn="false"
play-btn-position="center"
:autoplay="true" @loadedmetadata="loadedMetadata"></video>
<view class="slider">
<view class="thumb-left" @touchmove="e=>handleTouchMove(e,0)" @touchend="e=>handleTouchEnd(e,0)"
:style="` margin-left: ${thumbLeft}px;`">{{ start }}
</view>
<view class="slider-bg"></view>
<view class="thumb-right" @touchmove="e=>handleTouchMove(e,1)" @touchend="e=>handleTouchEnd(e,1)"
:style="` margin-right: ${thumbRight}px;`">{{ end }}
</view>
</view>
</view>
</template>
<script lang="ts" setup>
const videoInfo = defineProps(["info"])
const emit = defineEmits(['onChange'])
import {ref, computed, onMounted, getCurrentInstance} from "vue";
import {
onReady,
} from "@dcloudio/uni-app"
const min = ref(0)
const max = ref(0)
const minInterval = ref(15)//最小裁剪间隔
const thumbLeft = ref(0)
const thumbRight = ref(0)
const start = ref(computed(() => {
return Math.round((thumbLeft.value) * rate.value)
}))
const end = ref(computed(() => {
return Math.round((totalWidth.value - thumbRight.value) * rate.value)
}))
const rate = ref(computed(() => {
return max.value / totalWidth.value
}))
const interval = ref(computed(() => {
return minInterval.value / rate.value
}))
const instance = getCurrentInstance()
const thumbLeftSize = ref({
width: 0,
height: 0,
left: 0,
right: 0
})
const thumbRightSize = ref({
width: 0,
height: 0,
left: 0,
right: 0
})
let dxLeft = 0
let dxRight = 0
const totalWidth = ref(0)
const videoTotalDuration = ref(0)
let videoContext: UniApp.VideoContext = null
let windowWidth = 0
let timer: number = null
function loadedMetadata(e) {
max.value = Math.floor(e.detail.duration)
emit('onChange', {start: start.value, end: end.value})
}
onReady(() => {
videoContext = uni.createVideoContext('video', instance);
windowWidth = uni.getSystemInfoSync().windowWidth
})
onMounted(() => {
uni.createSelectorQuery().in(instance).select('.thumb-left').boundingClientRect(data => {
console.log(data)
thumbLeftSize.value = data
console.log(thumbLeftSize.value)
}).exec();
uni.createSelectorQuery().in(instance).select('.thumb-right').boundingClientRect(data => {
console.log(data)
thumbRightSize.value = data
console.log(thumbRightSize.value)
totalWidth.value = thumbRightSize.value.right - thumbLeftSize.value.left - 2 * thumbLeftSize.value.width
}).exec();
});
function handleTouchMove(e, index: Number) {
let pageX = e.touches[0].pageX
if (index == 0) {
//左边边view
dxLeft = Math.max(pageX - thumbLeftSize.value.left, 0)
//修正
if (dxLeft + dxRight + interval.value > totalWidth.value) {
dxLeft = totalWidth.value - dxRight
}
console.log("pageX:" + pageX, "dxRight:" + dxRight, "dxLeft:" + dxLeft, "thumbRight:" + thumbRight.value, "thumbLeft:" + thumbLeft.value, "width:" + thumbLeftSize.value.width, "windowWidth:" + windowWidth, thumbRightSize.value.right, "totalWidth:" + totalWidth.value)
if (dxLeft <= interval.value) {
//左边边界
thumbLeft.value = 0
return
}
if (dxRight + dxLeft + interval.value > totalWidth.value) {
thumbLeft.value = windowWidth - thumbRight.value - 2 * thumbLeftSize.value.width - 2 * thumbLeftSize.value.left - interval.value
} else {
thumbLeft.value = dxLeft - interval.value
}
} else {
//右边view
dxRight = Math.max(windowWidth - pageX - thumbRightSize.value.width, 0)
//修正
if (dxRight + dxLeft + interval.value > totalWidth.value) {
dxRight = totalWidth.value - dxLeft
}
console.log("pageX:" + pageX, "dxRight:" + dxRight, "dxLeft:" + dxLeft, "thumbRight:" + thumbRight.value, "thumbLeft:" + thumbLeft.value, "width:" + thumbLeftSize.value.width, "windowWidth:" + windowWidth, thumbRightSize.value.right, "totalWidth:" + totalWidth.value)
if (dxRight <= interval.value) {
//右边边界
thumbRight.value = 0
return
}
if (dxRight + dxLeft + interval.value > totalWidth.value) {
//左边边界修正
thumbRight.value = windowWidth - thumbLeft.value - 2 * thumbLeftSize.value.width - 2 * thumbLeftSize.value.left - interval.value
} else {
thumbRight.value = dxRight - interval.value
}
}
}
function handleTouchEnd(e, index: Number) {
emit('onChange', {start: start.value, end: end.value})
videoContext.seek(index == 0 ? start.value : end.value);
videoContext.play();
}
</script>
<style lang="scss" scoped>
.all {
margin-left: 25rpx;
margin-right: 25rpx;
.video {
height: 400rpx;
width: 100%;
}
.slider {
display: flex;
color: white;
flex-direction: row;
height: 100rpx;
.thumb-left {
width: 50rpx;
height: 100%;
color: black;
display: flex;
font-size: 12rpx;
align-items: center;
justify-content: center;
background-color: #8EFB7C;
border-top-left-radius: 20rpx;
border-bottom-left-radius: 20rpx;
}
.slider-bg {
display: flex;
flex: 1;
background-color: #F1FFF0
}
.thumb-right {
width: 50rpx;
height: 100%;
color: black;
display: flex;
font-size: 12rpx;
align-items: center;
justify-content: center;
background-color: #8EFB7C;
border-top-right-radius: 20rpx;
border-bottom-right-radius: 20rpx;
}
}
}
</style>