daShangDao_scanBook/uni_modules/ima-camera-view/readme.md

20 KiB
Raw Blame History

原生自定义相机拍照、视频录制 ima-camera-view

原生自定义相机拍照、视频录制 ima-camera-view是基于原生相机开发的UTS插件支持相机拍照视频录制 、可实现点击聚焦手势缩放自定义布局自定义蒙版(用于人脸拍照,身份证拍照等)。

⚠️注意️

由于之前技术选型不支持继续扩展相机的新特性,本插件ima-camera-view继续维护只修复现存的一些bug不再新增新功能 建议使用ima-camerax-view这个相机组件插件ima-camerax-view 地址 如果不追求如:超广角镜头切换0.5xchangeWideAngle按倍率缩放(setCameraZoom,如 0.5 / 1.0 / 2.0多摄逻辑镜头切换Camera2 白平衡 / HDR / 曝光补偿录像进度(onVideoTakenProgress)与设备方向变化(onOrientationChanged)回调等新特性的话,扔建议继续使用本插件。

  • ima-camerax-view【新插件】插件地址
  • ima-camera-view【本插件】插件地址
  • ima-camerax-view【新插件】ima-camera-view【本插件】组件 API 保持基本一致,便于从 CameraView 版平滑迁移

支持功能

  • 打开、关闭摄像头预览
  • 拍照、快照拍照
  • 录制视频、快照录制视频
  • 设置摄像头缩放级别
  • 设置相机白平衡
  • 设置相机HDR
  • 设置相机曝光
  • 设置摄像头方向
  • 设置闪光灯模式
  • 设置相机使用设备方向
  • 设置相机网格及颜色
  • 设置音频(录制视频时)
  • 设置圆角、圆预览(可自定义)
  • 外接摄像头预览方向修正(previewRotationAndroid
  • 设置拍照、录制视频的声音(可自定义)
  • 蓝牙自拍杆(可自定义)
  • 手机快捷键(可自定义)

自定义调整

  • 自定义调整页面地址:uni_modules/ima-camera-view/utssdk/app-android/index.vue
  • 蓝牙自拍杆、手机快捷键的自定义,可以参考文件中的shortcutListener方法
  • 设置拍照、录制视频的声音,可以参考文件中的photoSoundvideoSound方法

需要权限

  • 摄像头、音频、文件读取、文件写入、震动
"android.permission.CAMERA",
"android.permission.RECORD_AUDIO",
"android.permission.VIBRATE"
"android.permission.READ_EXTERNAL_STORAGE"
"android.permission.WRITE_EXTERNAL_STORAGE"
  • 即:在manifest.json中的distribute.android.permissions加入
// 拍摄照片和视频时需要
<uses-permission android:name="android.permission.CAMERA" /> 
// 拍摄视频时需要Audio.ON默认
<uses-permission android:name="android.permission.RECORD_AUDIO" /> 
// 读取拍照、录像文件文件时需要
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
// 报错拍照、录像文件文件时需要(默认保存到沙盒缓存)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
// 震动权限
<uses-permission android:name="android.permission.VIBRATE" />

快门声音素材

  • 将需要的快门声音放在uni_modules/ima-camera-view/utssdk/app-android/assets下即可
  • 熊猫办公
  • 站长素材

使用示例【此示例的代码只实现了相机拍照的逻辑,更多示例请导入项目】

  • 新建一个camera.nvue的文件
  • ⚠️注意️:只能在.nvue.uvue的文件后缀下才生效,不支持.vue
<template>
	<view class="ima-camera" :style="{ width: windowWidth, height: windowHeight }">
		<ima-camera-view
			ref="cameraRef"
			class="camera-view"
			:style="{ width: windowWidth + 'px', height: windowHeight + 'px' }"
			flash="on"
			@onPictureTaken="onPictureTaken"
			onFocusStart="onFocusStart"
		/>
		<view class="camera-menu">
			<!--返回键-->
			<cover-image @tap="back" class="camera-menu-button back" src="/static/camera/back.png" />
			<!--快门键-->
			<cover-image
				@tap="takePhoto"
				class="camera-menu-button shutter"
				src="/static/camera/shutter.png"
			/>
			<!--反转键-->
			<cover-image @tap="flip" class="camera-menu-button flip" src="/static/camera/flip.png" />
		</view>
	</view>
</template>

<script>
let _this = null
export default {
	data() {
		return {
			windowWidth: '', //屏幕可用宽度
			windowHeight: '', //屏幕可用高度
			facing: 'back'
		}
	},
	onLoad() {
		_this = this
		this.initCamera()
	},
	methods: {
		//初始化相机
		initCamera() {
			console.log('初始化相机')
			uni.getSystemInfo({
				success: (res) => {
					_this.windowWidth = res.windowWidth
					_this.windowHeight = res.windowHeight
				}
			})
		},
		onFocusStart(e) {
			console.log('聚焦', e)
		},
		takePhoto() {
			console.log('拍照', this.facing)
			this.$refs.cameraRef.takePhoto()
		},
		//返回
		back() {
			console.log('返回上一页', this.facing)
			uni.navigateBack()
		},
		//反转
		flip() {
			console.log('镜头反转', this.facing)
			this.facing = this.facing === 'back' ? 'front' : 'back'
			this.$refs.cameraRef.changeFacing(this.facing)
		},
		onPictureTaken(e) {
			console.log('拍照结果', e.detail)
			_this.snapshotsrc = e.detail?.path || ''
			_this.getTakenRes()
			uni.navigateBack()
		},
		//设置
		getTakenRes() {
			console.log('返回结果给上一页')
			let pages = getCurrentPages()
			let prevPage = pages[pages.length - 2] //上一个页面
			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
			prevPage.$vm.setImage({ path: _this.snapshotsrc })
		}
	}
}
</script>

<style lang="scss">
.ima-camera {
	justify-content: center;
	align-items: center;

	.camera-view {
		width: 100%;
		background: #111;
	}

	.camera-menu {
		position: absolute;
		left: 0;
		bottom: 0;
		width: 750rpx;
		height: 180rpx;
		z-index: 98;
		align-items: center;
		justify-content: center;

		&-button {
			width: 80rpx;
			height: 80rpx;
			position: absolute;
			bottom: 50rpx;
			z-index: 99;
			align-items: center;
			justify-content: center;
		}

		.back {
			left: 30rpx;
		}

		.shutter {
			width: 130rpx;
			height: 130rpx;
			left: 310rpx;
			bottom: 25rpx;
		}

		.flip {
			right: 30rpx;
		}
	}
}
</style>

外接摄像头方向修正Android

适用于无内置摄像头或外接 USB 摄像头的设备(如横屏平板、工控一体机)。当物理安装的摄像头与屏幕方向不一致,导致预览画面旋转 90° 等情况时,可通过 previewRotation 固定修正预览与拍照方向。

使用方式

方式一:属性(推荐)

<ima-camera-view
  ref="cameraRef"
  :previewRotation="90"
  :previewCornerRadiusRate="0.5"
  facing="front"
/>

方式二:方法动态调整

this.$refs.cameraRef.changePreviewRotation(90)   // 顺时针 90°
this.$refs.cameraRef.changePreviewRotation(-90)  // 逆时针 90°等价 270°

参数说明

取值 说明
0 不修正(默认)
90 / -270 顺时针旋转 90°
180 / -180 旋转 180°
270 / -90 顺时针旋转 270°逆时针 90°

注意事项

  • android 端生效;与 orientation(设备方向跟随)不同,previewRotation 用于固定补偿外接摄像头安装角度,不随手机旋转而改变。
  • 启用非 0previewRotation 后,组件会自动使用 TextureView 预览;拍照结果会同步叠加该角度修正。
  • 若预览方向仍不对,请依次尝试 90-90180,以实际安装方向为准。
  • 录像方向暂未做同等叠加修正;若录像也有方向问题,可在业务层二次处理或反馈 issue。

常见的比例的定义widthRatioheightRatio

// 正方形
AspectRatio.of(1, 1)      // 1:1

// 竖屏比例
AspectRatio.of(9, 16)     // 9:16 (手机竖屏)
AspectRatio.of(3, 4)      // 3:4
AspectRatio.of(2, 3)      // 2:3
AspectRatio.of(10, 16)    // 10:16 (5:8)

// 横屏比例
AspectRatio.of(16, 9)     // 16:9 (宽屏)
AspectRatio.of(4, 3)      // 4:3 (传统)
AspectRatio.of(3, 2)      // 3:2 (照片)
AspectRatio.of(16, 10)    // 16:10 (8:5)
AspectRatio.of(21, 9)     // 21:9 (超宽屏)

// 建议比例
const AspectRatios = {
  // 1:1 正方形
  SQUARE: AspectRatio.of(1, 1),
  // 9:16 竖屏(手机默认)
  PORTRAIT: AspectRatio.of(9, 16),
  // 16:9 横屏
  LANDSCAPE: AspectRatio.of(16, 9),
  // 3:4 传统照片比例
  THREE_FOUR: AspectRatio.of(3, 4),
  // 4:3 传统相机比例
  FOUR_THREE: AspectRatio.of(4, 3)
}

不同场景的推荐值tolerance

const TOLERANCE = {
  STRICT: 0.01.toFloat(),    // 非常严格,几乎精确匹配
  STANDARD: 0.05.toFloat(),  // 标准,推荐使用
  FLEXIBLE: 0.1.toFloat(),   // 灵活,兼容更多设备
  LOOSE: 0.2.toFloat()       // 宽松,可能匹配到意外比例
}

Api

属性 类型 默认值 说明 平台
widthRatio Number 0 照片尺寸比率(宽度): 默认全屏若widthRatio为9heightRatio为16则为9:16、widthRatio为3heightRatio为4则为3:4...不建议值过大常用的比例有1:1、3:4、4:3、9:16... android
heightRatio Number 0 照片尺寸比率(高度): 默认全屏若widthRatio为9heightRatio为16则为9:16、widthRatio为3heightRatio为4则为3:4...不建议值过大常用的比例有1:1、3:4、4:3、9:16... android
tolerance Number 0.1 照片尺寸容差值: 建议设为 0.05~0.15,以便稍微兼容不同设备相机实际比例差异 ,值为:01 android
whiteBalance iWhiteBalance "auto" 白平衡模式: auto自动、incandescent白炽、fluorescent荧光、daylight日光、cloudy多云 、loudy多云【慎用兼容1.1.3版本前单词拼错的问题将在1.2.0大版本更新后删除建议1.1.3后的版本使用cloudy】) android
hdr iHdr "off" HDR模式: off关闭、on开启 android
facing iFacing "back" 后置、前置摄像头: back(后置摄像头)、front(前置摄像头) android
flash iFlash "off" 闪光灯: off(关闭)、on(开启)、auto(自动)、torch(常开) android
audio iAudio "on" 音频: on(开启)、off(关闭)、mono(单声道)、stereo(立体声) android
orientation iOrientation "auto" 方向: auto(自动)、portrait(竖屏)、landscape(横屏) 【注意:目前竖屏、横屏拍出来都为竖屏方式,这两个参数的使用效果一致,为预留参数,为后期做准备】 android
grid iGrid "off" 网格: off(关闭)、draw_3X3(3x3)、draw_4x4(4x4)、draw_phi(phi) android
gridColor String "#808080" 颜色值: 只支持如:#fff、#ffffff、#......等类型的颜色值 android
photoSuffix iPhotoSuffix "jpeg" 照片格式: jpeg、jpg android
mode String 'picture' 相机模式: picture(拍照)、video(录视频) android
previewCornerRadius Number 0 预览圆角半径pxpreviewCornerRadiusRate 二选一或组合使用 android
previewCornerRadiusRate Number 0 预览圆角比例(相对短边);0.5 且预览区域为正方形时为圆形预览 android
previewRotation Number 0 外接摄像头预览/拍照方向修正角度:090180270(支持负值如 -90);详见上文「外接摄像头方向修正」 android
gallery Boolean false 是否将拍照、录像文件保存到系统相册(可见媒体库) android
shutter Boolean true 是否打开拍照声音: true(开启,此时配置sound才起作用)、false(关闭) android
sound String '' 相机拍照声音文件: 将mp3音频文件放在uni_modules/ima-camera-view/utssdk/app-android/assets下即可,为音频文件的名称,如xxx.mp3,默认手机原声 android
recorder Boolean true 是否打开录像声音: true(开启,此时配置sound2才起作用)、false(关闭) android
sound2 String '' 相机录像声音文件: 将mp3音频文件放在uni_modules/ima-camera-view/utssdk/app-android/assets下即可,为音频文件的名称,如xxx.mp3,默认手机原声 android
vibrate Boolean false 是否打开拍照震动: true(开启,此时配置duration才起作用)、false(关闭) android
duration Number 300 是否打开拍照震动时长单位毫秒ms android
shortcut Boolean false 是否开启蓝牙自拍杆、手机快捷键拍照: false(关闭)、true(开启) android

方法

共同 方法/* */

方法名称 说明 方法参数 平台
open 打开摄像头预览 android
close 关闭摄像头预览 android
takePhoto 拍照(标准拍照流程) android
takeVideo(duration) 开始录制视频 duration:拍摄时长单位毫秒ms【0 表示不限制】 android
stopVideo 停止视频录制 android
changeZoom(zoom) 设置摄像头缩放级别 zoom:缩放倍数(浮点数) android
changeExposure(exposure) 设置曝光值 exposure:曝光值(浮点数)【值为:-22默认为0】 android
changeWhiteBalance(whiteBalance) 设置相机白平衡 whiteBalance:参考api中的whiteBalance参数 android
changeHdr(hdr) 设置相机HDR hdr:参考api中的hdr参数 android
changeFacing((facing)) 设置摄像头方向 facing:参考api中的facing参数 android
changeFlash(flash) 设置闪光灯模式 flash:参考api中的flashs参数 android
changeOrientation(orientation) 设置相机使用设备方向 orientation:参考api中的orientations参数 android
changeGrid(grid,color) 设置相机网格及颜色 grid:参考api中的grid参数, color: 参考api中的gridColor参数 android
changeAudio(audio) 设置音频 audio:参考api中的audio参数 android
changeSuffix(suffix) 设置照片输出格式 suffix:参考api中的photoSuffix参数 android
changeSizeSelectors(width,height,tolerance) 设置相机特定比例/分辨率 width、height、tolerance 参考 api 中同名属性;0 表示使用屏幕宽高 android
changePreviewCorner(radius,radiusRate) 设置预览圆角 radius: 圆角 pxradiusRate: 圆角比例(正方形下 0.5 为圆形) android
changePreviewRotation(degrees) 设置外接摄像头预览/拍照方向修正 degrees: 0 / 90 / 180 / 270(支持负值);仅 Android android
changeGallery(gallery) 是否保存到系统相册 gallery: true / false android
changeMode(mode) 设置相机模式 mode: picture / video;也可直接使用 :mode prop android
takePhotoSnapshot 快照拍照(适用于快速拍照场景) android
takeVideoSnapshot(duration) 快照方式录制视频 duration:拍摄时长单位毫秒ms【0 表示不限制】 android

事件

事件名称 说明 回调参数 平台
onPictureTaken 拍照返回数据 ({path,width,height}: any) => {} android
onVideoTakenStart 录制视频开始事件 () => {} android
onVideoTakenEnd 录制视频结束事件 ({path,size}: any) => {} android
onFocusStart 自动对焦开始 ({x,y}: any) => {} android
onFocusEnd 自动对焦结束 ({x,y,focus}: any) => {} android
onOrientationChange 设备方向变化 ({angle,orientation,isPortrait,isLandscape}: any) => {} android
onCameraOpened 相机已打开 (data: any) => {} android
onCameraClosed 相机已关闭 (data: any) => {} android
onCameraError 相机错误 ({errorCode,reason,message}: any) => {} android