VUE3 移动端自制左右滑动预览视频和图片

视频组件:vue3-video-play。
用的是vant。本来用的是vant的图片预览组件进行改造的,以便预览图片和视频,后来发现体验太差,于是自己写了一套demo。
主要注意点就是切换的时候要销毁视频,使其重新加载,以免卡顿。
注:右上角还需要一个关闭按钮,有需要的自己添加吧,方法有:webCloseMedia,页面样式没写

<script setup>
import { ref, computed, reactive} from 'vue';
import 'vue3-video-play/dist/style.css';
import { videoPlay } from 'vue3-video-play';
const emit = defineEmits(['update:showPreview']);

const props = defineProps({
	images: { // 文件数组,[地址一,地址二,地址三...]
		type: Array,
		required: true
	},
	startPosition: {// 从第几个开始
		type: Number,
		default: () => { return 0; }
	},
	showPreview: {
		type: Boolean,
		required: true
	}
});

const _showPreview = computed({
	get() {
		return props.showPreview;
	},
	set(val) {
		emit('update:showPreview', val);
	}
});

const currentIndex = ref(props.startPosition);// 当前显示第几张
const showVideodom = ref(true);//是否显示视频

// 播放器配置
const options = reactive({
	width: '100%', //播放器高度
	height: '100%', //播放器高度
	// fullScreen: true,//网页全屏
	controlBtns: [
		'fullScreen',//全屏按钮
	]
});

/**********************滑动方法配置 ***************************/
const startX = ref(0);
const startY = ref(0);
const endX = ref(0);
const endY = ref(0);
const dValueX = ref(0);
const dValueY = ref(0);
const translateX = ref(0);
const horizontalMoved = ref(false);
const verticalMoved = ref(false);

const onTouchStart = (e) => {
	startX.value = e.targetTouches[0].pageX; startY.value = e.targetTouches[0].pageY;
};

const onTouchMove = (e) => {
	endX.value = e.targetTouches[0].pageX; endY.value = e.targetTouches[0].pageY;
	dValueX.value = Math.abs(startX.value - endX.value); dValueY.value = Math.abs(startY.value - endY.value);
	const stopRange = window.screen.width - window.screen.width / 3.5;
	if (dValueX.value > dValueY.value) {
		if (verticalMoved.value) { e.preventDefault(); return; }
		else horizontalMoved.value = true;
		if (dValueX.value < stopRange) {
			if (startX.value > endX.value) {
				if (!props.leftDisabled)
					translateX.value = dValueX.value * -1;
			} else {
				if (!props.rightDisabled) translateX.value = dValueX.value;
			}
		} e.preventDefault();
	} else { if (horizontalMoved.value) e.preventDefault(); else verticalMoved.value = true; }
};

const onTouchEnd = (e) => {
	const range = window.screen.width / 3;
	if (horizontalMoved.value) {
		if (dValueX.value > range) {
			if (startX.value > endX.value) {
				if (!props.leftDisabled) handleChange('left');
			} else if (startX.value < endX.value) {
				if (!props.rightDisabled) handleChange('right');
			}
		}
	} 
	horizontalMoved.value = false;
	verticalMoved.value = false;
	translateX.value = 0;
	startX.value = endX.value = 0;
	startY.value = endY.value = 0;
};
/**********************end 滑动方法配置 ***************************/
// 右上角关闭按钮事件
const webCloseMedia = () => {
	emit('update:showPreview', false);
};
/**
 * @description: 滑动使用的方法
 * @param {String} value left:左滑   right:右滑
 */
const handleChange = (value) => {
	const len = props.images.length;
	// 只有一个文件的时候不做反应
	if (len === 1) {
		return false;
	}
	showVideodom.value = false;// 模板中用v-if来销毁和展示视频组件
	if ('left' === value) {
		if (currentIndex.value + 1 === len) {
			currentIndex.value = 0;
		} else {
			++currentIndex.value;
		}
	} else if ('right' === value) {
		if (currentIndex.value === 0) {
			currentIndex.value = len - 1;
		} else {
			--currentIndex.value;
		}
	}
	setTimeout(() => {
		showVideodom.value = true;
	}, 200);
};

</script>
<template>
  <van-overlay
    v-model:show="_showPreview" :custom-style="{ background: 'rgba(0,0,0,1)!important' }"
    lazy-render :lock-scroll="false"
  >    
    <div
      v-if="showVideodom" class="pre-style" @touchstart="onTouchStart" @touchmove="onTouchMove"
      @touchend="onTouchEnd"
    >
    <!-- 我这里只判断了mp4 mov MOV 格式 -->
      <videoPlay
        v-if="images[currentIndex].endsWith('mp4') || images[currentIndex].toLocaleLowerCase().endsWith('mov')"
        v-model:show="_showPreview" :src="images[currentIndex]" autoplay v-bind="options"
      />
      <img v-else :src="images[currentIndex]" style="width: 100%;height: 100%;">
    </div>
  </van-overlay>
</template>
<style lang="less" scoped>
.pre-style {
	width: 100%;
	height: 100%;
}
</style>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值