react-native-photo-video-editor 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/PhotoVideoEditor.podspec +1 -0
- package/README.md +10 -6
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/android/build.gradle +1 -1
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/assets/Stickers/AUTUMN_1.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_10.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_11.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_12.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_13.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_14.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_15.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_16.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_17.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_18.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_2.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_3.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_4.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_5.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_6.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_7.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_8.png +0 -0
- package/android/src/main/assets/Stickers/AUTUMN_9.png +0 -0
- package/android/src/main/assets/Stickers/LOL_1.png +0 -0
- package/android/src/main/assets/Stickers/LOL_10.png +0 -0
- package/android/src/main/assets/Stickers/LOL_11.png +0 -0
- package/android/src/main/assets/Stickers/LOL_12.png +0 -0
- package/android/src/main/assets/Stickers/LOL_13.png +0 -0
- package/android/src/main/assets/Stickers/LOL_14.png +0 -0
- package/android/src/main/assets/Stickers/LOL_15.png +0 -0
- package/android/src/main/assets/Stickers/LOL_16.png +0 -0
- package/android/src/main/assets/Stickers/LOL_17.png +0 -0
- package/android/src/main/assets/Stickers/LOL_18.png +0 -0
- package/android/src/main/assets/Stickers/LOL_19.png +0 -0
- package/android/src/main/assets/Stickers/LOL_2.png +0 -0
- package/android/src/main/assets/Stickers/LOL_3.png +0 -0
- package/android/src/main/assets/Stickers/LOL_4.png +0 -0
- package/android/src/main/assets/Stickers/LOL_5.png +0 -0
- package/android/src/main/assets/Stickers/LOL_6.png +0 -0
- package/android/src/main/assets/Stickers/LOL_7.png +0 -0
- package/android/src/main/assets/Stickers/LOL_8.png +0 -0
- package/android/src/main/assets/Stickers/LOL_9.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_1.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_2.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_3.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_4.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_5.png +0 -0
- package/android/src/main/assets/Stickers/SPRING_6.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_1.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_10.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_11.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_12.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_13.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_14.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_15.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_16.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_17.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_18.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_19.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_2.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_20.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_21.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_3.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_4.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_5.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_6.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_7.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_8.png +0 -0
- package/android/src/main/assets/Stickers/SUMMER_9.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_1.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_12.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_13.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_14.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_15.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_16.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_2.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_25.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_26.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_27.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_28.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_29.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_3.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_30.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_31.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_32.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_7.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_8.png +0 -0
- package/android/src/main/assets/Stickers/TEXT_9.png +0 -0
- package/android/src/main/java/com/photovideoeditor/editor/PhotoVideoEditorActivity.kt +901 -651
- package/android/src/main/java/com/photovideoeditor/photo/export/PhotoExporter.kt +8 -23
- package/android/src/main/java/com/photovideoeditor/photo/render/CropGeometry.kt +71 -0
- package/android/src/main/java/com/photovideoeditor/photo/render/OverlayGeometry.kt +36 -0
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoEditSession.kt +5 -7
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoFilterPresets.kt +71 -41
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoLayer.kt +5 -1
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoLayerRenderer.kt +24 -1
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoTransformRenderer.kt +33 -0
- package/android/src/main/java/com/photovideoeditor/photo/render/PhotoTransformState.kt +6 -1
- package/android/src/main/java/com/photovideoeditor/photo/ui/CropOverlayView.kt +112 -122
- package/android/src/main/java/com/photovideoeditor/photo/ui/DrawOverlayView.kt +66 -0
- package/android/src/main/java/com/photovideoeditor/photo/ui/LayerOverlayView.kt +63 -14
- package/android/src/main/java/com/photovideoeditor/photo/ui/ZoomableImageView.kt +10 -0
- package/android/src/main/java/com/photovideoeditor/stickers/OnlineStickerSheet.kt +135 -104
- package/android/src/main/java/com/photovideoeditor/ui/components/CropPanel.kt +122 -0
- package/android/src/main/java/com/photovideoeditor/ui/components/EditorPanel.kt +250 -0
- package/android/src/main/java/com/photovideoeditor/ui/components/EditorToolSlider.kt +103 -0
- package/android/src/main/java/com/photovideoeditor/video/export/VideoExporter.kt +38 -11
- package/android/src/main/java/com/photovideoeditor/video/render/VideoCropEffects.kt +35 -0
- package/android/src/main/java/com/photovideoeditor/video/render/VideoEditSession.kt +10 -0
- package/android/src/main/java/com/photovideoeditor/video/render/VideoTransformState.kt +1 -0
- package/android/src/main/res/drawable/ic_draw.xml +6 -0
- package/android/src/main/res/drawable/ic_pause.xml +7 -0
- package/android/src/main/res/drawable/ic_play.xml +7 -0
- package/docs/api.md +1 -1
- package/docs/editor-ui-validation.md +22 -0
- package/docs/photo-editor.md +5 -6
- package/ios/Editor/PhotoVideoEditorViewController.swift +918 -494
- package/ios/Editor/UI/CropPanel.swift +97 -0
- package/ios/Editor/UI/EditorPanel.swift +334 -0
- package/ios/Editor/UI/EditorToolSlider.swift +22 -0
- package/ios/Editor/UI/TextEditorSheet.swift +84 -0
- package/ios/Photo/Export/PhotoExporter.swift +3 -3
- package/ios/Photo/Rendering/CropGeometry.swift +48 -0
- package/ios/Photo/Rendering/PhotoEditSession.swift +21 -10
- package/ios/Photo/Rendering/PhotoFilterPresets.swift +53 -23
- package/ios/Photo/Rendering/PhotoLayer.swift +14 -2
- package/ios/Photo/Rendering/PhotoLayerRenderer.swift +16 -1
- package/ios/Photo/Rendering/PhotoTransformState.swift +5 -0
- package/ios/Photo/UI/CropOverlayView.swift +98 -134
- package/ios/Photo/UI/DrawOverlayView.swift +48 -0
- package/ios/Photo/UI/FilterThumbnailLoader.swift +62 -0
- package/ios/Photo/UI/LayerOverlayView.swift +36 -11
- package/ios/Photo/UI/ZoomableImageView.swift +19 -1
- package/ios/Resources/Stickers/AUTUMN_1.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_10.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_11.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_12.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_13.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_14.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_15.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_16.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_17.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_18.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_2.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_3.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_4.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_5.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_6.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_7.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_8.png +0 -0
- package/ios/Resources/Stickers/AUTUMN_9.png +0 -0
- package/ios/Resources/Stickers/LOL_1.png +0 -0
- package/ios/Resources/Stickers/LOL_10.png +0 -0
- package/ios/Resources/Stickers/LOL_11.png +0 -0
- package/ios/Resources/Stickers/LOL_12.png +0 -0
- package/ios/Resources/Stickers/LOL_13.png +0 -0
- package/ios/Resources/Stickers/LOL_14.png +0 -0
- package/ios/Resources/Stickers/LOL_15.png +0 -0
- package/ios/Resources/Stickers/LOL_16.png +0 -0
- package/ios/Resources/Stickers/LOL_17.png +0 -0
- package/ios/Resources/Stickers/LOL_18.png +0 -0
- package/ios/Resources/Stickers/LOL_19.png +0 -0
- package/ios/Resources/Stickers/LOL_2.png +0 -0
- package/ios/Resources/Stickers/LOL_3.png +0 -0
- package/ios/Resources/Stickers/LOL_4.png +0 -0
- package/ios/Resources/Stickers/LOL_5.png +0 -0
- package/ios/Resources/Stickers/LOL_6.png +0 -0
- package/ios/Resources/Stickers/LOL_7.png +0 -0
- package/ios/Resources/Stickers/LOL_8.png +0 -0
- package/ios/Resources/Stickers/LOL_9.png +0 -0
- package/ios/Resources/Stickers/SPRING_1.png +0 -0
- package/ios/Resources/Stickers/SPRING_2.png +0 -0
- package/ios/Resources/Stickers/SPRING_3.png +0 -0
- package/ios/Resources/Stickers/SPRING_4.png +0 -0
- package/ios/Resources/Stickers/SPRING_5.png +0 -0
- package/ios/Resources/Stickers/SPRING_6.png +0 -0
- package/ios/Resources/Stickers/SUMMER_1.png +0 -0
- package/ios/Resources/Stickers/SUMMER_10.png +0 -0
- package/ios/Resources/Stickers/SUMMER_11.png +0 -0
- package/ios/Resources/Stickers/SUMMER_12.png +0 -0
- package/ios/Resources/Stickers/SUMMER_13.png +0 -0
- package/ios/Resources/Stickers/SUMMER_14.png +0 -0
- package/ios/Resources/Stickers/SUMMER_15.png +0 -0
- package/ios/Resources/Stickers/SUMMER_16.png +0 -0
- package/ios/Resources/Stickers/SUMMER_17.png +0 -0
- package/ios/Resources/Stickers/SUMMER_18.png +0 -0
- package/ios/Resources/Stickers/SUMMER_19.png +0 -0
- package/ios/Resources/Stickers/SUMMER_2.png +0 -0
- package/ios/Resources/Stickers/SUMMER_20.png +0 -0
- package/ios/Resources/Stickers/SUMMER_21.png +0 -0
- package/ios/Resources/Stickers/SUMMER_3.png +0 -0
- package/ios/Resources/Stickers/SUMMER_4.png +0 -0
- package/ios/Resources/Stickers/SUMMER_5.png +0 -0
- package/ios/Resources/Stickers/SUMMER_6.png +0 -0
- package/ios/Resources/Stickers/SUMMER_7.png +0 -0
- package/ios/Resources/Stickers/SUMMER_8.png +0 -0
- package/ios/Resources/Stickers/SUMMER_9.png +0 -0
- package/ios/Resources/Stickers/TEXT_1.png +0 -0
- package/ios/Resources/Stickers/TEXT_12.png +0 -0
- package/ios/Resources/Stickers/TEXT_13.png +0 -0
- package/ios/Resources/Stickers/TEXT_14.png +0 -0
- package/ios/Resources/Stickers/TEXT_15.png +0 -0
- package/ios/Resources/Stickers/TEXT_16.png +0 -0
- package/ios/Resources/Stickers/TEXT_2.png +0 -0
- package/ios/Resources/Stickers/TEXT_25.png +0 -0
- package/ios/Resources/Stickers/TEXT_26.png +0 -0
- package/ios/Resources/Stickers/TEXT_27.png +0 -0
- package/ios/Resources/Stickers/TEXT_28.png +0 -0
- package/ios/Resources/Stickers/TEXT_29.png +0 -0
- package/ios/Resources/Stickers/TEXT_3.png +0 -0
- package/ios/Resources/Stickers/TEXT_30.png +0 -0
- package/ios/Resources/Stickers/TEXT_31.png +0 -0
- package/ios/Resources/Stickers/TEXT_32.png +0 -0
- package/ios/Resources/Stickers/TEXT_7.png +0 -0
- package/ios/Resources/Stickers/TEXT_8.png +0 -0
- package/ios/Resources/Stickers/TEXT_9.png +0 -0
- package/ios/Resources/Stickers/a_pety_icon.png +0 -0
- package/ios/Stickers/OnlineStickerSheetViewController.swift +102 -159
- package/ios/Video/Export/VideoExporter.swift +10 -1
- package/ios/Video/Render/VideoCropGeometry.swift +48 -0
- package/ios/Video/Render/VideoTransformState.swift +1 -0
- package/lib/module/index.js +2 -2
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/types.d.ts +2 -2
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +1 -1
- package/src/types.ts +2 -2
- package/android/src/main/java/com/photovideoeditor/stickers/OpenMojiCatalog.kt +0 -172
- package/android/src/main/java/com/photovideoeditor/stickers/RemoteImageLoader.kt +0 -110
- package/ios/Stickers/OpenMojiCatalog.swift +0 -188
- package/ios/Stickers/RemoteImageLoader.swift +0 -127
|
@@ -8,7 +8,9 @@ final class LayerOverlayView: UIView {
|
|
|
8
8
|
var maxScale: CGFloat = 8
|
|
9
9
|
var layers: [PhotoLayer] = [] { didSet { setNeedsDisplay() } }
|
|
10
10
|
var selectedLayerID: String? { didSet { setNeedsDisplay() } }
|
|
11
|
+
var onLayerDelete: ((String) -> Void)?
|
|
11
12
|
var onLayerTapped: ((String?) -> Void)?
|
|
13
|
+
var onLayerDoubleTapped: ((String) -> Void)?
|
|
12
14
|
var onLayerTransformChanged: ((_ id: String, _ x: CGFloat, _ y: CGFloat, _ scale: CGFloat, _ rotationDegrees: CGFloat) -> Void)?
|
|
13
15
|
var onLayerTransformEnded: ((String) -> Void)?
|
|
14
16
|
|
|
@@ -41,19 +43,24 @@ final class LayerOverlayView: UIView {
|
|
|
41
43
|
context.translateBy(x: center.x, y: center.y)
|
|
42
44
|
context.rotate(by: layer.rotationDegrees * .pi / 180)
|
|
43
45
|
context.setStrokeColor(UIColor.white.cgColor)
|
|
44
|
-
context.setLineWidth(
|
|
45
|
-
context.setLineDash(phase: 0, lengths: [8, 5])
|
|
46
|
+
context.setLineWidth(1)
|
|
46
47
|
context.stroke(CGRect(x: -half.width, y: -half.height, width: half.width * 2, height: half.height * 2))
|
|
47
48
|
context.setLineDash(phase: 0, lengths: [])
|
|
48
49
|
context.setFillColor(UIColor.white.cgColor)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
context
|
|
50
|
+
for point in [CGPoint(x: -half.width, y: -half.height), CGPoint(x: half.width, y: -half.height), CGPoint(x: -half.width, y: half.height), CGPoint(x: half.width, y: half.height)] {
|
|
51
|
+
context.fillEllipse(in: CGRect(x: point.x - 4, y: point.y - 4, width: 8, height: 8))
|
|
52
|
+
}
|
|
53
|
+
drawControl(context, point: CGPoint(x: -half.width, y: -half.height), symbol: "xmark", tint: .systemRed)
|
|
54
|
+
drawControl(context, point: CGPoint(x: half.width, y: half.height), symbol: "arrow.up.left.and.arrow.down.right", tint: DesignTokens.primary)
|
|
54
55
|
context.restoreGState()
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
private func drawControl(_ context: CGContext, point: CGPoint, symbol: String, tint: UIColor) {
|
|
59
|
+
context.setFillColor(UIColor.white.cgColor)
|
|
60
|
+
context.fillEllipse(in: CGRect(x: point.x - handleRadius, y: point.y - handleRadius, width: handleRadius * 2, height: handleRadius * 2))
|
|
61
|
+
UIImage(systemName: symbol)?.withTintColor(tint, renderingMode: .alwaysOriginal).draw(in: CGRect(x: point.x - 7, y: point.y - 7, width: 14, height: 14))
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
58
65
|
guard imageBounds.width > 0 else { return }
|
|
59
66
|
for touch in touches {
|
|
@@ -70,6 +77,11 @@ final class LayerOverlayView: UIView {
|
|
|
70
77
|
return
|
|
71
78
|
}
|
|
72
79
|
let selected = selectedLayer()
|
|
80
|
+
if let selected, !selected.locked {
|
|
81
|
+
let center = center(of: selected); let handle = handlePoint(selected)
|
|
82
|
+
let deletePoint = CGPoint(x: center.x * 2 - handle.x, y: center.y * 2 - handle.y)
|
|
83
|
+
if distance(deletePoint, point) <= handleTouchRadius { onLayerDelete?(selected.id); resetGesture(); return }
|
|
84
|
+
}
|
|
73
85
|
let handleHit = selected.flatMap { !$0.locked && isHandleHit($0, point) ? $0 : nil }
|
|
74
86
|
let hit = handleHit ?? hitTest(point)
|
|
75
87
|
onLayerTapped?(hit?.id)
|
|
@@ -107,13 +119,22 @@ final class LayerOverlayView: UIView {
|
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
|
|
110
|
-
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
122
|
+
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
|
123
|
+
if let touch = touches.first, touch.tapCount >= 2, let id = gestureID { onLayerDoubleTapped?(id) }
|
|
124
|
+
endTouches(touches)
|
|
125
|
+
}
|
|
111
126
|
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { endTouches(touches) }
|
|
112
127
|
|
|
113
128
|
private func endTouches(_ touches: Set<UITouch>) {
|
|
114
129
|
let endedPrimary = primaryTouch.map { touches.contains($0) } ?? false
|
|
115
130
|
let endedSecondary = secondaryTouch.map { touches.contains($0) } ?? false
|
|
116
|
-
if endedPrimary || endedSecondary {
|
|
131
|
+
if endedPrimary || endedSecondary {
|
|
132
|
+
let remaining = endedPrimary ? secondaryTouch : primaryTouch
|
|
133
|
+
if let remaining, !touches.contains(remaining), let layer = currentGestureLayer() {
|
|
134
|
+
primaryTouch = remaining; secondaryTouch = nil
|
|
135
|
+
startLayer = layer; startPoint = remaining.location(in: self); gesture = .drag
|
|
136
|
+
} else { finishGesture() }
|
|
137
|
+
}
|
|
117
138
|
}
|
|
118
139
|
private func emit(_ layer: PhotoLayer, x: CGFloat, y: CGFloat, scale: CGFloat, rotation: CGFloat) {
|
|
119
140
|
onLayerTransformChanged?(layer.id, x, y, scale, rotation)
|
|
@@ -141,13 +162,17 @@ final class LayerOverlayView: UIView {
|
|
|
141
162
|
case .sticker:
|
|
142
163
|
// Mirrors `PhotoLayerRenderer.drawSticker`'s `shortSide * 0.18` box (half-extent = 0.09).
|
|
143
164
|
let half = shortSide * 0.09
|
|
144
|
-
base = CGSize(width: half, height: half)
|
|
165
|
+
base = CGSize(width: half + 4, height: half / max(layer.overlayAspectRatio ?? 1, 0.001) + 4)
|
|
145
166
|
case .overlay:
|
|
146
167
|
// Mirrors `PhotoLayerRenderer.drawOverlay`'s box: full canvas width, height from aspect ratio.
|
|
147
168
|
let aspectRatio = layer.overlayAspectRatio.flatMap { $0 > 0 ? $0 : nil } ?? 1
|
|
148
169
|
base = CGSize(width: imageBounds.width / 2, height: imageBounds.width / (2 * aspectRatio))
|
|
170
|
+
case .drawing:
|
|
171
|
+
let maxX = layer.drawPoints.map { abs($0.0) }.max() ?? 0.08
|
|
172
|
+
let maxY = layer.drawPoints.map { abs($0.1) }.max() ?? 0.08
|
|
173
|
+
base = CGSize(width: maxX * imageBounds.width + handleRadius, height: maxY * imageBounds.height + handleRadius)
|
|
149
174
|
}
|
|
150
|
-
return CGSize(width: max(
|
|
175
|
+
return CGSize(width: max(24, base.width * layer.scale), height: max(24, base.height * layer.scale))
|
|
151
176
|
}
|
|
152
177
|
private func handlePoint(_ layer: PhotoLayer) -> CGPoint {
|
|
153
178
|
let center = center(of: layer); let half = selectionHalfExtents(layer); let radians = layer.rotationDegrees * .pi / 180
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import UIKit
|
|
2
|
+
import AVFoundation
|
|
2
3
|
|
|
3
4
|
/// UIImageView supporting pinch-to-zoom and single-finger pan for the photo
|
|
4
5
|
/// preview, reporting the current on-screen image rect via `onBoundsChanged`
|
|
@@ -14,6 +15,7 @@ final class ZoomableImageView: UIImageView {
|
|
|
14
15
|
|
|
15
16
|
private let pinchRecognizer = UIPinchGestureRecognizer()
|
|
16
17
|
private let panRecognizer = UIPanGestureRecognizer()
|
|
18
|
+
private var lastLayoutSize: CGSize = .zero
|
|
17
19
|
private var minScale: CGFloat = 1
|
|
18
20
|
private var maxScale: CGFloat = 4
|
|
19
21
|
|
|
@@ -37,12 +39,28 @@ final class ZoomableImageView: UIImageView {
|
|
|
37
39
|
reportBounds()
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
func setRenderedBounds(_ target: CGRect) {
|
|
43
|
+
guard let image, bounds.width > 0, bounds.height > 0 else { return }
|
|
44
|
+
let fitted = AVMakeRect(aspectRatio: image.size, insideRect: bounds)
|
|
45
|
+
let scale = target.width / max(fitted.width, 0.001)
|
|
46
|
+
transform = CGAffineTransform(translationX: target.midX - center.x, y: target.midY - center.y).scaledBy(x: scale, y: scale)
|
|
47
|
+
}
|
|
48
|
+
|
|
40
49
|
func currentImageBounds() -> CGRect {
|
|
41
50
|
guard let image = image, bounds.width > 0, bounds.height > 0, image.size.width > 0, image.size.height > 0 else { return bounds }
|
|
42
51
|
let scale = min(bounds.width / image.size.width, bounds.height / image.size.height)
|
|
43
52
|
let fittedSize = CGSize(width: image.size.width * scale, height: image.size.height * scale)
|
|
44
53
|
let origin = CGPoint(x: (bounds.width - fittedSize.width) / 2, y: (bounds.height - fittedSize.height) / 2)
|
|
45
|
-
|
|
54
|
+
let rect = CGRect(origin: origin, size: fittedSize)
|
|
55
|
+
return superview.map { convert(rect, to: $0) } ?? rect
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override func layoutSubviews() {
|
|
59
|
+
super.layoutSubviews()
|
|
60
|
+
if bounds.size != lastLayoutSize {
|
|
61
|
+
lastLayoutSize = bounds.size
|
|
62
|
+
resetToFit()
|
|
63
|
+
}
|
|
46
64
|
}
|
|
47
65
|
|
|
48
66
|
private func reportBounds() {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|