Commit 3f3bdcb5 authored by CZ1004's avatar CZ1004

【优化】调整压缩动画以及细节

parent 87820404
{
"images" : [
{
"filename" : "Group_1171275116.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group_1171275116@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Group_1171275116@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -25,7 +25,7 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -25,7 +25,7 @@ class CompressCompletedViewController : BaseViewController{
} }
} }
var comVideoDataSource : [URL?] = []{ var comVideoDataSource : [URL] = []{
didSet{ didSet{
if let url = comVideoDataSource.first{ if let url = comVideoDataSource.first{
DispatchQueue.main.async { DispatchQueue.main.async {
...@@ -225,6 +225,8 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -225,6 +225,8 @@ class CompressCompletedViewController : BaseViewController{
} }
// MARK: 事件方法 // MARK: 事件方法
/// 保留两个
@objc func keepButtonAction(){ @objc func keepButtonAction(){
if currentMediaType == .compressPhoto { if currentMediaType == .compressPhoto {
if let imageData = self.comDataSource.first { if let imageData = self.comDataSource.first {
...@@ -234,22 +236,19 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -234,22 +236,19 @@ class CompressCompletedViewController : BaseViewController{
}) { success, error in }) { success, error in
if(success){ if(success){
print("保存照片成功") print("保存照片成功")
}else {
if let error = error {
print("保存相片时出错: \(error.localizedDescription)")
}
} }
self.jumpToRootVC() self.showDeleteSuccess(fileCount: 1, fileSize: Int64(self.completedSize))
} }
}else { }else {
self.jumpToRootVC() self.showDeleteSuccess(fileCount: 1, fileSize: Int64(self.completedSize))
} }
}else{ }else{
// 保存视频到相册 // 保存视频到相册
if let url = self.comVideoDataSource.first {
PHPhotoLibrary.shared().performChanges({ PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url!) if let url = self.comVideoDataSource.first{
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: url as URL)
}
}) { (success, saveError) in }) { (success, saveError) in
if success { if success {
print("保存视频成功") print("保存视频成功")
...@@ -258,14 +257,13 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -258,14 +257,13 @@ class CompressCompletedViewController : BaseViewController{
print("保存视频时出错: \(error.localizedDescription)") print("保存视频时出错: \(error.localizedDescription)")
} }
} }
self.jumpToRootVC() self.showDeleteSuccess(fileCount: 1, fileSize: Int64(self.completedSize))
}
}else {
self.jumpToRootVC()
} }
} }
} }
/// 删除原数据
@objc func deleteButtonAction(){ @objc func deleteButtonAction(){
if let model = self.model { if let model = self.model {
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [model.localIdentifier], options: nil) let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [model.localIdentifier], options: nil)
...@@ -275,15 +273,11 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -275,15 +273,11 @@ class CompressCompletedViewController : BaseViewController{
if(success){ if(success){
PhotoManager.shared.removeDataWhenDeleteInPage(data: [self.model!]) PhotoManager.shared.removeDataWhenDeleteInPage(data: [self.model!])
print("删除文件成功") print("删除文件成功")
}else {
if let error = error {
print("删除文件时出错: \(error.localizedDescription)")
} }
} self.showDeleteSuccess(fileCount: 1, fileSize: Int64(self.completedSize))
self.jumpToRootVC()
} }
}else { }else {
self.jumpToRootVC() self.showDeleteSuccess(fileCount: 1, fileSize: Int64(self.completedSize))
} }
} }
...@@ -291,16 +285,25 @@ class CompressCompletedViewController : BaseViewController{ ...@@ -291,16 +285,25 @@ class CompressCompletedViewController : BaseViewController{
// MARK: 辅助方法 // MARK: 辅助方法
/// 返回压缩控制器 // 删除成功页面
func jumpToRootVC(){ func showDeleteSuccess(fileCount:Int,fileSize:Int64){
DispatchQueue.main.async { DispatchQueue.main.async {
if let viewControllers = self.navigationController?.viewControllers { self.jumpToRootVC()
for controller in viewControllers.reversed() { let vc = DelSuccessViewController()
if controller is CompressController { vc.delType = fileCount > 1 ? "photos" : "photo"
self.navigationController?.popToViewController(controller, animated: true) vc.fileSzie = fileSize
break vc.fileCount = fileCount
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true)
} }
} }
/// 返回压缩控制器
func jumpToRootVC(){
DispatchQueue.main.async {
if let targetVC = self.navigationController?.viewControllers.first(where: { $0 is CompressController }) {
self.navigationController?.popToViewController(targetVC, animated: true)
} }
} }
} }
......
...@@ -153,7 +153,36 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo ...@@ -153,7 +153,36 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if self.currentResourceType == .compressPhoto{
// 判断资源是否存在
let options = PHImageRequestOptions()
options.isNetworkAccessAllowed = false
options.progressHandler = nil
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers: [self.resourceData[indexPath.row].localIdentifier], options: nil)
guard let phAsset = fetchResult.firstObject else {
showAlert()
return
}
PHImageManager.default().requestImageDataAndOrientation(
for: phAsset,
options: options
) { data, _, _, info in
if data == nil {
self.showAlert()
}else {
self.startCompress(model: self.resourceData[indexPath.row])
}
}
}else {
self.getVideoURLFromLocalIdentifier(localIdentifier: self.resourceData[indexPath.row].localIdentifier) { url, error in
if url != nil {
self.startCompress(model: self.resourceData[indexPath.row]) self.startCompress(model: self.resourceData[indexPath.row])
}else {
self.showAlert()
}
}
}
} }
func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize { func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize {
return CGSize (width: self.collectionView.width, height: 188) return CGSize (width: self.collectionView.width, height: 188)
...@@ -271,11 +300,59 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo ...@@ -271,11 +300,59 @@ extension CompressController:WaterfallMutiSectionDelegate,UICollectionViewDataSo
} }
func jumpToNextPage(model:AssetModel){ func jumpToNextPage(model:AssetModel){
// 先将值传到下一个页面 // 先将值传到下一个页面
let vc : CompressQualityController = CompressQualityController() let vc : CompressQualityController = CompressQualityController()
vc.currentMediaType = self.currentResourceType vc.currentMediaType = self.currentResourceType
vc.model = model vc.model = model
self.navigationController?.pushViewController(vc, animated: true) self.navigationController?.pushViewController(vc, animated: true)
}
func showAlert(){
let alert = UIAlertController(title: nil, message: "ICloud video cannot be viewed", preferredStyle: .alert)
self.present(alert, animated: true, completion: nil)
// 2 秒后关闭弹窗
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
alert.dismiss(animated: true, completion: nil)
}
}
// 注意私有方法(某些参数不一样) 这个只能在这个类中使用
private func getVideoURLFromLocalIdentifier(localIdentifier: String, completion: @escaping (URL?, Error?) -> Void) {
// 通过 localIdentifier 获取 PHAsset
let fetchOptions = PHFetchOptions()
let assets = PHAsset.fetchAssets(withLocalIdentifiers: [localIdentifier], options: fetchOptions)
guard let asset = assets.firstObject, asset.mediaType == .video else {
DispatchQueue.main.async {
completion(nil, NSError(domain: "com.example.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "未找到对应视频资源"]))
}
return
}
let options = PHVideoRequestOptions()
options.isNetworkAccessAllowed = false // 允许从网络下载
options.deliveryMode = .fastFormat // 要求高质量格式
PHImageManager.default().requestAVAsset(forVideo: asset, options: options) { (avAsset, audioMix, info) in
if let error = info?[PHImageErrorKey] as? Error {
DispatchQueue.main.async {
completion(nil, error)
}
return
}
if let urlAsset = avAsset as? AVURLAsset {
DispatchQueue.main.async {
completion(urlAsset.url, nil)
}
} else {
DispatchQueue.main.async {
completion(nil, NSError(domain: "CustomErrorDomain", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to get video URL"]))
}
}
}
} }
......
...@@ -258,7 +258,7 @@ class CompressQualityController : BaseViewController{ ...@@ -258,7 +258,7 @@ class CompressQualityController : BaseViewController{
fileprivate func updateNextView(_ compressAllSize: Double, _ compressingView: CompressingView,_ comDataSource : [Data],_ comVideoDataSource : [URL?]) { fileprivate func updateNextView(_ compressAllSize: Double, _ compressingView: CompressingView,_ comDataSource : [Data],_ comVideoDataSource : [URL]) {
DispatchQueue.main.async { DispatchQueue.main.async {
compressingView.removeFromSuperview() compressingView.removeFromSuperview()
let vc = CompressCompletedViewController() let vc = CompressCompletedViewController()
......
...@@ -22,13 +22,11 @@ class CompressingViewController: BaseViewController { ...@@ -22,13 +22,11 @@ class CompressingViewController: BaseViewController {
} }
} }
var qualityType : CompressQualityType? { var qualityType : CompressQualityType = .low {
didSet{ didSet{
if let model = model { if let model = model {
if let qualityType = qualityType {
DispatchQueue.main.async { DispatchQueue.main.async {
self.targetSizeLabel.text = formatFileSize(model.assetSize * qualityType.rawValue) self.targetSizeLabel.text = formatFileSize(model.assetSize * self.qualityType.rawValue)
}
} }
} }
} }
...@@ -85,7 +83,7 @@ class CompressingViewController: BaseViewController { ...@@ -85,7 +83,7 @@ class CompressingViewController: BaseViewController {
lazy var progressBar : CustomCompressProgressBar = { lazy var progressBar : CustomCompressProgressBar = {
let bar = CustomCompressProgressBar() let bar = CustomCompressProgressBar()
bar.thumbImage = UIImage(systemName: "arrowtriangle.right.fill")?.withTintColor(.red) bar.thumbImage = UIImage(named: "Group_1171275116")
bar.layer.cornerRadius = 3.5 bar.layer.cornerRadius = 3.5
bar.clipsToBounds = true bar.clipsToBounds = true
return bar return bar
...@@ -104,42 +102,56 @@ class CompressingViewController: BaseViewController { ...@@ -104,42 +102,56 @@ class CompressingViewController: BaseViewController {
// MARK:设置数据 // MARK: 压缩方法
/// 开始压缩
func startCompress(){ func startCompress(){
if let qualityType = qualityType {
let manager : CompressViewModel = CompressViewModel()
if self.currentMediaType == .compressPhoto { if self.currentMediaType == .compressPhoto {
// 表示压缩图片 self.compressPhoto(model: self.model)
}else {
self.compressVideo(model: self.model)
}
}
/// 压缩单个图片
/// - Parameter model: 资源
private func compressPhoto(model : AssetModel?){
if let model = model {
var comDataSource : [Data] = [] var comDataSource : [Data] = []
manager.compress(assets: [self.model!], compressionQuality: qualityType.rawValue) {progress in let manager : CompressViewModel = CompressViewModel()
Print(progress) manager.compress(assets: [model], compressionQuality: qualityType.rawValue) {progress in
DispatchQueue.main.async { DispatchQueue.main.async {
self.progressBar.updateProgress(to: CGFloat(progress)) self.progressBar.updateProgress(to: CGFloat(progress))
} }
} completion: { compressedDataArray, errorArray in } completion: { compressedDataArray, errorArray in
var compressAllSize = 0.0 var compressAllSize = 0.0
for (index, data) in compressedDataArray.enumerated() { for (_, data) in compressedDataArray.enumerated() {
if let error = errorArray[index] { if let data = data {
print("第 \(index + 1) 个文件压缩出错: \(error.localizedDescription)")
} else if let data = data {
print("第 \(index + 1) 个文件压缩完成,压缩后大小: \(data.count) 字节")
compressAllSize = compressAllSize + Double(data.count) compressAllSize = compressAllSize + Double(data.count)
comDataSource.append(data) comDataSource.append(data)
} else {
print("第 \(index + 1) 个文件压缩失败")
} }
} }
self.progressBar.animationCompletion = {
// 不管成功失败都跳转下一页
self.updateNextView(compressAllSize,comDataSource,[]) self.updateNextView(compressAllSize,comDataSource,[])
} }
}else{ }
// 压缩视频 }
}
/// 压缩单个视频
/// - Parameter model: 资源
private func compressVideo(model : AssetModel?){
if let model = model {
var compressAllSize : Double = 0.0 var compressAllSize : Double = 0.0
CompressViewModel.compressVideos(models: [self.model!], quality: Float(qualityType.rawValue)) { progress in CompressViewModel.compressVideos(models: [model], quality: Float(qualityType.rawValue)) { progress in
DispatchQueue.main.async { DispatchQueue.main.async {
self.progressBar.updateProgress(to: CGFloat(progress)) self.progressBar.updateProgress(to: CGFloat(progress))
} }
} completion: { (outputURLs, errors) in } completion: { (outputURLs, errors) in
for (index, outputURL) in outputURLs.enumerated() { var finallyUrls : [URL] = []
for (_, outputURL) in outputURLs.enumerated() {
if let outputURL = outputURL { if let outputURL = outputURL {
do { do {
let attributes = try FileManager.default.attributesOfItem(atPath: outputURL.path) let attributes = try FileManager.default.attributesOfItem(atPath: outputURL.path)
...@@ -149,21 +161,26 @@ class CompressingViewController: BaseViewController { ...@@ -149,21 +161,26 @@ class CompressingViewController: BaseViewController {
} catch { } catch {
Print("获取视频文件大小失败") Print("获取视频文件大小失败")
} }
} else if let error = errors[index] { finallyUrls.append(outputURL)
print("Error compressing video \(index): \(error.localizedDescription)")
} }
} }
Print("---------压缩后的大小:\(compressAllSize)") self.progressBar.animationCompletion = {
// 不管成功失败都跳转下一页 // 不管成功失败都跳转下一页
self.updateNextView(compressAllSize,[],outputURLs) self.updateNextView(compressAllSize,[],finallyUrls)
} }
} }
} }
} }
fileprivate func updateNextView(_ compressAllSize: Double,_ comDataSource : [Data],_ comVideoDataSource : [URL?]) {
/// 压缩结果处理
/// - Parameters:
/// - compressAllSize: 压缩后总大小
/// - comDataSource: 压缩后的图片数据数组
/// - comVideoDataSource: 压缩后的视频链接数组
fileprivate func updateNextView(_ compressAllSize: Double,_ comDataSource : [Data],_ comVideoDataSource : [URL]) {
DispatchQueue.main.async { DispatchQueue.main.async {
let vc = CompressCompletedViewController() let vc = CompressCompletedViewController()
vc.currentMediaType = self.currentMediaType vc.currentMediaType = self.currentMediaType
...@@ -176,7 +193,7 @@ class CompressingViewController: BaseViewController { ...@@ -176,7 +193,7 @@ class CompressingViewController: BaseViewController {
} }
// MARK:设置UI // MARK: 设置UI
func setUI(){ func setUI(){
self.view.addSubview(self.bacImageView) self.view.addSubview(self.bacImageView)
self.bacImageView.snp.makeConstraints { make in self.bacImageView.snp.makeConstraints { make in
...@@ -222,8 +239,8 @@ class CompressingViewController: BaseViewController { ...@@ -222,8 +239,8 @@ class CompressingViewController: BaseViewController {
self.progressBar.snp.makeConstraints { make in self.progressBar.snp.makeConstraints { make in
make.left.equalTo(16) make.left.equalTo(16)
make.right.equalToSuperview().offset(-16) make.right.equalToSuperview().offset(-16)
make.height.equalTo(7) make.height.equalTo(24)
make.bottom.equalTo(-43 - safeHeight) make.bottom.equalTo(-34 - safeHeight)
} }
self.animationView.play(fromProgress: 0, toProgress: 1 , loopMode: .loop) self.animationView.play(fromProgress: 0, toProgress: 1 , loopMode: .loop)
......
...@@ -8,23 +8,47 @@ ...@@ -8,23 +8,47 @@
import UIKit import UIKit
class CustomCompressProgressBar: UIView { class CustomCompressProgressBar: UIView {
var animationCompletion: (() -> Void) = {}
// 背景色(已完成进度颜色)
private let backgroundLayer = CALayer()
// 前景色(已完成进度颜色) // 前景色(已完成进度颜色)
private let foregroundLayer = CALayer() private let foregroundLayer = CALayer()
// 进度指示图标 // 进度指示图标
private let thumbLayer = CALayer() private let thumbLayer = CALayer()
// 当前进度值(0-1) // 当前进度值(0-1)
private var progress: CGFloat = 0.0 private var progress: CGFloat = 0.0
// 最后一次更新时间 // 动画持续时间
private var lastUpdateTime: Date? private let animationDuration: CFTimeInterval = 4.0
// 动画定时器
private var displayLink: CADisplayLink?
private var animationStartTime: CFTimeInterval = 0
private var startProgress: CGFloat = 0
private var targetProgress: CGFloat = 0
// 缩略图图片
var thumbImage: UIImage? { var thumbImage: UIImage? {
didSet { didSet {
thumbLayer.contents = thumbImage?.cgImage thumbLayer.contents = thumbImage?.cgImage
thumbLayer.frame = CGRect(origin: .zero, size: thumbImage?.size ?? CGSize(width: 20, height: 20)) // 调整缩略图锚点
thumbLayer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
// 设置正确尺寸并居中
thumbLayer.frame = CGRect(
x: 0,
y: bounds.height/2 - 12, // 24/2=12
width: 24,
height: 24
)
} }
} }
// 添加视图配置防止裁剪
override func didMoveToSuperview() {
super.didMoveToSuperview()
self.clipsToBounds = false
layer.masksToBounds = false
}
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
setup() setup()
...@@ -36,82 +60,90 @@ class CustomCompressProgressBar: UIView { ...@@ -36,82 +60,90 @@ class CustomCompressProgressBar: UIView {
} }
private func setup() { private func setup() {
backgroundColor = .white // 设置背景层
layer.cornerRadius = frame.height / 2 backgroundLayer.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1).cgColor
layer.masksToBounds = true backgroundLayer.frame = CGRect(x: 0, y: self.bounds.height/2 - 3.5, width: self.bounds.width, height: 7)
backgroundLayer.cornerRadius = 3.5
layer.addSublayer(backgroundLayer)
// 设置前景层 // 设置前景层
foregroundLayer.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1).cgColor foregroundLayer.backgroundColor = UIColor(red: 0, green: 0.51, blue: 1, alpha: 1).cgColor
foregroundLayer.cornerRadius = layer.cornerRadius foregroundLayer.cornerRadius = 3.5
layer.addSublayer(foregroundLayer) layer.addSublayer(foregroundLayer)
// 设置缩略图层 // 设置缩略图层
thumbLayer.contentsGravity = .resizeAspect
layer.addSublayer(thumbLayer) layer.addSublayer(thumbLayer)
} }
override func layoutSubviews() { override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
CATransaction.begin()
CATransaction.setDisableActions(true)
updateLayers(for: progress) updateLayers(for: progress)
CATransaction.commit()
} }
func updateProgress(to newProgress: CGFloat) { func updateProgress(to newProgress: CGFloat) {
let currentTime = Date()
let clampedProgress = max(0, min(newProgress, 1.0)) let clampedProgress = max(0, min(newProgress, 1.0))
var duration: TimeInterval = 0 startProgress = currentPresentationProgress()
targetProgress = clampedProgress
if let lastTime = lastUpdateTime { startAnimation()
let timeSinceLast = currentTime.timeIntervalSince(lastTime)
duration = timeSinceLast < 1.0 ? 1.0 : timeSinceLast
} }
animateProgress(from: progress, to: clampedProgress, duration: duration) private func currentPresentationProgress() -> CGFloat {
lastUpdateTime = currentTime if let presentation = foregroundLayer.presentation() {
return presentation.bounds.width / bounds.width
} }
return progress
private func updateLayers(for progress: CGFloat) {
let foregroundWidth = bounds.width * progress
foregroundLayer.frame = CGRect(x: 0, y: 0, width: foregroundWidth, height: bounds.height)
let thumbSize = thumbLayer.bounds.size
let thumbX = progress * bounds.width - thumbSize.width/2
thumbLayer.frame.origin = CGPoint(
x: max(0, min(thumbX, bounds.width - thumbSize.width)),
y: (bounds.height - thumbSize.height)/2
)
} }
private func animateProgress(from oldProgress: CGFloat, to newProgress: CGFloat, duration: TimeInterval) { private func startAnimation() {
foregroundLayer.removeAllAnimations() animationStartTime = CACurrentMediaTime()
thumbLayer.removeAllAnimations() displayLink?.invalidate()
displayLink = CADisplayLink(target: self, selector: #selector(updateAnimation))
guard duration > 0 else { displayLink?.add(to: .main, forMode: .common)
progress = newProgress
updateLayers(for: newProgress)
return
} }
let foregroundAnimation = CABasicAnimation(keyPath: "bounds.size.width") @objc private func updateAnimation() {
foregroundAnimation.fromValue = oldProgress * bounds.width let elapsed = CACurrentMediaTime() - animationStartTime
foregroundAnimation.toValue = newProgress * bounds.width let percent = min(elapsed / animationDuration, 1.0)
foregroundAnimation.duration = duration
foregroundAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
let thumbAnimation = CABasicAnimation(keyPath: "position.x") let currentProgress = startProgress + (targetProgress - startProgress) * CGFloat(percent)
thumbAnimation.fromValue = (oldProgress * bounds.width) - thumbLayer.bounds.width/2 progress = currentProgress
thumbAnimation.toValue = (newProgress * bounds.width) - thumbLayer.bounds.width/2
thumbAnimation.duration = duration
thumbAnimation.timingFunction = CAMediaTimingFunction(name: .linear)
progress = newProgress
CATransaction.begin() CATransaction.begin()
CATransaction.setDisableActions(true) CATransaction.setDisableActions(true)
foregroundLayer.bounds.size.width = newProgress * bounds.width updateLayers(for: currentProgress)
thumbLayer.position.x = (newProgress * bounds.width) - thumbLayer.bounds.width/2
CATransaction.commit() CATransaction.commit()
foregroundLayer.add(foregroundAnimation, forKey: nil) if percent >= 1.0 {
thumbLayer.add(thumbAnimation, forKey: nil) displayLink?.invalidate()
displayLink = nil
// 触发完成回调
animationCompletion()
}
} }
}
private func updateLayers(for progress: CGFloat) {
let foregroundWidth = bounds.width * progress
foregroundLayer.frame = CGRect(
x: 0,
y: bounds.height/2 - 3.5,
width: foregroundWidth,
height: 7
)
// 修改缩略图位置计算
let thumbSize = thumbLayer.bounds.size
// 计算中心点位置(确保始终显示完整缩略图)
let thumbCenterX = foregroundWidth - thumbSize.width/2
// 限制缩略图显示范围(不超出进度条边界)
let minX = -thumbSize.width/2 // 允许左侧部分超出
let maxX = bounds.width - thumbSize.width/2
thumbLayer.frame.origin.x = max(minX, min(thumbCenterX, maxX))
// 设置垂直居中
thumbLayer.frame.origin.y = bounds.height/2 - thumbSize.height/2
}
}
...@@ -136,8 +136,8 @@ class CompressViewModel{ ...@@ -136,8 +136,8 @@ class CompressViewModel{
private func compressSingleAsset(_ asset: PHAsset,_ compressionQuality : CGFloat, progress: @escaping (Float) -> Void, completion: @escaping (Data?, Error?) -> Void) { private func compressSingleAsset(_ asset: PHAsset,_ compressionQuality : CGFloat, progress: @escaping (Float) -> Void, completion: @escaping (Data?, Error?) -> Void) {
let options = PHImageRequestOptions() let options = PHImageRequestOptions()
options.isSynchronous = false options.isSynchronous = false
options.deliveryMode = .highQualityFormat // 设置为原图片
options.version = .original
PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, error) in PHImageManager.default().requestImageDataAndOrientation(for: asset, options: options) { (imageData, _, _, error) in
guard let originalData = imageData else { guard let originalData = imageData else {
completion(nil, nil) completion(nil, nil)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment