Files
hospital-rescue-app-v2/uni_modules/x-mlkit-scannig-s/utssdk/app-ios/index.uts
T
2026-09-24 16:25:22 +08:00

743 lines
23 KiB
Plaintext

import { AVCaptureSession, AVCaptureDevice, AVMediaType, AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureDeviceInput, AVCaptureInput, AVCaptureVideoDataOutput, AVCaptureConnection, AVCaptureVideoPreviewLayer, AVLayerVideoGravity, AVCaptureVideoOrientation } from 'AVFoundation';
import { PHPhotoLibrary, PHAuthorizationStatus } from 'Photos';
import { CMSampleBuffer, CMSampleBufferGetFormatDescription, CMFormatDescription, CMVideoFormatDescriptionGetDimensions } from 'CoreMedia';
import { DispatchQueue } from "Dispatch"
import { UIView, UIImage, UIApplication, UIImageView, UILabel, UIViewController, UIFontDescriptor, UIFont, NSTextAlignment, UITapGestureRecognizer, UIImagePickerController, UIImagePickerControllerDelegate, UINavigationControllerDelegate } from 'UIKit';
import { CGRect, CGFloat, CGPoint } from 'CoreFoundation';
import { Barcode, BarcodeScannerOptions, BarcodeFormat, BarcodeScanner, CMVideoDimensions } from "MLKitBarcodeScanning"
import { VisionImage } from "MLKit"
import { SCANNING_PHOTO_RESULT, SCANNING_PHOTO_RESULT_BOUND, CALL_RESULT_FUN, AUTH_CALL_BACK_TYPE } from '../interface.uts';
import { NotificationCenter, NSNotification, Notification } from 'Foundation';
import { Selector } from 'ObjectiveC';
import { Alignment } from 'ARKit';
import { CABasicAnimation } from 'QuartzCore';
type ConverXy = {
x : number,
y : number,
minx : number,
maxx : number,
miny : number,
maxy : number,
}
type contaiaSize = {
width : number,
height : number
}
type contaiaCalseSize = {
scale : number,
offsetX : number,
offsetY : number
}
type contaiPointXy = {
x : number,
y : number
}
// 资料参考:
// https://github.com/JimmyPun610/BarcodeScanner.Mobile/blob/master/BarcodeScanner.Mobile.Maui/Platforms/iOS/CaptureVideoDelegate.cs
// 识别结果
let scanResult = [] as Swift.Array<Barcode>
let captureSession : null | AVCaptureSession = null;
let captureDeviceAllGlobal : null | AVCaptureDevice = null;
let FlashButton:null|UILabel = null;
let flashModel = false;
// 视频宽
let videoWidth = 0
// 视频高
let videoHeight = 0
// 图像捕捉事件代理。
let captureOutDelegate : CaptureOutSessionBuffer | null = null;
let pointsEvents = [] as PointClickEvent[]
let isCamreaing = false;
let pointView = [] as UIView[]
let onlyCamera : boolean = false;
let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all)
let parentView : UIView | null = null
let camreaViewLayer : UIView | null = null
let pointsLayerView : UIView | null = null
let imageUiView : UIImageView | null = null
let cameraView : AVCaptureVideoPreviewLayer | null = null
let backevents : BackEvents | null = null;
let photosevents : PhotoSelectedEvents | null = null;
let scanevents : ScanEvents | null = null;
let flashBtnevents:FlashBtnEvents|null = null;
let rsultCallBack : CALL_RESULT_FUN = (str : string) => { }
let delegate : null | useImagePickerDelegate = null;
let openAnimation = true;
/** 加上这个标签可以持续响应事件,回调执行时必要的标签. */
@MainActor
class useImagePickerDelegate implements UIImagePickerControllerDelegate, UINavigationControllerDelegate {
call : (image : any | null) => void;
constructor(call : (image : any | null) => void) {
this.call = call;
}
imagePickerController(controller : UIImagePickerController, @argumentLabel("didFinishPickingMediaWithInfo") info : Map<UIImagePickerController.InfoKey, any>) {
let image = info.get(UIImagePickerController.InfoKey.originalImage)
this.call(image)
controller.dismiss(animated = true, completion = null)
}
imagePickerControllerDidCancel(controller : UIImagePickerController) {
this.call(null)
controller.dismiss(animated = true, completion = null)
}
}
class PointClickEvent {
private callback : (txt : string) => void
private text : string;
constructor(callback : (txt : string) => void, atext : string) {
this.callback = callback;
this.text = atext;
super.init()
}
@objc onclick() {
this.callback(this.text)
}
}
class BackEvents {
private callback : () => void
constructor(callback : () => void) {
this.callback = callback
super.init()
}
@objc onclick() {
this.callback()
}
}
class PhotoSelectedEvents {
private callback : () => void
constructor(callback : () => void) {
this.callback = callback
super.init()
}
@objc onclick() {
this.callback()
}
}
class ScanEvents {
private callback : () => void
constructor(callback : () => void) {
this.callback = callback
super.init()
}
@objc onclick() {
this.callback()
}
}
class FlashBtnEvents {
private callback : () => void
constructor(callback : () => void) {
this.callback = callback
super.init()
}
@objc onclick() {
this.callback()
}
}
class CaptureOutSessionBuffer implements AVCaptureVideoDataOutputSampleBufferDelegate {
callback : (str : SCANNING_PHOTO_RESULT) => void = (str : SCANNING_PHOTO_RESULT) => { }
constructor(dv : (str : SCANNING_PHOTO_RESULT) => void) {
this.callback = dv;
super()
}
captureOutput(output : AVCaptureOutput, @argumentLabel("didOutput") sampleBuffer : CMSampleBuffer, @argumentLabel("from") connection : AVCaptureConnection) {
if (!isCamreaing) return;
// console.log('图片捕捉正确')
let image = new VisionImage(buffer = sampleBuffer)
// 这里会直接影响到测量的起始点。下面是镜像,测量是图片左上为起始,但设备是竖向,因此计算时的x,y坐标其实是相对屏幕向右转下,x,y是反向的,因为是镜像
// 所以计算位置时,x,y是反的,宽和高也是相反的。
image.orientation = UIImage.Orientation.right
let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all)
// options=barcodeOptions
let barcodeScanner = new BarcodeScanner.barcodeScanner(options = barcodeOptions)
barcodeScanner.process(image, completion = (features : Swift.Array<Barcode> | null, error) => {
if (features == null || error != null) {
return;
}
if (features!.length == 0 || scanResult.length > 0) {
return;
}
// 暂停识别。
captureSession!.stopRunning()
scanResult = features!
let descVideo : CMFormatDescription | null = CMSampleBufferGetFormatDescription(sampleBuffer);
if (descVideo != null) {
let dimesionsize : CMVideoDimensions = CMVideoFormatDescriptionGetDimensions(descVideo!)
videoWidth = Number(dimesionsize.width)
videoHeight = Number(dimesionsize.height)
}
let listpos = [] as number[][][]
let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[]
let rulstText = [] as string[]
for (let i = 0; i < features!.length; i++) {
let barcode = features![i]
// 位置信息
let bounds = barcode.frame
// 坐标
let corners = barcode.cornerPoints
// 解析的内容
let rawValue = barcode.rawValue
let iminfo = {
width: Number(bounds.width),
height: Number(bounds.height),
centerX: Number(bounds.midX),
centerY: Number(bounds.midY)
} as SCANNING_PHOTO_RESULT_BOUND
let posinfo = [] as number[][]
for (pos in corners!) {
// pos是pointValue类型并返回CGPoint,其中有x,y
let ponit = pos.cgPointValue
posinfo.push([Number(ponit.x), Number(ponit.y)] as number[])
}
listpos.push(posinfo)
bounedlist.push(iminfo)
rulstText.push(rawValue == null ? '' : (rawValue!))
}
let res = {
url: '',
position: listpos,
bounds: bounedlist,
text: rulstText,
imgWidth:0,
imgHeight:0
} as SCANNING_PHOTO_RESULT
this.callback(res)
})
}
}
// 检查权限
export function isCheckPermissions(callFun : null | AUTH_CALL_BACK_TYPE) {
let realcall : AUTH_CALL_BACK_TYPE = (_ : boolean) => { };
if (callFun != null) {
let cllfunFun = callFun!;
realcall = cllfunFun
}
if (!onlyCamera) {
PHPhotoLibrary.requestAuthorization((isok : PHAuthorizationStatus) => {
// 拒绝了相册选取权限。
if (isok != PHAuthorizationStatus.authorized) {
realcall(false)
return;
}
AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => {
if (!isok2) {
realcall(false)
return;
}
realcall(true)
})
})
} else {
AVCaptureDevice.requestAccess(for = AVMediaType.video, completionHandler = (isok2 : boolean) => {
if (!isok2) {
realcall(false)
return;
}
realcall(true)
})
}
}
function xCamreaInit() {
let t = this;
let sys = uni.getSystemInfoSync();
if (parentView != null) {
parentView!.removeFromSuperview()
}
parentView = new UIView();
let scaleAni = new CABasicAnimation(keyPath = "transform.scale")
scaleAni.fromValue = 0
scaleAni.toValue = 1
scaleAni.duration = 0.25
parentView!.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = (sys.screenHeight).toInt())
parentView!.backgroundColor = UTSiOS.colorWithString("#000000")
let parent = UTSiOS.getCurrentViewController() as UIViewController;
let windUiview = parent.view as UIView
windUiview.addSubview(parentView!)
let safeTop = sys.statusBarHeight + 50
let safeHeight = sys.screenHeight - 100 - sys.statusBarHeight - 50
// 绘制界面
// 创建一张图片预览层。
imageUiView = new UIImageView();
imageUiView!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt())
imageUiView!.isHidden = true;
parentView!.addSubview(imageUiView!);
// 创建小绿点层.
pointsLayerView = new UIView()
pointsLayerView!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt())
// 创建视频预览层。
camreaViewLayer = new UIView()
camreaViewLayer!.frame = new CGRect(x = 0, y = safeTop.toInt(), width = (sys.windowWidth).toInt(), height = (safeHeight).toInt())
parentView!.addSubview(camreaViewLayer!);
cameraView = new AVCaptureVideoPreviewLayer(session = captureSession!)
// 设置预览层绑定
// 下面的缩放会居中显示,因此左顶点可能在左上方
cameraView!.videoGravity = AVLayerVideoGravity.resizeAspectFill
cameraView!.connection!.videoOrientation = AVCaptureVideoOrientation.portrait
cameraView!.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = (safeHeight).toInt())
DispatchQueue.main.async(execute = () : void => {
// 绑定渲染层。
camreaViewLayer!.layer.addSublayer(cameraView!)
captureSession!.startRunning()
// 创建一个上遮盖板。
// let toplayer = new UIView()
// toplayer.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = 100)
// toplayer.backgroundColor = UTSiOS.colorWithString("rgba(255,0,0,0)")
// parentView!.addSubview(toplayer);
// 创建一个下遮盖板。
let bottomlayer = new UIView()
bottomlayer.frame = new CGRect(x = 0, y = 0, width = (sys.windowWidth).toInt(), height = 100)
bottomlayer.backgroundColor = UTSiOS.colorWithString("#000000")
parentView!.addSubview(bottomlayer);
// 创建一个返回按钮文本。
let backButton = new UILabel()
backButton.frame = new CGRect(x = 16, y = 58, width = (sys.windowWidth - 16).toInt(), height = 32)
backButton.text = String("返回")
backButton.font = UIFont.systemFont(ofSize = new CGFloat(16))
backButton.textColor = UTSiOS.colorWithString("#FFFFFF")
parentView!.addSubview(backButton);
// 创建一个相册选取按钮
let photoBtn = new UILabel()
photoBtn.frame = new CGRect(x = 16, y = (sys.screenHeight - 88).toInt(), width = 80, height = 32)
photoBtn.text = String(onlyCamera ? "" : "相册选取")
photoBtn.font = UIFont.systemFont(ofSize = new CGFloat(16))
photoBtn.textColor = UTSiOS.colorWithString("#FFFFFF")
parentView!.addSubview(photoBtn);
// 创建个闪光灯打开和关闭的文本层.
let flashBtn = new UILabel()
flashBtn.frame = new CGRect(x = ((sys.windowWidth - 80)/2).toInt(), y = (sys.screenHeight - 88).toInt(), width = 80, height = 32)
flashBtn.text = String("开灯")
flashBtn.font = UIFont.systemFont(ofSize = new CGFloat(16))
flashBtn.textAlignment = NSTextAlignment.center
flashBtn.textColor = UTSiOS.colorWithString("#FFFFFF")
parentView!.addSubview(flashBtn);
FlashButton = flashBtn;
// 创建一个继续扫一扫的按钮
let scanBtn = new UILabel()
scanBtn.frame = new CGRect(x = (sys.windowWidth - 96).toInt(), y = (sys.screenHeight - 88).toInt(), width = 80, height = 32)
scanBtn.text = String("扫一扫")
scanBtn.font = UIFont.systemFont(ofSize = new CGFloat(16))
scanBtn.textAlignment = NSTextAlignment.right
scanBtn.textColor = UTSiOS.colorWithString("#FFFFFF")
parentView!.addSubview(scanBtn);
// 最高层级.
parentView!.addSubview(pointsLayerView!);
// 添加事件。
// 返回,关闭弹层。
backevents = new BackEvents(() => {
closeScan();
quitView();
})
// 点击了相册选取。
function setToXiangChe() {
if (onlyCamera) {
return;
}
let pic = new UIImagePickerController()
DispatchQueue.main.async(execute = () : void => {
delegate = new useImagePickerDelegate((image : any | null) => {
if (image != null) {
let realimageds = image! as UIImage;
closeScan();
imageUiView!.image = realimageds
imageUiView!.contentMode = UIView.ContentMode.scaleAspectFit
camreaViewLayer!.isHidden = true;
imageUiView!.isHidden = false;
// 图片识别码.
let visionImage = new VisionImage(image = realimageds)
visionImage.orientation = realimageds.imageOrientation
let barcodeOptions = BarcodeScannerOptions(formats = BarcodeFormat.all)
let barcodeScanner = new BarcodeScanner.barcodeScanner(options = barcodeOptions)
barcodeScanner.process(visionImage, completion = (features : Swift.Array<Barcode> | null, error) => {
if (features == null || error != null) {
return;
}
if (features!.length == 0) {
return;
}
scanResult = features!
videoWidth = Number(realimageds.size.width);
videoHeight = Number(realimageds.size.height);
let listpos = [] as number[][][]
let bounedlist = [] as SCANNING_PHOTO_RESULT_BOUND[]
let rulstText = [] as string[]
for (let i = 0; i < features!.length; i++) {
let barcode = features![i]
// 位置信息
let bounds = barcode.frame
// 坐标
let corners = barcode.cornerPoints
// 解析的内容
let rawValue = barcode.rawValue
let iminfo = {
width: Number(bounds.width),
height: Number(bounds.height),
centerX: Number(bounds.midX),
centerY: Number(bounds.midY)
} as SCANNING_PHOTO_RESULT_BOUND
let posinfo = [] as number[][]
for (pos in corners!) {
// pos是pointValue类型并返回CGPoint,其中有x,y
let ponit = pos.cgPointValue
posinfo.push([Number(ponit.x), Number(ponit.y)] as number[])
}
listpos.push(posinfo)
bounedlist.push(iminfo)
rulstText.push(rawValue == null ? '' : (rawValue!))
}
let result = {
url: '',
position: listpos,
bounds: bounedlist,
text: rulstText,
imgWidth:0,
imgHeight:0
} as SCANNING_PHOTO_RESULT
let deg = 0;
if (realimageds.imageOrientation == UIImage.Orientation.right) {
deg = 90
} else if (realimageds.imageOrientation == UIImage.Orientation.up) {
deg = 0
} else if (realimageds.imageOrientation == UIImage.Orientation.left) {
deg = 270
} else if (realimageds.imageOrientation == UIImage.Orientation.down) {
deg = 180
}
console.log(deg)
createPointView(result, deg)
uni.setStorageSync("xMlKITScaning", JSON.stringify(result.text))
// t.$emit("scan")
if (result.text.length == 1) {
rsultCallBack(result.text[0])
closeScan()
quitView()
}
})
}
});
pic.sourceType = UIImagePickerController.SourceType.photoLibrary
pic.mediaTypes = ["public.image"]
pic.delegate = delegate!
UTSiOS.getCurrentViewController().present(pic, animated = true, completion = nil)
})
}
photosevents = new PhotoSelectedEvents(() => {
setToXiangChe();
})
scanevents = new ScanEvents(() => {
// 继续扫一扫
openAnimation = false
startCamera();
})
flashBtnevents = new FlashBtnEvents(() => {
// 开头灯光
flashModel = !flashModel
setFlashModel(flashModel)
flashBtn.text = flashModel?"关灯":String("开灯")
})
// 返回的事件。
backButton.isUserInteractionEnabled = true
let backevents_rz = new UITapGestureRecognizer()
backevents_rz.addTarget(backevents, action = new Selector("onclick"))
backButton.addGestureRecognizer(backevents_rz)
// 相册 按钮事件。。
let photosevents_rz = new UITapGestureRecognizer()
photosevents_rz.addTarget(photosevents, action = new Selector("onclick"))
photoBtn.addGestureRecognizer(photosevents_rz)
photoBtn.isUserInteractionEnabled = true
// 扫一扫 按钮事件。。
scanBtn.isUserInteractionEnabled = true
let scanevents_rz = new UITapGestureRecognizer()
scanevents_rz.addTarget(scanevents, action = new Selector("onclick"))
scanBtn.addGestureRecognizer(scanevents_rz)
//打开灯光事件.setFlashModel
flashBtn.isUserInteractionEnabled = true
let flashBtnevents_rz = new UITapGestureRecognizer()
flashBtnevents_rz.addTarget(flashBtnevents, action = new Selector("onclick"))
flashBtn.addGestureRecognizer(flashBtnevents_rz)
if (openAnimation) {
// 增加显示动画.
parentView!.layer.add(scaleAni, forKey = "scaleAnimation")
}
// ios识别太快了,图像还没定焦就识别出来了,稍微延迟下,不要太快了。与安卓对齐 下。
setTimeout(function () {
isCamreaing = true;
}, 300);
})
}
function calcPoint(c_w : number, c_h : number, image_w : number, image_h : number, image_point_x : number, image_point_y : number, degration : number) : ConverXy {
function scaleAndCenterContent(
container : contaiaSize,
content : contaiaSize
) : contaiaCalseSize {
// 计算缩放比例
const scaleWidth = container.width / content.width;
const scaleHeight = container.height / content.height;
const scale = Math.min(scaleWidth, scaleHeight);
// 计算居中偏移量
const offsetX = (container.width - content.width * scale) / 2;
const offsetY = (container.height - content.height * scale) / 2;
return { scale, offsetX, offsetY } as contaiaCalseSize;
}
function mapContentCoordinatesToContainer(
contentX : number,
contentY : number,
calcsize : contaiaCalseSize
) : contaiPointXy {
// 映射内容层坐标到容器层坐标
const containerX = contentX * calcsize.scale + calcsize.offsetX;
const containerY = contentY * calcsize.scale + calcsize.offsetY;
return { x: containerX, y: containerY } as contaiPointXy;
}
let rc = scaleAndCenterContent(
{ width: c_w, height: c_h } as contaiaSize,
{ width: image_h, height: image_w } as contaiaSize
)
if (degration == 0) {
rc = scaleAndCenterContent(
{ width: c_w, height: c_h } as contaiaSize,
{ width: image_w, height: image_h } as contaiaSize
)
}
let result = mapContentCoordinatesToContainer(image_point_y, image_point_x, rc)
if (degration == 0) {
result = mapContentCoordinatesToContainer(image_point_x, image_point_y, rc)
}
let nexyxcov = {
x: c_w - result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0
} as ConverXy
if (degration == 0) {
nexyxcov = {
x: result.x, y: result.y, minx: 0, maxx: 0, miny: 0, maxy: 0
} as ConverXy
}
return nexyxcov
}
function createPointView(result : SCANNING_PHOTO_RESULT, degration : number) {
let realCgSize = camreaViewLayer!.frame as CGRect;
let realWidth = Number(realCgSize.width);
let realHeight = Number(realCgSize.height);
clearPointView();
let pointSize = 30
DispatchQueue.main.async(execute = () : void => {
for (let i = 0; i < result.bounds.length; i++) {
let text = result.text[i]
let bounds = result.bounds[i]
let pos = result.position[i];
let resutxy = calcPoint(realWidth, realHeight, videoWidth, videoHeight, bounds.centerX, bounds.centerY, degration)
let x = resutxy.x - 15
let y = resutxy.y - 15
let rect = new CGRect(x = x.toInt(), y = y.toInt(), width = pointSize.toInt(), height = pointSize.toInt())
let pointViewSelf = new UIView();
pointViewSelf.layer.frame = rect;
pointViewSelf.backgroundColor = UTSiOS.colorWithString('#21d429');
pointViewSelf.layer.borderWidth = 2
pointViewSelf.layer.borderColor = UTSiOS.colorWithString('#FFFFFF').cgColor;
pointViewSelf.layer.cornerRadius = new CGFloat(pointSize / 2);
let onlick = new PointClickEvent((atext : string) => {
rsultCallBack(atext)
closeScan()
quitView()
}, text);
pointsEvents.push(onlick)
let tapGestureCancel = new UITapGestureRecognizer()
tapGestureCancel.addTarget(onlick, action = new Selector("onclick"))
pointViewSelf.addGestureRecognizer(tapGestureCancel)
pointsLayerView!.addSubview(pointViewSelf)
pointView.push(pointViewSelf)
}
})
}
/** 手动开启和关闭闪光灯 */
function setFlashModel(flash : boolean) {
if (captureDeviceAllGlobal != null) {
let islock = UTSiOS.try(captureDeviceAllGlobal!.lockForConfiguration(), "?")
if (islock != null) {
captureDeviceAllGlobal!.torchMode = flash ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
captureDeviceAllGlobal!.unlockForConfiguration()
}
}
}
function clearPointView() {
DispatchQueue.main.async(execute = () : void => {
for (let i = 0; i < pointView.length; i++) {
let item = pointView[i];
item.removeFromSuperview();
}
pointView = [] as UIView[]
})
}
function closeScan() {
// 移除点。
clearPointView()
if (captureSession != null) {
captureSession!.stopRunning()
for (input in captureSession!.inputs) {
captureSession!.removeInput(input)
}
for (output in captureSession!.outputs) {
captureSession!.removeOutput(output)
}
captureSession = null;
}
scanResult = [] as Swift.Array<Barcode>
pointsEvents = [] as PointClickEvent[]
captureDeviceAllGlobal = nil;
FlashButton = nil;
}
function startCamera() {
isCamreaing = false;
closeScan();
captureSession = new AVCaptureSession();
let captureDevice = AVCaptureDevice.default(for = AVMediaType.video)
let captureOut = new AVCaptureVideoDataOutput();
captureSession!.sessionPreset = AVCaptureSession.Preset.photo
captureOutDelegate = new CaptureOutSessionBuffer((result : SCANNING_PHOTO_RESULT) => {
createPointView(result, 90)
uni.setStorageSync("xMlKITScaning", JSON.stringify(result.text))
// t.$emit("scan")
if (result.text.length == 1) {
rsultCallBack(result.text[0])
setTimeout(function () {
closeScan()
quitView()
}, 150);
}
})
// 新建设备的输入设备
let inputDevice = UTSiOS.try(new AVCaptureDeviceInput(device = captureDevice!), "?")
if (inputDevice != null) {
// 添加输入到会话中。
captureSession!.addInput(inputDevice!)
}
captureOut.alwaysDiscardsLateVideoFrames = true;
// 设置输出会话
captureOut.setSampleBufferDelegate(captureOutDelegate!, queue = DispatchQueue.global())
if (captureSession!.canAddOutput(captureOut)) {
captureSession!.addOutput(captureOut)
// console.log("绑定输出层正确!")
}
xCamreaInit();
captureDeviceAllGlobal = captureDevice
}
function quitView() {
if (parentView != null) {
parentView!.removeFromSuperview()
}
}
export function openCameraApi(callback : CALL_RESULT_FUN, onlyCameras : boolean) {
rsultCallBack = callback
openAnimation = true;
onlyCamera = onlyCameras
startCamera();
}
export function closeCamera() {
closeScan();
quitView();
}