@@ -20,6 +20,10 @@ final class AnimatedImageModel : ObservableObject {
20
20
// Layout Binding Object
21
21
final class AnimatedImageLayout : ObservableObject {
22
22
@Published var contentMode : ContentMode = . fill
23
+ @Published var aspectRatio : CGFloat ?
24
+ @Published var renderingMode : Image . TemplateRenderingMode ?
25
+ @Published var interpolation : Image . Interpolation ?
26
+ @Published var antialiased : Bool = false
23
27
}
24
28
25
29
// View
@@ -31,53 +35,111 @@ public struct AnimatedImage : ViewRepresentable {
31
35
var webContext : [ SDWebImageContextOption : Any ] ? = nil
32
36
33
37
#if os(macOS)
34
- public typealias NSViewType = SDAnimatedImageView
38
+ public typealias NSViewType = AnimatedImageViewWrapper
35
39
#else
36
- public typealias UIViewType = SDAnimatedImageView
40
+ public typealias UIViewType = AnimatedImageViewWrapper
37
41
#endif
38
42
39
43
#if os(macOS)
40
- public func makeNSView( context: NSViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
44
+ public func makeNSView( context: NSViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
41
45
makeView ( context: context)
42
46
}
43
47
44
- public func updateNSView( _ nsView: SDAnimatedImageView , context: NSViewRepresentableContext < AnimatedImage > ) {
48
+ public func updateNSView( _ nsView: AnimatedImageViewWrapper , context: NSViewRepresentableContext < AnimatedImage > ) {
45
49
updateView ( nsView, context: context)
46
50
}
47
51
#else
48
- public func makeUIView( context: UIViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
52
+ public func makeUIView( context: UIViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
49
53
makeView ( context: context)
50
54
}
51
55
52
- public func updateUIView( _ uiView: SDAnimatedImageView , context: UIViewRepresentableContext < AnimatedImage > ) {
56
+ public func updateUIView( _ uiView: AnimatedImageViewWrapper , context: UIViewRepresentableContext < AnimatedImage > ) {
53
57
updateView ( uiView, context: context)
54
58
}
55
59
#endif
56
60
57
- func makeView( context: ViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
58
- SDAnimatedImageView ( )
61
+ func makeView( context: ViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
62
+ AnimatedImageViewWrapper ( )
59
63
}
60
64
61
- func updateView( _ view: SDAnimatedImageView , context: ViewRepresentableContext < AnimatedImage > ) {
62
- view. image = imageModel. image
65
+ func updateView( _ view: AnimatedImageViewWrapper , context: ViewRepresentableContext < AnimatedImage > ) {
66
+ view. wrapped . image = imageModel. image
63
67
if let url = imageModel. url {
64
- view. sd_setImage ( with: url, placeholderImage: view . image , options: webOptions, context: webContext)
68
+ view. wrapped . sd_setImage ( with: url, placeholderImage: nil , options: webOptions, context: webContext)
65
69
}
66
70
71
+ layoutView ( view, context: context)
72
+ }
73
+
74
+ func layoutView( _ view: AnimatedImageViewWrapper , context: ViewRepresentableContext < AnimatedImage > ) {
75
+ // AspectRatio
76
+ if let aspectRatio = imageLayout. aspectRatio {
77
+ // Not implements
78
+ }
79
+ // ContentMode
67
80
switch imageLayout. contentMode {
68
81
case . fit:
69
82
#if os(macOS)
70
- view. imageScaling = . scaleProportionallyUpOrDown
83
+ view. wrapped . imageScaling = . scaleProportionallyUpOrDown
71
84
#else
72
- view. contentMode = . scaleAspectFit
85
+ view. wrapped . contentMode = . scaleAspectFit
73
86
#endif
74
87
case . fill:
75
88
#if os(macOS)
76
- view. imageScaling = . scaleAxesIndependently
89
+ view. wrapped . imageScaling = . scaleAxesIndependently
77
90
#else
78
- view. contentMode = . scaleToFill
91
+ view. wrapped . contentMode = . scaleToFill
79
92
#endif
80
93
}
94
+ // RenderingMode
95
+ if let renderingMode = imageLayout. renderingMode {
96
+ switch renderingMode {
97
+ case . template:
98
+ #if os(macOS)
99
+ view. wrapped. image? . isTemplate = true
100
+ #else
101
+ view. wrapped. image = view. wrapped. image? . withRenderingMode ( . alwaysTemplate)
102
+ #endif
103
+ case . original:
104
+ #if os(macOS)
105
+ view. wrapped. image? . isTemplate = false
106
+ #else
107
+ view. wrapped. image = view. wrapped. image? . withRenderingMode ( . alwaysOriginal)
108
+ #endif
109
+ @unknown default :
110
+ // Future cases, not implements
111
+ break
112
+ }
113
+ }
114
+ // Interpolation
115
+ if let interpolation = imageLayout. interpolation {
116
+ switch interpolation {
117
+ case . high:
118
+ view. interpolationQuality = . high
119
+ case . medium:
120
+ view. interpolationQuality = . medium
121
+ case . low:
122
+ view. interpolationQuality = . low
123
+ case . none:
124
+ view. interpolationQuality = . none
125
+ @unknown default :
126
+ // Future cases, not implements
127
+ break
128
+ }
129
+ } else {
130
+ view. interpolationQuality = . default
131
+ }
132
+ // Antialiased
133
+ view. shouldAntialias = imageLayout. antialiased
134
+
135
+ // Display
136
+ #if os(macOS)
137
+ view. updateConstraintsIfNeeded ( )
138
+ view. needsDisplay = true
139
+ #else
140
+ view. updateConstraintsIfNeeded ( )
141
+ view. setNeedsDisplay ( )
142
+ #endif
81
143
}
82
144
83
145
public func image( _ image: SDAnimatedImage ? ) -> Self {
@@ -90,15 +152,49 @@ public struct AnimatedImage : ViewRepresentable {
90
152
return self
91
153
}
92
154
93
- public func scaledToFit( ) -> Self {
94
- imageLayout. contentMode = . fit
155
+ public func resizable(
156
+ capInsets: EdgeInsets = EdgeInsets ( ) ,
157
+ resizingMode: Image . ResizingMode = . stretch) -> AnimatedImage
158
+ {
159
+ return self
160
+ }
161
+
162
+ public func renderingMode( _ renderingMode: Image . TemplateRenderingMode ? ) -> AnimatedImage {
163
+ imageLayout. renderingMode = renderingMode
164
+ return self
165
+ }
166
+
167
+ public func interpolation( _ interpolation: Image . Interpolation ) -> AnimatedImage {
168
+ imageLayout. interpolation = interpolation
169
+ return self
170
+ }
171
+
172
+ public func antialiased( _ isAntialiased: Bool ) -> AnimatedImage {
173
+ imageLayout. antialiased = isAntialiased
95
174
return self
96
175
}
97
176
98
- public func scaledToFill( ) -> Self {
99
- imageLayout. contentMode = . fill
177
+ public func aspectRatio( _ aspectRatio: CGFloat ? = nil , contentMode: ContentMode ) -> AnimatedImage {
178
+ imageLayout. aspectRatio = aspectRatio
179
+ imageLayout. contentMode = contentMode
100
180
return self
101
181
}
182
+
183
+ public func aspectRatio( _ aspectRatio: CGSize , contentMode: ContentMode ) -> AnimatedImage {
184
+ var ratio : CGFloat ?
185
+ if aspectRatio. width > 0 && aspectRatio. height > 0 {
186
+ ratio = aspectRatio. width / aspectRatio. height
187
+ }
188
+ return self . aspectRatio ( ratio, contentMode: contentMode)
189
+ }
190
+
191
+ public func scaledToFit( ) -> AnimatedImage {
192
+ self . aspectRatio ( nil , contentMode: . fit)
193
+ }
194
+
195
+ public func scaledToFill( ) -> AnimatedImage {
196
+ self . aspectRatio ( nil , contentMode: . fill)
197
+ }
102
198
}
103
199
104
200
extension AnimatedImage {
@@ -123,4 +219,17 @@ extension AnimatedImage {
123
219
}
124
220
}
125
221
222
+ #if DEBUG
223
+ struct AnimatedImage_Previews : PreviewProvider {
224
+ static var previews : some View {
225
+ Group {
226
+ AnimatedImage ( url: URL ( string: " http://assets.sbnation.com/assets/2512203/dogflops.gif " ) )
227
+ . resizable ( )
228
+ . aspectRatio ( contentMode: . fit)
229
+ . padding ( )
230
+ }
231
+ }
232
+ }
233
+ #endif
234
+
126
235
#endif
0 commit comments