// // IMImageContainerLogic.swift // Crush // // Created by Leon on 2025/8/22. // import UIKit /// 设计稿中的常量 struct ImageDisplayConstants { var W_MAX: CGFloat var H_MAX: CGFloat var W_MIN: CGFloat var H_MIN: CGFloat var RATIO_MIN: CGFloat var RATIO_MAX: CGFloat static let `default` = ImageDisplayConstants( W_MAX: 372, H_MAX: 372, W_MIN: 48, H_MIN: 48, RATIO_MIN: 9.0 / 21.0, RATIO_MAX: 21.0 / 9.0 ) } /// 计算结果 struct CalculatedImageSize { var width: CGFloat var height: CGFloat var type: ImageType var ratio: CGFloat } /// 图片类型 enum ImageType: String { case large case small case tiny } /// 工具类 class ImageDisplayLogic { /// 限制数值范围 private static func clamp(_ value: CGFloat, min: CGFloat, max: CGFloat) -> CGFloat { return Swift.min(Swift.max(value, min), max) } /// 判断图片类型 static func getImageType(originalWidth: CGFloat, originalHeight: CGFloat, constants: ImageDisplayConstants = .default) -> ImageType { let W_MAX = constants.W_MAX let H_MAX = constants.H_MAX let W_MIN = constants.W_MIN let H_MIN = constants.H_MIN // A. 大图 let isLargeImage = ( (originalWidth >= W_MAX && originalHeight > (9.0/21.0) * H_MAX) || (originalHeight >= H_MAX && originalWidth > (9.0/21.0) * W_MAX) ) if isLargeImage { return .large } // C. 超小图 let isTinyImage = (originalWidth < W_MIN || originalHeight < H_MIN) if isTinyImage { return .tiny } // B. 小图 return .small } /// 计算最终展示比例 static func calculateDisplayRatio(originalWidth: CGFloat, originalHeight: CGFloat, imageType: ImageType, constants: ImageDisplayConstants = .default) -> CGFloat { let originalRatio = originalWidth / originalHeight if imageType == .large { return clamp(originalRatio, min: constants.RATIO_MIN, max: constants.RATIO_MAX) } else { return originalRatio } } /// 计算最终展示尺寸 static func calculateImageDisplaySize(originalWidth: CGFloat, originalHeight: CGFloat, constants: ImageDisplayConstants = .default) -> CalculatedImageSize { let W_MAX = constants.W_MAX let H_MAX = constants.H_MAX let W_MIN = constants.W_MIN let H_MIN = constants.H_MIN // 1. 类型 let imageType = getImageType(originalWidth: originalWidth, originalHeight: originalHeight, constants: constants) // 2. 比例 let displayRatio = calculateDisplayRatio(originalWidth: originalWidth, originalHeight: originalHeight, imageType: imageType, constants: constants) // 3. 最终尺寸 var finalWidth: CGFloat = 0 var finalHeight: CGFloat = 0 switch imageType { case .large: if displayRatio >= 1 { // 宽图 finalWidth = W_MAX finalHeight = W_MAX / displayRatio } else { // 高图 finalHeight = H_MAX finalWidth = H_MAX * displayRatio } case .small: if displayRatio >= 1 { finalHeight = originalHeight finalWidth = min(originalWidth, W_MAX) } else { finalWidth = originalWidth finalHeight = min(originalHeight, H_MAX) } case .tiny: if displayRatio >= 1 { finalHeight = H_MIN finalWidth = min(H_MIN * displayRatio, W_MAX) } else { finalWidth = W_MIN finalHeight = min(W_MIN / displayRatio, H_MAX) } } return CalculatedImageSize( width: round(finalWidth), height: round(finalHeight), type: imageType, ratio: displayRatio ) } /// 根据容器宽度调整常量 static func adjustConstants(for containerWidth: CGFloat) -> ImageDisplayConstants { let maxSize = min(containerWidth * 0.5, 372) var c = ImageDisplayConstants.default c.W_MAX = maxSize c.H_MAX = maxSize return c } }