鴻蒙自定義相機的拍照頁面

1、權限申請

    "requestPermissions": [{"name": "ohos.permission.CAMERA","reason": "$string:reason_camera","usedScene": {"abilities": ["EntryAbility"]}},{"name": "ohos.permission.MEDIA_LOCATION","reason": "$string:reason_media_location","usedScene": {"abilities": ["EntryAbility"]}}]

2、ui實現

import { dataSharePredicates } from '@kit.ArkData';
import { abilityAccessCtrl, Permissions } from '@kit.AbilityKit';
import { camera } from '@kit.CameraKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { filePreview } from '@kit.PreviewKit';
import { cameraShooting, capture, getUriAsync, previewPhoto, setPhotoFlashMode } from '../utils/CameraShooter';
import display from '@ohos.display';
import { AppStorageV2, curves } from '@kit.ArkUI';
import { sensor } from '@kit.SensorServiceKit';
import { DegreeConstants } from '../constants/DegreeConstants'let cameraPosition = 0;
let surfaceId = '';
let context = getContext(this);@Entry
@ComponentV2
struct XComponentPage {mXComponentController: XComponentController = new XComponentController;permissions: Array<Permissions> = ['ohos.permission.CAMERA','ohos.permission.MEDIA_LOCATION',];@Local cameraMargin: number = 40@Local cameraHeight: number = 2560@Local isRatio: boolean = true; // true: 16 / 9@Local isFront: boolean = false;@Local photoUri: string | Resource | PixelMap = ''@Local isStabilization: boolean = false;@Local isMovingPhoto: boolean = false;@Local flashPic: ResourceStr = ''textTimerController: TextTimerController = new TextTimerController();@Local rotation: number = 0;@Local moreTools: ResourceStr[] = ['相冊', '拍照', '拍視頻']@BuilderbottomKeystrokeBuilder() {// 底部拍照翻轉相機Row() {Image(this.photoUri).borderWidth(this.photoUri === '' ? 0 : 1).borderColor(Color.White).height(70).width(70).borderRadius(35).rotate({ angle: this.rotation }).animation({ curve: curves.springMotion() }).onClick(() => {if (this.photoUri !== '') {previewPhoto(context);}})// 拍照Column() {Column() {}.width(60).height(60).backgroundColor('#0FD7B8').borderRadius(30)}.width(72).height(72).border({ width: 3, color: Color.White }).borderRadius(36).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).onClick(() => {capture(this.isFront);getUriAsync().then(photoUri => {// photoUri 就是你要的圖片uri// 可以賦值給 @State/@Local 變量,UI自動刷新this.photoUri = photoUri;console.log('hlasdlkas===' + this.photoUri)});})Column() {Text('翻轉').width(28).onClick(async () => {cameraPosition = cameraPosition === 1 ? 0 : 1cameraShooting(cameraPosition, surfaceId, context, this.isRatio);this.Initialize();this.isFront = cameraPosition !== 0;})}.height(70).width(70).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center)}.margin({ top: 20 }).width('100%').justifyContent(FlexAlign.SpaceAround).margin({ bottom: 39 })}@BuilderproportionBuilder() {Row({ space: 20 }) {Text('1:1').height(30).onClick(() => {this.cameraMargin = 100this.cameraHeight = 1440this.isRatio = falsecameraShooting(cameraPosition, surfaceId, context, this.isRatio);this.Initialize();})Text('9:16').height(30).onClick(() => {this.cameraHeight = 2560this.cameraMargin = 40this.isRatio = truecameraShooting(cameraPosition, surfaceId, context, this.isRatio);this.Initialize();})}.margin({ top: 500 })}onPageShow(): void {filePreview.closePreview(context);}async aboutToAppear() {sensor.on(sensor.SensorId.GRAVITY, (data: sensor.GravityResponse) => {let degree: number = -1;degree = this.getCalDegree(data.x, data.y, data.z);if (degree >= 0 && (degree <= DegreeConstants.DEGREE_ONE || degree >= DegreeConstants.DEGREE_FOUR)) {this.rotation = camera.ImageRotation.ROTATION_0;} else if (degree >= DegreeConstants.DEGREE_ONE && degree <= DegreeConstants.DEGREE_TWO) {this.rotation = camera.ImageRotation.ROTATION_270;} else if (degree >= DegreeConstants.DEGREE_TWO && degree <= DegreeConstants.DEGREE_THREE) {this.rotation = camera.ImageRotation.ROTATION_180;} else if (degree >= DegreeConstants.DEGREE_THREE && degree <= DegreeConstants.DEGREE_FOUR) {this.rotation = camera.ImageRotation.ROTATION_90;}})abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context, this.permissions).then(() => {setTimeout(async () => {await cameraShooting(cameraPosition, surfaceId, context, this.isRatio);}, 200);});}aboutToDisappear(): void {sensor.off(sensor.SensorId.GRAVITY);}getCalDegree(x: number, y: number, z: number): number {let degree: number = -1;if ((x * x + y * y) * 3 < z * z) {return degree;}degree = 90 - (Number)(Math.round(Math.atan2(y, -x) / Math.PI * 180));return degree >= 0 ? degree % 360 : degree % 360 + 360;}build() {Stack({ alignContent: Alignment.Top }) {XComponent({ type: XComponentType.SURFACE, controller: this.mXComponentController }).onLoad(async () => {// todo:切換比例,暫時用不到if (this.isRatio === true) {this.mXComponentController.setXComponentSurfaceRect({surfaceWidth: display.getDefaultDisplaySync().width,surfaceHeight: display.getDefaultDisplaySync().width * 16 / 9,offsetY: 0});surfaceId = this.mXComponentController.getXComponentSurfaceId();} else {this.mXComponentController.setXComponentSurfaceRect({surfaceWidth: display.getDefaultDisplaySync().width,surfaceHeight: display.getDefaultDisplaySync().width,});surfaceId = this.mXComponentController.getXComponentSurfaceId();}}).width(px2vp(1440)).height(px2vp(this.cameraHeight)).align(Alignment.Top)Column() {Column() {Row() {Text('x').width(24)Text('拍照').fontWeight(600)Text().width(24)}.width('100%').justifyContent(FlexAlign.SpaceBetween)//比例this.proportionBuilder()// 底部按鍵this.bottomKeystrokeBuilder()}.width('100%').height(px2vp(display.getDefaultDisplaySync().width * 16 / 9) - 10).justifyContent(FlexAlign.SpaceBetween)// 更多Row() {ForEach(this.moreTools, (item: ResourceStr, index: number) => {Text(item)})}.width('70%').layoutWeight(1).justifyContent(FlexAlign.SpaceBetween).alignItems(VerticalAlign.Center)}.height('100%').align(Alignment.Top).padding({ left: 14, right: 14, top: 10 })}.height('100%').width('100%').backgroundColor(Color.White).padding({ top: 50 }) //頂部安全區}Initialize(): void {this.isStabilization = false;this.isMovingPhoto = false;if (this.isRatio === true) {this.mXComponentController.setXComponentSurfaceRect({surfaceWidth: display.getDefaultDisplaySync().width,surfaceHeight: display.getDefaultDisplaySync().width * 16 / 9, offsetY: 0})} else {this.mXComponentController.setXComponentSurfaceRect({surfaceWidth: display.getDefaultDisplaySync().width,surfaceHeight: display.getDefaultDisplaySync().width})}}switchFlash(flashMode: number): void {setPhotoFlashMode(flashMode);}async getThumbnail(): Promise<void> {let predicates: dataSharePredicates.DataSharePredicates = new dataSharePredicates.DataSharePredicates();predicates.orderByDesc(photoAccessHelper.PhotoKeys.DATE_ADDED);let fetchOptions: photoAccessHelper.FetchOptions = {fetchColumns: [],predicates: predicates};let photoHelper = photoAccessHelper.getPhotoAccessHelper(context);let fetchResult: photoAccessHelper.FetchResult<photoAccessHelper.PhotoAsset> =await photoHelper.getAssets(fetchOptions);if (fetchResult !== undefined) {let photoAsset: photoAccessHelper.PhotoAsset = await fetchResult.getFirstObject();this.photoUri = await photoAsset.getThumbnail();}}
}

3、工具

import { camera } from '@kit.CameraKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { common } from '@kit.AbilityKit';
import { AppStorageV2, display } from '@kit.ArkUI';
import { colorSpaceManager } from '@kit.ArkGraphics2D';let previewOutput: camera.PreviewOutput;
let cameraInput: camera.CameraInput;
let photoSession: camera.PhotoSession;
let photoOutPut: camera.PhotoOutput;
let currentContext: Context;
let uri: string;
let uriWaiters: ((uri: string) => void)[] = [];export async function cameraShooting(cameraPosition: number, surfaceId: string, context: Context, ratio: boolean):Promise<number[]> {currentContext = context;releaseCamera();let cameraManager: camera.CameraManager = camera.getCameraManager(context);if (!cameraManager) {return [];}let cameraArray: camera.CameraDevice[] = cameraManager.getSupportedCameras();if (cameraArray.length <= 0) {return [];}cameraInput = cameraManager.createCameraInput(cameraArray[cameraPosition]);await cameraInput.open();let sceneModes: camera.SceneMode[] = cameraManager.getSupportedSceneModes(cameraArray[cameraPosition]);let cameraOutputCap: camera.CameraOutputCapability =cameraManager.getSupportedOutputCapability(cameraArray[cameraPosition], camera.SceneMode.NORMAL_PHOTO);let isSupportPhotoMode: boolean = sceneModes.indexOf(camera.SceneMode.NORMAL_PHOTO) >= 0;if (!isSupportPhotoMode) {return [];}if (!cameraOutputCap) {return [];}let previewProfilesArray: camera.Profile[] = cameraOutputCap.previewProfiles;let photoProfilesArray: camera.Profile[] = cameraOutputCap.photoProfiles;let previewProfile: undefined | camera.Profile = previewProfilesArray.find((profile: camera.Profile) => {let screen = display.getDefaultDisplaySync();if (screen.width <= 1080) {if (ratio === true) {return profile.size.height === 1080 && profile.size.width === 1920;} else {return profile.size.height === 1080 && profile.size.width === 1080;}} else {if (ratio === true) {return profile.size.height === 1440 && profile.size.width === 2560;} else {return profile.size.height === 1440 && profile.size.width === 1440;}}});let photoProfile: undefined | camera.Profile = photoProfilesArray.find((profile: camera.Profile) => {if (previewProfile) {return profile.size.width <= 4096 && profile.size.width >= 2448;}return undefined;});previewOutput = cameraManager.createPreviewOutput(previewProfile, surfaceId);if (previewOutput === undefined) {return [];}photoOutPut = cameraManager.createPhotoOutput(photoProfile);if (photoOutPut === undefined) {return [];}// Save PicturesetPhotoOutputCb(photoOutPut);photoSession = cameraManager.createSession(camera.SceneMode.NORMAL_PHOTO) as camera.PhotoSession;if (photoSession === undefined) {return [];}photoSession.beginConfig();photoSession.addInput(cameraInput);photoSession.addOutput(previewOutput);photoSession.addOutput(photoOutPut);photoSession.setColorSpace(colorSpaceManager.ColorSpace.DISPLAY_P3);await photoSession.commitConfig();await photoSession.start();let flashStatus: boolean = photoSession.hasFlash();if (flashStatus) {photoSession.setFlashMode(camera.FlashMode.FLASH_MODE_CLOSE);}let focusModeStatus: boolean = photoSession.isFocusModeSupported(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);if (focusModeStatus) {photoSession.setFocusMode(camera.FocusMode.FOCUS_MODE_CONTINUOUS_AUTO);}let zoomRatioRange = photoSession.getZoomRatioRange();return zoomRatioRange;
}export function capture(isFront: boolean): void {let settings: camera.PhotoCaptureSetting = {quality: camera.QualityLevel.QUALITY_LEVEL_HIGH,rotation: camera.ImageRotation.ROTATION_0,mirror: isFront};photoOutPut.capture(settings);
}export async function setPhotoFlashMode(flashMode: number): Promise<void> {photoSession.setFlashMode(flashMode);
}export async function releaseCamera(): Promise<void> {if (photoSession) {photoSession.stop();}if (cameraInput) {cameraInput.close();}if (previewOutput) {previewOutput.release();}if (photoSession) {photoSession.release();}if (photoOutPut) {photoOutPut.release();}
}function setPhotoOutputCb(photoOutput: camera.PhotoOutput): void {photoOutput.on('photoAssetAvailable',async (_err: BusinessError, photoAsset: photoAccessHelper.PhotoAsset): Promise<void> => {let accessHelper: photoAccessHelper.PhotoAccessHelper =photoAccessHelper.getPhotoAccessHelper(currentContext);let assetChangeRequest: photoAccessHelper.MediaAssetChangeRequest =new photoAccessHelper.MediaAssetChangeRequest(photoAsset);assetChangeRequest.saveCameraPhoto();await accessHelper.applyChanges(assetChangeRequest);uri = photoAsset.uri;// AppStorage.setOrCreate('photoUri', await photoAsset.getThumbnail());uriWaiters.forEach(fn => fn(uri));uriWaiters = [];});
}export function getUriAsync(): Promise<string> {return new Promise(resolve => {uriWaiters.push(resolve);});
}export function previewPhoto(context: Context): void {let photoContext = context as common.UIAbilityContext;photoContext.startAbility({parameters: { uri: uri },action: 'ohos.want.action.viewData',bundleName: 'com.huawei.hmos.photos',abilityName: 'com.huawei.hmos.photos.MainAbility'})
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/87328.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/87328.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/87328.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

greenplum7.2并行備份及恢復

1.并行備份 pg_dump -Fd --gp-syntax -U gpadmin -p 5432 -h 172.19.0.2 -d postgres -j 4 -f /opt/greenplum/data/postgres_backup_$(date %Y-%m-%d) 參數 含義 -Fd 使用 directory 格式&#xff08;支持并行&#xff09; --gp-syntax 使用 Greenplum 特定語法&#xff08;…

備賽2025年初中古詩文大會:練習歷年真題,吃透知識點(0703)

初中古詩文大會的比賽內容古詩詞、文言文各占比50%左右&#xff0c;從歷年的比賽來看&#xff0c;中考語文的古詩文部分&#xff08;35分&#xff09;涉及到的古詩詞、文言文知識點都在初中古詩文大會中考過。這些知識點掌握了&#xff0c;對于將來高中、高考也有直接的幫助。 …

BRAKER:真核微生物cds和蛋白注釋

https://github.com/Gaius-Augustus/BRAKER 安裝 # 第一次打開會pull這個docker docker run --user 1000:100 --rm -it teambraker/braker3:latest bash bash /opt/BRAKER/example/docker-tests/test3.sh braker.gtf&#xff1a;BRAKER 的最終基因集。 braker.codingseq&am…

基于 Three.js 與 WebGL 的商場全景 VR 導航系統源碼級解析

本文面向Web前端開發者、WebGL/Three.js 愛好者、對VR/AR應用開發感興趣的技術人員、智慧商場解決方案開發者。詳細介紹如何利用 WebGL (Three.js框架) 構建高性能的商場全景VR環境&#xff0c;并實現精準的室內定位與3D路徑規劃導航功能。 如需獲取商場全景VR導航系統解決方案…

AWS CloudFormation部署雙可用區VPC網絡架構 - 完整指南

一、模板概述 本CloudFormation模板用于在AWS上快速部署一個高可用的雙可用區VPC網絡架構,包含公有子網和私有子網。該架構是構建云原生應用的基礎,特別適合生產環境使用。 二、完整模板代碼 AWSTemplateFormatVersion: 2010-09-09 Description: Customizable dual-AZ VPC…

2025汽車聲學升級:高透音汽車喇叭網成高端車型新標配

隨著消費者對車載音質和靜謐性要求的提升&#xff0c;高透音汽車喇叭網正成為高端車型的差異化配置。傳統沖壓金屬網因聲學損耗大、設計單一逐漸被淘汰&#xff0c;而新一代蝕刻工藝通過微孔結構優化&#xff0c;實現了聲學性能與美學設計的雙重突破。以下是技術趨勢與市場前景…

決策樹(Decision tree)算法詳解(ID3、C4.5、CART)

文章目錄 一、決策樹介紹1.1 決策樹的結構特征1.2 決策樹的構建三步驟1.3 決策樹構建例子 二、ID3決策樹&#xff1a;基于信息增益的決策模型2.1 信息增益的公式與符號解析2.2 信息增益的意義2.3 ID3決策樹案例演示&#xff1a;貸款申請分類2.4 ID3決策樹缺陷 三、C4.5決策樹&a…

python基礎-網絡的TCP、UDP協議操作

1.tcp基本語法 # ### TCP協議 客戶端 import socket # 1.創建一個socket對象 sk socket.socket() # 2.與服務端建立連接 sk.connect( ("127.0.0.1" , 9000) ) # 3.收發數據的邏輯 """發送的數據類型是二進制字節流""" ""&q…

基于spark的航班價格分析預測及可視化

基于spark的航班價格分析預測及可視化 項目概況 [&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;&#x1f447;] 點這里,查看所有項目 [&#x1f446;&#x1f446;&#x1f446;&#x1f446;&#x1f446;&#x1f446;&…

每日算法刷題Day41 6.28:leetcode前綴和2道題,用時1h20min(要加快)

5. 523.連續的子數組和(中等,學習) 523. 連續的子數組和 - 力扣&#xff08;LeetCode&#xff09; 思想 1.給你一個整數數組 nums 和一個整數 k &#xff0c;如果 nums 有一個 好的子數組 返回 true &#xff0c;否則返回 false&#xff1a; 一個 好的子數組 是&#xff1a;…

拉取vue-element-admin

這個錯誤表明 npm 在嘗試通過 SSH 克隆 GitHub 倉庫時遇到了權限問題&#xff0c;根本原因是系統無法正確處理中文用戶名路徑下的 SSH 配置。以下是詳細的解決方案&#xff1a; 解決方案 1&#xff1a;使用 HTTPS 代替 SSH&#xff08;推薦&#xff09; 修改 Git 全局配置&…

c語言的數組注意事項

在C語言中&#xff0c;int()[5]和int是兩種完全不同的指針類型&#xff0c;理解它們的區別對于正確處理數組和多維數組至關重要。下面詳細解釋&#xff1a; 1&#xff1a;int*&#xff08;指向整型的指針&#xff09; 含義&#xff1a;指向單個int類型數據的指針典型用法&…

在 NestJS 中優雅使用 TypeORM 進行事務管理

事務管理是數據庫操作中至關重要的部分&#xff0c;它能確保一系列操作要么全部成功&#xff0c;要么全部失敗。本文將詳細介紹在 NestJS 框架中使用 TypeORM 進行事務管理的多種方法。 為什么需要事務管理&#xff1f; 想象一下銀行轉賬場景&#xff1a;從一個賬戶扣款后&am…

給任意apk內容添加水印

1 有源碼給app添加水印 使用java可以適配更多的apk&#xff0c;如果使用koltin一些老的apk就會有適配問題 通過registerActivityLifecycleCallbacks拿到activity對象設置水印 在application里面registerActivityLifecycleCallbacks就行 static class MyActivityLifecycleCallb…

擴展的Fortran在高性能計算(HPC)中助力有限元分析(FEA)、流體力學(CFD)、結構力學、復合材料和增材制造仿真的詳細指南【附完整示例代碼實現】

Fortran 在高性能計算(HPC)中的仿真應用 本指南深入探討 Fortran 語言如何在高性能計算(HPC)中助力有限元分析(FEA)、流體力學(CFD)、結構力學、復合材料和增材制造仿真。每部分詳細介紹,分析 Fortran 的優勢、應用場景和實現細節,并附帶完整的 Fortran 模擬代碼(含…

Java 大視界 -- Java 大數據機器學習模型在自然語言處理中的跨語言信息檢索與知識融合(331)

Java 大視界 -- Java 大數據機器學習模型在自然語言處理中的跨語言信息檢索與知識融合&#xff08;331&#xff09; 引言&#xff1a;正文&#xff1a;一、Java 驅動的多語言數據處理平臺1.1 分布式多語言語料智能清洗系統1.2 多語言文本分布式存儲與索引優化1.3 低資源語言數據…

[2025CVPR]SEEN-DA:基于語義熵引導的領域感知注意力機制

目錄 引言 研究背景 方法介紹 核心思想 語義熵&#xff08;Semantic Entropy&#xff09; 語義熵引導的注意力機制 領域感知注意力模塊 實驗設計 數據集 實現細節 結果與分析 對比實驗結果 消融實驗 代碼實現 結論 引言 領域自適應目標檢測&#xff08;Domain …

你的RAG系統安全么?

生成式人工智能&#xff08;GenAI&#xff09;近年來發展迅速&#xff0c;大語言模型成為這一浪潮的核心力量。無論是商業還是開源模型&#xff0c;它們都具備強大的語言理解與生成能力&#xff0c;正廣泛應用于內容創作、聊天機器人等場景&#xff0c;讓企業更容易落地智能應用…

【2.3 漫畫SpringSecurity - 守護應用安全的鋼鐵衛士】

?? 漫畫SpringSecurity - 守護應用安全的鋼鐵衛士 ?? 目錄 記憶口訣可視化圖表形象比喻數字記憶實戰案例記憶卡片總結詩句面試準備?? 記憶口訣 ??? SpringSecurity核心 - “認證授權過濾鏈” 認證Authentication確身份,用戶名密碼驗證真 授權Authorization控權限,…

ModbusRTU轉Profinet網關在電子天平與PLC系統集成中的應用

ModbusRTU轉Profinet網關在電子天平與PLC系統集成中的應用 工業自動化場景中&#xff0c;設備通信協議差異常成為系統集成的隱形壁壘。某精密制造企業近期遇到的奧豪斯電子天平與西門子PLC通訊難題&#xff0c;正是這一矛盾的典型縮影。奧豪斯天平采用ModbusRTU協議&#xff0…