uniapp+Vue3自定义扫码页面

211 阅读1分钟

很久没有更新文章了,写一篇自定义扫描的文章

<!-- 扫一扫页面 -->
<template>
	<view class="scan-view">
		<view class="scan-border">
			<camera class="scan-camera" @scancode="handleScancode" @error="handleError" mode="scanCode"
				device-position="back" flash="off">
				<cover-view class="scan-animation" :animation="animationData"></cover-view>
				<cover-view class="scan-pict">
					<cover-image @click="handlePhoto" class="pic" src="/static/openXc.png"></cover-image>
				</cover-view>
			</camera>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		onMounted,
		onUnmounted
	} from 'vue'
	import {
		onShow,
		onHide,
		onLoad
	} from '@dcloudio/uni-app'

	// 动画实例
	const animation = uni.createAnimation({})
	const animationData = ref(null)

	// 音频实例
	const innerAudioContext = uni.createInnerAudioContext()
	innerAudioContext.autoplay = true

	// 状态
	const hasScan = ref(false)

	// 从相册选择图片
	const handlePhoto = () => {
		uni.chooseImage({
			count: 1,
			sizeType: ["original", "compressed"],
			sourceType: ["album"],
			success: (res) => {
				console.log(JSON.stringify(res.tempFilePaths))
			}
		})
	}

	// 动画效果
	const startAnimation = () => {
		let direction = true
		const interval = setInterval(() => {
			if (direction) {
				animation.translateY(250).step({
					duration: 1500
				})
			} else {
				animation.translateY(-10).step({
					duration: 1500
				})
			}
			direction = !direction
			animationData.value = animation.export()
		}, 1500)

		return interval
	}

	// 扫码处理
	const handleScancode = (e) => {
		console.log('扫码结果:', e.detail.result)
		uni.navigateBack({
			delta: 1 // 返回上一页
		});
	}

	// 错误处理
	const handleError = (e) => {
		console.error('相机错误:', e)
	}

	// 生命周期
	let animationInterval

	onMounted(() => {
		animationInterval = startAnimation()
	})

	onShow(() => {
		animationInterval = startAnimation()
	})
	onLoad((options) => {
		console.log('相机options', options)
	})

	onHide(() => {
		hasScan.value = false
		clearInterval(animationInterval)
	})

	onUnmounted(() => {
		hasScan.value = false
		clearInterval(animationInterval)
		innerAudioContext.destroy()
	})
</script>

<style lang="scss" scoped>
	.scan-view {
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		background-color: #ffffff;
		position: fixed;
		align-items: center;
		justify-content: space-around;
	}

	.scan-border {
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
		align-items: center;

		.scan-camera {
			width: 100%;
			height: 86.4%;
			border-radius: 6rpx;
		}
	}

	.scan-animation {
		position: absolute;
		top: 24%;
		left: 20%;
		width: 480rpx;
		height: 8rpx;
		background-color: #0091ff;
		border-radius: 50%;
	}

	.scan-pict {
		position: absolute;
		right: 1%;
		bottom: 1%;
		width: 70rpx;
		height: 70rpx;
		z-index: 20;
		border-radius: 50%;
		background-color: #c0c0c0;
		opacity: 0.8;

		.pic {
			z-index: 999;
			width: 50rpx;
			height: 50rpx;
			margin: 10rpx;
		}
	}
</style>