camera.uvue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. <template>
  2. <view style="flex: 1;">
  3. <camera style="width: 100%; height: 300px;" :resolution="'medium'" :device-position="devicePosition"
  4. :flash="flash" :frame-size="frameSize" @stop="handleStop" @error="handleError" @initdone="handleInitDone">
  5. </camera>
  6. <scroll-view style="flex: 1;">
  7. <view>
  8. <button type="default" @click="handleScanCode">扫码</button>
  9. <button type="default" @click="switchDevicePosition">切换前后摄像头</button>
  10. <button type="default" @click="switchFlash">闪光灯</button>
  11. <button type="default" @click="setOnFrameListener">设置帧数据监听</button>
  12. <button type="default" @click="startFrameListener">开始捕捉帧数据</button>
  13. <button type="default" @click="stopFrameListener">停止捕捉帧数据</button>
  14. <view>
  15. <view class="uni-title">
  16. <text class="uni-title-text">设置预览缩放</text>
  17. </view>
  18. <view class="uni-camera-wrapper">
  19. <slider class="uni-camera-test-host" :disabled="maxZoom == 0" :show-value="true" :min="1"
  20. :max="maxZoom" :value="1" @change="zoomSliderChange" />
  21. </view>
  22. </view>
  23. <view>
  24. <view class="uni-title">
  25. <text class="uni-title-text">拍摄照片示例</text>
  26. <button type="default" @click="handleTakePhoto">拍摄照片</button>
  27. <radio-group style="flex-direction: row;" name="成像质量" @change="takePhotoQualityChange">
  28. <radio value="normal" :checked="true">普通质量</radio>
  29. <radio value="low">低质量</radio>
  30. <radio value="high">高质量</radio>
  31. <radio value="original">原图</radio>
  32. </radio-group>
  33. </view>
  34. <view class="uni-camera-wrapper">
  35. <image class="uni-camera-test-host-without-flex" style="width: 150px;height: 150px;"
  36. v-if="imageSrc != ''" :src="imageSrc"></image>
  37. </view>
  38. </view>
  39. <view>
  40. <view class="uni-title">
  41. <text class="uni-title-text">录制视频示例</text>
  42. <view style="flex-direction: row;margin-top: 8px;">
  43. <text class="uni-title-size">录制时长:</text>
  44. <input class="uni-title-size"
  45. style="width: 50px; margin-left: 10px;border: 0.5px solid grey;text-align: right;"
  46. type="number" @input="timeoutInput" :value="timeout" />
  47. <text class="uni-title-size" style="margin-left: 8px;">秒</text>
  48. </view>
  49. <button type="default" style="font-family: monospace;margin-top: 8px;" @click="startRecord"
  50. :disabled="startRecordStatus">{{ startRecordStatus ? `${remain}秒` : "录制视频" }}</button>
  51. <button type="default" @click="stopRecord">停止录制</button>
  52. <radio-group style="flex-direction: row;margin-top: 8px;" name="是否压缩"
  53. @change="startRecordCompressChange">
  54. <radio value="0" :checked="true">未启动视频压缩</radio>
  55. <radio value="1">启动视频压缩</radio>
  56. </radio-group>
  57. </view>
  58. <view class="uni-camera-wrapper">
  59. <video class="uni-camera-test-host-without-flex" style="width: 300px;height: 300px;"
  60. v-if="videoSrc != ''" :src="videoSrc" :controls="true"></video>
  61. </view>
  62. </view>
  63. </view>
  64. </scroll-view>
  65. </view>
  66. </template>
  67. <script>
  68. export default {
  69. data() {
  70. return {
  71. devicePosition: "back",
  72. flash: "off",
  73. frameSize: "medium",
  74. listener: null as CameraContextCameraFrameListener | null,
  75. maxZoom: 0,
  76. imageSrc: "",
  77. quality: "normal",
  78. timeout: 30,
  79. compressed: false,
  80. videoSrc: "",
  81. startRecordStatus: false,
  82. remain: 0,
  83. intervalId: -1,
  84. timeoutStr: '30'
  85. }
  86. },
  87. onLoad() {
  88. },
  89. methods: {
  90. handleScanCode() {
  91. uni.navigateTo({
  92. url:"/pages/component/camera/camera-scan-code"
  93. })
  94. },
  95. switchDevicePosition() {
  96. this.devicePosition = this.devicePosition == "back" ? "front" : "back"
  97. },
  98. switchFlash() {
  99. this.flash = this.flash == "torch" ? "off" : "torch"
  100. },
  101. handleStop(e : UniCameraStopEvent) {
  102. console.log("stop", e.detail);
  103. },
  104. handleError(e : UniCameraErrorEvent) {
  105. console.log("error", e.detail);
  106. },
  107. handleInitDone(e : UniCameraInitDoneEvent) {
  108. console.log("initdone", e.detail);
  109. this.maxZoom = e.detail.maxZoom ?? 0
  110. },
  111. zoomSliderChange(event : UniSliderChangeEvent) {
  112. const value = event.detail.value
  113. const context = uni.createCameraContext();
  114. context?.setZoom({
  115. zoom: value,
  116. success: (e : any) => {
  117. console.log(e);
  118. }
  119. } as CameraContextSetZoomOptions)
  120. },
  121. handleTakePhoto() {
  122. const context = uni.createCameraContext();
  123. context?.takePhoto({
  124. quality: this.quality,
  125. selfieMirror: false,
  126. success: (res : CameraContextTakePhotoResult) => {
  127. console.log("res.tempImagePath", res.tempImagePath);
  128. this.imageSrc = res.tempImagePath ?? ''
  129. },
  130. fail: (e : any) => {
  131. console.log("take photo", e);
  132. }
  133. } as CameraContextTakePhotoOptions)
  134. },
  135. takePhotoQualityChange(event : UniRadioGroupChangeEvent) {
  136. this.quality = event.detail.value
  137. console.log("quality", this.quality);
  138. },
  139. setOnFrameListener() {
  140. const context = uni.createCameraContext();
  141. this.listener = context?.onCameraFrame((frame : CameraContextOnCameraFrame) => {
  142. console.log("OnFrame :", frame);
  143. })
  144. },
  145. startFrameListener() {
  146. this.listener?.start({
  147. success: (res : any) => {
  148. console.log("startFrameListener success", res);
  149. }
  150. } as CameraContextCameraFrameListenerStartOptions)
  151. },
  152. stopFrameListener() {
  153. this.listener?.stop({
  154. success: (res : any) => {
  155. console.log("stopFrameListener success", res);
  156. }
  157. } as CameraContextCameraFrameListenerStopOptions)
  158. },
  159. startRecord() {
  160. const context = uni.createCameraContext();
  161. let timeout = this.getTimeout()
  162. this.timeout = timeout
  163. context?.startRecord({
  164. timeout: timeout,
  165. selfieMirror: false,
  166. timeoutCallback: (res : any) => {
  167. console.log("timeoutCallback", res);
  168. this.startRecordStatus = false
  169. if (typeof res != "string") {
  170. const result = res as CameraContextStartRecordTimeoutResult
  171. this.videoSrc = result.tempVideoPath ?? ''
  172. }
  173. clearInterval(this.intervalId)
  174. },
  175. success: (res : any) => {
  176. this.startRecordStatus = true
  177. console.log("start record success", res);
  178. this.remain = timeout
  179. this.intervalId = setInterval(() => {
  180. if (this.remain <= 0) {
  181. clearInterval(this.intervalId)
  182. } else {
  183. this.remain--
  184. }
  185. }, 1000)
  186. },
  187. fail: (res : any) => {
  188. console.log("start record fail", res);
  189. this.startRecordStatus = false
  190. this.remain = 0
  191. clearInterval(this.intervalId)
  192. }
  193. } as CameraContextStartRecordOptions)
  194. },
  195. stopRecord() {
  196. this.startRecordStatus = false
  197. const context = uni.createCameraContext();
  198. context?.stopRecord({
  199. compressed: this.compressed,
  200. success: (res : CameraContextStopRecordResult) => {
  201. console.log("stop record success", res);
  202. this.videoSrc = res.tempVideoPath ?? ''
  203. },
  204. fail: (res : any) => {
  205. console.log("stop record fail", res);
  206. }
  207. } as CameraContextStopRecordOptions)
  208. clearInterval(this.intervalId)
  209. this.remain = 0
  210. },
  211. startRecordCompressChange(event : UniRadioGroupChangeEvent) {
  212. this.compressed = parseInt(event.detail.value) == 1
  213. },
  214. timeoutInput(event : UniInputEvent) {
  215. this.timeoutStr = event.detail.value
  216. },
  217. getTimeout() : number {
  218. let value = parseInt(this.timeoutStr)
  219. // #ifdef APP-ANDROID
  220. if (value == NaN) {
  221. // #endif
  222. // #ifndef APP-ANDROID
  223. if (value !== value) {
  224. // #endif
  225. return 30
  226. } else {
  227. if (value < 1) {
  228. return 1
  229. } else if (value > 60 * 5) {
  230. return 60 * 5
  231. } else {
  232. return value
  233. }
  234. }
  235. }
  236. }
  237. }
  238. </script>
  239. <style>
  240. .uni-title {
  241. padding: 10px 0;
  242. }
  243. .uni-title-text {
  244. font-size: 15px;
  245. font-weight: bold;
  246. }
  247. .uni-camera-wrapper {
  248. display: flex;
  249. padding: 8px 13px;
  250. margin: 5px 0;
  251. flex-direction: row;
  252. flex-wrap: nowrap;
  253. background-color: #ffffff;
  254. }
  255. .uni-camera-test-host {
  256. height: 28px;
  257. padding: 0px;
  258. flex: 1;
  259. background-color: #ffffff;
  260. }
  261. .uni-camera-test-host-without-flex {
  262. height: 28px;
  263. padding: 0px;
  264. background-color: #ffffff;
  265. }
  266. .uni-title-size {
  267. font-size: 22px;
  268. }
  269. </style>