@@ -20,6 +20,10 @@ final class AnimatedImageModel : ObservableObject {
2020// Layout Binding Object
2121final class AnimatedImageLayout : ObservableObject {
2222 @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
2327}
2428
2529// View
@@ -31,53 +35,115 @@ public struct AnimatedImage : ViewRepresentable {
3135 var webContext : [ SDWebImageContextOption : Any ] ? = nil
3236
3337 #if os(macOS)
34- public typealias NSViewType = SDAnimatedImageView
38+ public typealias NSViewType = AnimatedImageViewWrapper
3539 #else
36- public typealias UIViewType = SDAnimatedImageView
40+ public typealias UIViewType = AnimatedImageViewWrapper
3741 #endif
3842
3943 #if os(macOS)
40- public func makeNSView( context: NSViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
44+ public func makeNSView( context: NSViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
4145 makeView ( context: context)
4246 }
4347
44- public func updateNSView( _ nsView: SDAnimatedImageView , context: NSViewRepresentableContext < AnimatedImage > ) {
48+ public func updateNSView( _ nsView: AnimatedImageViewWrapper , context: NSViewRepresentableContext < AnimatedImage > ) {
4549 updateView ( nsView, context: context)
4650 }
4751 #else
48- public func makeUIView( context: UIViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
52+ public func makeUIView( context: UIViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
4953 makeView ( context: context)
5054 }
5155
52- public func updateUIView( _ uiView: SDAnimatedImageView , context: UIViewRepresentableContext < AnimatedImage > ) {
56+ public func updateUIView( _ uiView: AnimatedImageViewWrapper , context: UIViewRepresentableContext < AnimatedImage > ) {
5357 updateView ( uiView, context: context)
5458 }
5559 #endif
5660
57- func makeView( context: ViewRepresentableContext < AnimatedImage > ) -> SDAnimatedImageView {
58- SDAnimatedImageView ( )
61+ func makeView( context: ViewRepresentableContext < AnimatedImage > ) -> AnimatedImageViewWrapper {
62+ AnimatedImageViewWrapper ( )
5963 }
6064
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
6367 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)
6569 }
6670
71+ layoutView ( view, context: context)
72+ }
73+
74+ func layoutView( _ view: AnimatedImageViewWrapper , context: ViewRepresentableContext < AnimatedImage > ) {
75+ // AspectRatio
76+ if let _ = imageLayout. aspectRatio {
77+ // TODO: Needs layer transform and geometry calculation
78+ }
79+
80+ // ContentMode
6781 switch imageLayout. contentMode {
6882 case . fit:
6983 #if os(macOS)
70- view. imageScaling = . scaleProportionallyUpOrDown
84+ view. wrapped . imageScaling = . scaleProportionallyUpOrDown
7185 #else
72- view. contentMode = . scaleAspectFit
86+ view. wrapped . contentMode = . scaleAspectFit
7387 #endif
7488 case . fill:
7589 #if os(macOS)
76- view. imageScaling = . scaleAxesIndependently
90+ view. wrapped . imageScaling = . scaleAxesIndependently
7791 #else
78- view. contentMode = . scaleToFill
92+ view. wrapped . contentMode = . scaleToFill
7993 #endif
8094 }
95+
96+ // RenderingMode
97+ if let renderingMode = imageLayout. renderingMode {
98+ switch renderingMode {
99+ case . template:
100+ #if os(macOS)
101+ view. wrapped. image? . isTemplate = true
102+ #else
103+ view. wrapped. image = view. wrapped. image? . withRenderingMode ( . alwaysTemplate)
104+ #endif
105+ case . original:
106+ #if os(macOS)
107+ view. wrapped. image? . isTemplate = false
108+ #else
109+ view. wrapped. image = view. wrapped. image? . withRenderingMode ( . alwaysOriginal)
110+ #endif
111+ @unknown default :
112+ // Future cases, not implements
113+ break
114+ }
115+ }
116+
117+ // Interpolation
118+ if let interpolation = imageLayout. interpolation {
119+ switch interpolation {
120+ case . high:
121+ view. interpolationQuality = . high
122+ case . medium:
123+ view. interpolationQuality = . medium
124+ case . low:
125+ view. interpolationQuality = . low
126+ case . none:
127+ view. interpolationQuality = . none
128+ @unknown default :
129+ // Future cases, not implements
130+ break
131+ }
132+ } else {
133+ view. interpolationQuality = . default
134+ }
135+
136+ // Antialiased
137+ view. shouldAntialias = imageLayout. antialiased
138+
139+ // Display
140+ #if os(macOS)
141+ view. needsLayout = true
142+ view. needsDisplay = true
143+ #else
144+ view. setNeedsLayout ( )
145+ view. setNeedsDisplay ( )
146+ #endif
81147 }
82148
83149 public func image( _ image: SDAnimatedImage ? ) -> Self {
@@ -90,15 +156,49 @@ public struct AnimatedImage : ViewRepresentable {
90156 return self
91157 }
92158
93- public func scaledToFit( ) -> Self {
94- imageLayout. contentMode = . fit
159+ public func resizable(
160+ capInsets: EdgeInsets = EdgeInsets ( ) ,
161+ resizingMode: Image . ResizingMode = . stretch) -> AnimatedImage
162+ {
163+ return self
164+ }
165+
166+ public func renderingMode( _ renderingMode: Image . TemplateRenderingMode ? ) -> AnimatedImage {
167+ imageLayout. renderingMode = renderingMode
168+ return self
169+ }
170+
171+ public func interpolation( _ interpolation: Image . Interpolation ) -> AnimatedImage {
172+ imageLayout. interpolation = interpolation
173+ return self
174+ }
175+
176+ public func antialiased( _ isAntialiased: Bool ) -> AnimatedImage {
177+ imageLayout. antialiased = isAntialiased
95178 return self
96179 }
97180
98- public func scaledToFill( ) -> Self {
99- imageLayout. contentMode = . fill
181+ public func aspectRatio( _ aspectRatio: CGFloat ? = nil , contentMode: ContentMode ) -> AnimatedImage {
182+ imageLayout. aspectRatio = aspectRatio
183+ imageLayout. contentMode = contentMode
100184 return self
101185 }
186+
187+ public func aspectRatio( _ aspectRatio: CGSize , contentMode: ContentMode ) -> AnimatedImage {
188+ var ratio : CGFloat ?
189+ if aspectRatio. width > 0 && aspectRatio. height > 0 {
190+ ratio = aspectRatio. width / aspectRatio. height
191+ }
192+ return self . aspectRatio ( ratio, contentMode: contentMode)
193+ }
194+
195+ public func scaledToFit( ) -> AnimatedImage {
196+ self . aspectRatio ( nil , contentMode: . fit)
197+ }
198+
199+ public func scaledToFill( ) -> AnimatedImage {
200+ self . aspectRatio ( nil , contentMode: . fill)
201+ }
102202}
103203
104204extension AnimatedImage {
@@ -123,4 +223,17 @@ extension AnimatedImage {
123223 }
124224}
125225
226+ #if DEBUG
227+ struct AnimatedImage_Previews : PreviewProvider {
228+ static var previews : some View {
229+ Group {
230+ AnimatedImage ( url: URL ( string: " http://assets.sbnation.com/assets/2512203/dogflops.gif " ) )
231+ . resizable ( )
232+ . aspectRatio ( contentMode: . fit)
233+ . padding ( )
234+ }
235+ }
236+ }
237+ #endif
238+
126239#endif
0 commit comments