├── snapShot ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png ├── 9.png ├── 10.png ├── logo.png └── Banners.png ├── TGImage ├── TGImage │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── 2.imageset │ │ │ ├── 2.png │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── AppDelegate.swift │ ├── TGImage │ │ └── TGImage.swift │ └── ViewController.swift ├── TGImage.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj └── TGImage.podspec ├── LICENSE ├── .gitignore └── README.md /snapShot/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/1.png -------------------------------------------------------------------------------- /snapShot/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/2.png -------------------------------------------------------------------------------- /snapShot/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/3.png -------------------------------------------------------------------------------- /snapShot/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/4.png -------------------------------------------------------------------------------- /snapShot/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/5.png -------------------------------------------------------------------------------- /snapShot/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/6.png -------------------------------------------------------------------------------- /snapShot/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/7.png -------------------------------------------------------------------------------- /snapShot/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/8.png -------------------------------------------------------------------------------- /snapShot/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/9.png -------------------------------------------------------------------------------- /snapShot/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/10.png -------------------------------------------------------------------------------- /snapShot/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/logo.png -------------------------------------------------------------------------------- /snapShot/Banners.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/snapShot/Banners.png -------------------------------------------------------------------------------- /TGImage/TGImage/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TGImage/TGImage/Assets.xcassets/2.imageset/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/targetcloud/TGImage/HEAD/TGImage/TGImage/Assets.xcassets/2.imageset/2.png -------------------------------------------------------------------------------- /TGImage/TGImage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TGImage/TGImage/Assets.xcassets/2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "2.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TGImage/TGImage.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "TGImage" 3 | s.version = "0.0.2" 4 | s.summary = "一款以最时髦的方式来使用UIImage的swift插件" 5 | s.homepage = "https://github.com/targetcloud/TGImage" 6 | s.license = "MIT" 7 | s.author = { "targetcloud" => "targetcloud@163.com" } 8 | s.platform = :ios, "8.0" 9 | s.source = { :git => "https://github.com/targetcloud/TGImage.git", :tag => s.version } 10 | s.source_files = "TGImage/TGImage/TGImage/**/*.{swift,h,m}" 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /TGImage/TGImage/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | } 43 | ], 44 | "info" : { 45 | "version" : 1, 46 | "author" : "xcode" 47 | } 48 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 targetcloud 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /TGImage/TGImage/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | -------------------------------------------------------------------------------- /TGImage/TGImage/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TGImage/TGImage/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /TGImage/TGImage/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TGImage 4 | // 5 | // Created by targetcloud on 2017/6/30. 6 | // Copyright © 2017年 targetcloud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # TGImage 4 | 5 | 一款以最时髦的方式来使用UIImage的swift插件 6 | 7 | ![Swift](https://img.shields.io/badge/Swift-3.0-orange.svg) 8 | ![Build](https://img.shields.io/badge/build-passing-green.svg) 9 | ![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat) 10 | ![Platform](https://img.shields.io/cocoapods/p/Pastel.svg?style=flat) 11 | ![Cocoapod](https://img.shields.io/badge/pod-v0.0.2-blue.svg) 12 | 13 | 14 | ## Features 15 | - [x] 支持链式编程 16 | - [x] 支持with 和size两种开启模式 17 | - [x] 支持+= 、+两种图片相加操作 18 | - [x] 用例丰富、快速使用 19 | 20 | ## Usage 21 | 22 | #### size开启模式 23 | 24 | ```swift 25 | UIImage.size() 或.resizable() 26 | .color .border .corner 27 | .image 28 | .position 29 | ``` 30 | 31 | > ##### 其中size开启的是固定大小模式、resizable开启的是可变大小模式 32 | > ##### 其中color支持传入渐变色,如 gradient: [.lightGray, .white], locations: [0, 1], from: CGPoint(x: 0, y: 1), to: CGPoint(x: 0, y: 0) 33 | > ##### 其中border可以设置color、width、radius、alignment 34 | > ##### 其中corner可以分别设置4个角或统一设置四个角为同一个值 35 | > ##### 其中image用于生成 UIImage 36 | > ##### 其中position用于后面+或+=时用 37 | 38 | ##### 注意:按上面大的顺序链式编程,在size和image之间的color 、border 、corner没有顺序要求 39 | 40 | 41 | size开启方式 42 | 43 | ```swift 44 | UIImage.size(width: CGFloat, height: CGFloat) 45 | UIImage.size(_ size: CGSize) 46 | UIImage.resizable() 47 | ``` 48 | 49 | #### with CGContext开启模式 50 | 51 | 支持UIImage.with类方式开启或image.with类实例开启 52 | 53 | 类方式是返回单图,实例方式开始是在实例图的基础再加上with图,实际是两图相加模式 54 | 55 | 56 | with开启方式 57 | 58 | ```swift 59 | UIImage.with(width: CGFloat, height: CGFloat, block: ContextBlock)//单 60 | image.with(size: CGSize, opaque: Bool = false, scale: CGFloat = 0, block: ContextBlock)//相加 61 | image.with(_ block: ContextBlock)//单 62 | ``` 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | #### 应用场景及Demo(以下图都是用代码绘制的哦) 72 | 73 | 在cell的某角上放一个某角载剪的渐变图 74 | 75 | 在某图上再画图 76 | 77 | 多个图相加放入容器图中 78 | 79 | … 80 | 81 | #### 1 82 | 83 | ```swift 84 | UIImageView(image: ({ () -> UIImage in 85 | var container = UIImage.size(width: 180, height: 20) 86 | .color(.clear) 87 | .image 88 | for i in 0..<7{ 89 | let doti = UIImage.size(width: 20, height: 20) 90 | .color(gradient: [UIColor.randomColor(), UIColor.randomColor()], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 91 | .corner(radius: 10) 92 | .image 93 | .position(CGPoint(x: i * 20 + (i + 1) * 3, y: 0)) 94 | container = container + doti 95 | } 96 | return container 97 | })()) 98 | ``` 99 | 100 | 101 | 102 | 103 | #### 2 104 | 105 | ```swift 106 | UIImageView(image: ({ () -> UIImage in 107 | var container = UIImage.size(width: 30, height: 120) 108 | .color(.clear) 109 | .image 110 | for i in 0..<4{ 111 | let doti = UIImage.size(width: CGFloat(30 - i * 4), height: CGFloat(30 - i * 4)) 112 | .color(gradient: [UIColor.randomColor(), UIColor.randomColor()], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 113 | .corner(radius: CGFloat(30 - i * 4) * 0.5) 114 | .image 115 | .position(CGPoint(x: i * 2, y: 30 * i + (i + 1) * 3)) 116 | container += doti 117 | } 118 | return container 119 | })()) 120 | ``` 121 | 122 | 123 | 124 | 125 | #### 3 126 | 127 | ```swift 128 | UIImageView(image: 129 | UIImage.size(width: 27, height: 27) 130 | .corner(radius: 13.5) 131 | .color(.white) 132 | .border(color: .lightGray) 133 | .border(width: 2) 134 | .image 135 | .with({ context in 136 | context.setLineCap(.round) 137 | UIColor.lightGray.setStroke() 138 | context.setLineWidth(2) 139 | context.move(to: CGPoint(x: 6, y: 12)) 140 | context.addLine(to: CGPoint(x: 9, y: 18)) 141 | context.move(to: CGPoint(x: 9, y: 18)) 142 | context.addLine(to: CGPoint(x: 21, y: 9)) 143 | context.strokePath() 144 | }) 145 | ) 146 | ``` 147 | 148 | 149 | 150 | 151 | #### 4 152 | 153 | ```swift 154 | UIImageView(image: UIImage.size(width: 100, height: 100) 155 | .color(gradient: [.green, .blue], locations: [0, 1], from: CGPoint(x: 0, y: 1), to: CGPoint(x: 0, y: 0)) 156 | .border(gradient: [.red, .yellow], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 0)) 157 | .border(width: 5) 158 | .border(alignment: .outside) 159 | .corner(topLeft: 20) 160 | .corner(topRight: 50) 161 | .corner(bottomLeft: 50) 162 | .corner(bottomRight: 20) 163 | .image) 164 | ``` 165 | 166 | 167 | 168 | 169 | #### 5 170 | 171 | ```swift 172 | UIImageView(image: ({ () -> UIImage in 173 | let background = UIImage.size(width: 120, height: 120) 174 | .color(gradient: [.black, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 0, y: 1)) 175 | .corner(radius: 13.5) 176 | .image 177 | let circle = UIImage.size(width: 106, height: 106) 178 | .color(.white) 179 | .corner(radius: 50) 180 | .image 181 | let center = UIImage.size(width: 8, height: 8) 182 | .color(.black) 183 | .corner(radius: 3) 184 | .image 185 | let clock = background + circle + center 186 | return clock.with { context in 187 | context.setLineCap(.round) 188 | UIColor.black.setStroke() 189 | context.setLineWidth(2) 190 | context.move(to: CGPoint(x: clock.size.width / 2, y: clock.size.height / 2)) 191 | context.addLine(to: CGPoint(x: clock.size.width / 2 - 5, y: 15)) 192 | context.move(to: CGPoint(x: clock.size.width / 2, y: clock.size.height / 2)) 193 | context.addLine(to: CGPoint(x: clock.size.width - 25, y: clock.size.height / 2 - 3)) 194 | context.strokePath() 195 | UIColor.red.setStroke() 196 | context.setLineWidth(1) 197 | context.move(to: CGPoint(x: clock.size.width / 2 + 8, y: clock.size.height / 2 - 7)) 198 | context.addLine(to: CGPoint(x: 26, y: clock.size.height / 2 + 35)) 199 | context.strokePath() 200 | UIColor.red.setFill() 201 | let rect = CGRect(x: clock.size.width / 2 - 1, y: clock.size.height / 2 - 1, width: 3, height: 3) 202 | context.fillEllipse(in: rect) 203 | } 204 | })()) 205 | ``` 206 | 207 | 208 | 209 | 210 | #### 6 211 | 212 | ```swift 213 | UIImageView(image: 214 | ({ () -> UIImage in 215 | let circle = UIImage.size(width: 8, height: 8) 216 | .color(.white) 217 | .corner(radius: 4) 218 | .image 219 | .position(CGPoint(x: 5, y: 5)) 220 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 221 | .color(gradient: [.red, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 222 | .corner(bottomRight: 20) 223 | .image + circle 224 | })()) 225 | ``` 226 | 227 | 228 | 229 | 230 | ```swift 231 | UIImageView(image: 232 | ({ () -> UIImage in 233 | let circle = UIImage.size(width: 8, height: 8) 234 | .color(.white) 235 | .corner(radius: 4) 236 | .image 237 | .position(CGPoint(x: UIScreen.main.bounds.width * 0.5 - 15, y: 5)) 238 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 239 | .color(gradient: [.white, .lightGray], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 240 | .corner(bottomLeft: 20) 241 | .image + circle 242 | })()) 243 | ``` 244 | 245 | 246 | 247 | 248 | ```swift 249 | UIImageView(image: 250 | ({ () -> UIImage in 251 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 252 | .color(gradient: [.white, UIColor.randomColor().withAlphaComponent(0.5)], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 253 | .corner(topLeft: 20) 254 | .image 255 | })()) 256 | ``` 257 | 258 | 259 | 260 | 261 | ```swift 262 | UIImageView(image: 263 | ({ () -> UIImage in 264 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 22) 265 | .color(gradient: [UIColor.randomColor(), .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 266 | .corner(topLeft: 10) 267 | .image 268 | })()) 269 | 270 | UIImageView(image: 271 | ({ () -> UIImage in 272 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 22) 273 | .color(gradient: [.lightGray, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 274 | .corner(bottomLeft: 10) 275 | .image 276 | })()) 277 | ``` 278 | 279 | 280 | 281 | 282 | #### 更多使用配置组合效果请download本项目或fork本项目查看 283 | 284 | ## Installation 285 | - 下载并拖动TGImage.swift到你的工程中 286 | 287 | - Cocoapods 288 | ``` 289 | pod 'TGImage' 290 | ``` 291 | 292 | ## Reference 293 | - http://blog.csdn.net/callzjy 294 | - https://github.com/targetcloud/baisibudejie 295 | - https://github.com/targetcloud/TGRefreshSwift 296 | - https://github.com/targetcloud/TGLabel 297 | - https://github.com/targetcloud/TGPhotoPicker 298 | 299 | 300 | 如果你觉得赞,请Star 301 | 302 | -------------------------------------------------------------------------------- /TGImage/TGImage.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6AC5392C1F0645D2007D1C37 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC5392B1F0645D2007D1C37 /* AppDelegate.swift */; }; 11 | 6AC5392E1F0645D2007D1C37 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC5392D1F0645D2007D1C37 /* ViewController.swift */; }; 12 | 6AC539311F0645D2007D1C37 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AC5392F1F0645D2007D1C37 /* Main.storyboard */; }; 13 | 6AC539331F0645D2007D1C37 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6AC539321F0645D2007D1C37 /* Assets.xcassets */; }; 14 | 6AC539361F0645D2007D1C37 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6AC539341F0645D2007D1C37 /* LaunchScreen.storyboard */; }; 15 | 6AC539411F0759CB007D1C37 /* TGImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AC539401F0759CB007D1C37 /* TGImage.swift */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 6AC539281F0645D2007D1C37 /* TGImage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TGImage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 6AC5392B1F0645D2007D1C37 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 6AC5392D1F0645D2007D1C37 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 22 | 6AC539301F0645D2007D1C37 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 23 | 6AC539321F0645D2007D1C37 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | 6AC539351F0645D2007D1C37 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 25 | 6AC539371F0645D2007D1C37 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 6AC539401F0759CB007D1C37 /* TGImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TGImage.swift; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 6AC539251F0645D2007D1C37 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 6AC5391F1F0645D2007D1C37 = { 41 | isa = PBXGroup; 42 | children = ( 43 | 6AC5392A1F0645D2007D1C37 /* TGImage */, 44 | 6AC539291F0645D2007D1C37 /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | 6AC539291F0645D2007D1C37 /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 6AC539281F0645D2007D1C37 /* TGImage.app */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 6AC5392A1F0645D2007D1C37 /* TGImage */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 6AC5393F1F0759CB007D1C37 /* TGImage */, 60 | 6AC5392B1F0645D2007D1C37 /* AppDelegate.swift */, 61 | 6AC5392D1F0645D2007D1C37 /* ViewController.swift */, 62 | 6AC5392F1F0645D2007D1C37 /* Main.storyboard */, 63 | 6AC539321F0645D2007D1C37 /* Assets.xcassets */, 64 | 6AC539341F0645D2007D1C37 /* LaunchScreen.storyboard */, 65 | 6AC539371F0645D2007D1C37 /* Info.plist */, 66 | ); 67 | path = TGImage; 68 | sourceTree = ""; 69 | }; 70 | 6AC5393F1F0759CB007D1C37 /* TGImage */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 6AC539401F0759CB007D1C37 /* TGImage.swift */, 74 | ); 75 | path = TGImage; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXNativeTarget section */ 81 | 6AC539271F0645D2007D1C37 /* TGImage */ = { 82 | isa = PBXNativeTarget; 83 | buildConfigurationList = 6AC5393A1F0645D2007D1C37 /* Build configuration list for PBXNativeTarget "TGImage" */; 84 | buildPhases = ( 85 | 6AC539241F0645D2007D1C37 /* Sources */, 86 | 6AC539251F0645D2007D1C37 /* Frameworks */, 87 | 6AC539261F0645D2007D1C37 /* Resources */, 88 | ); 89 | buildRules = ( 90 | ); 91 | dependencies = ( 92 | ); 93 | name = TGImage; 94 | productName = TGImage; 95 | productReference = 6AC539281F0645D2007D1C37 /* TGImage.app */; 96 | productType = "com.apple.product-type.application"; 97 | }; 98 | /* End PBXNativeTarget section */ 99 | 100 | /* Begin PBXProject section */ 101 | 6AC539201F0645D2007D1C37 /* Project object */ = { 102 | isa = PBXProject; 103 | attributes = { 104 | LastSwiftUpdateCheck = 0830; 105 | LastUpgradeCheck = 0830; 106 | ORGANIZATIONNAME = targetcloud; 107 | TargetAttributes = { 108 | 6AC539271F0645D2007D1C37 = { 109 | CreatedOnToolsVersion = 8.3.3; 110 | ProvisioningStyle = Automatic; 111 | }; 112 | }; 113 | }; 114 | buildConfigurationList = 6AC539231F0645D2007D1C37 /* Build configuration list for PBXProject "TGImage" */; 115 | compatibilityVersion = "Xcode 3.2"; 116 | developmentRegion = English; 117 | hasScannedForEncodings = 0; 118 | knownRegions = ( 119 | en, 120 | Base, 121 | ); 122 | mainGroup = 6AC5391F1F0645D2007D1C37; 123 | productRefGroup = 6AC539291F0645D2007D1C37 /* Products */; 124 | projectDirPath = ""; 125 | projectRoot = ""; 126 | targets = ( 127 | 6AC539271F0645D2007D1C37 /* TGImage */, 128 | ); 129 | }; 130 | /* End PBXProject section */ 131 | 132 | /* Begin PBXResourcesBuildPhase section */ 133 | 6AC539261F0645D2007D1C37 /* Resources */ = { 134 | isa = PBXResourcesBuildPhase; 135 | buildActionMask = 2147483647; 136 | files = ( 137 | 6AC539361F0645D2007D1C37 /* LaunchScreen.storyboard in Resources */, 138 | 6AC539331F0645D2007D1C37 /* Assets.xcassets in Resources */, 139 | 6AC539311F0645D2007D1C37 /* Main.storyboard in Resources */, 140 | ); 141 | runOnlyForDeploymentPostprocessing = 0; 142 | }; 143 | /* End PBXResourcesBuildPhase section */ 144 | 145 | /* Begin PBXSourcesBuildPhase section */ 146 | 6AC539241F0645D2007D1C37 /* Sources */ = { 147 | isa = PBXSourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | 6AC539411F0759CB007D1C37 /* TGImage.swift in Sources */, 151 | 6AC5392E1F0645D2007D1C37 /* ViewController.swift in Sources */, 152 | 6AC5392C1F0645D2007D1C37 /* AppDelegate.swift in Sources */, 153 | ); 154 | runOnlyForDeploymentPostprocessing = 0; 155 | }; 156 | /* End PBXSourcesBuildPhase section */ 157 | 158 | /* Begin PBXVariantGroup section */ 159 | 6AC5392F1F0645D2007D1C37 /* Main.storyboard */ = { 160 | isa = PBXVariantGroup; 161 | children = ( 162 | 6AC539301F0645D2007D1C37 /* Base */, 163 | ); 164 | name = Main.storyboard; 165 | sourceTree = ""; 166 | }; 167 | 6AC539341F0645D2007D1C37 /* LaunchScreen.storyboard */ = { 168 | isa = PBXVariantGroup; 169 | children = ( 170 | 6AC539351F0645D2007D1C37 /* Base */, 171 | ); 172 | name = LaunchScreen.storyboard; 173 | sourceTree = ""; 174 | }; 175 | /* End PBXVariantGroup section */ 176 | 177 | /* Begin XCBuildConfiguration section */ 178 | 6AC539381F0645D2007D1C37 /* Debug */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_ANALYZER_NONNULL = YES; 183 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 184 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 185 | CLANG_CXX_LIBRARY = "libc++"; 186 | CLANG_ENABLE_MODULES = YES; 187 | CLANG_ENABLE_OBJC_ARC = YES; 188 | CLANG_WARN_BOOL_CONVERSION = YES; 189 | CLANG_WARN_CONSTANT_CONVERSION = YES; 190 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 191 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 192 | CLANG_WARN_EMPTY_BODY = YES; 193 | CLANG_WARN_ENUM_CONVERSION = YES; 194 | CLANG_WARN_INFINITE_RECURSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 197 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 198 | CLANG_WARN_UNREACHABLE_CODE = YES; 199 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 200 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 201 | COPY_PHASE_STRIP = NO; 202 | DEBUG_INFORMATION_FORMAT = dwarf; 203 | ENABLE_STRICT_OBJC_MSGSEND = YES; 204 | ENABLE_TESTABILITY = YES; 205 | GCC_C_LANGUAGE_STANDARD = gnu99; 206 | GCC_DYNAMIC_NO_PIC = NO; 207 | GCC_NO_COMMON_BLOCKS = YES; 208 | GCC_OPTIMIZATION_LEVEL = 0; 209 | GCC_PREPROCESSOR_DEFINITIONS = ( 210 | "DEBUG=1", 211 | "$(inherited)", 212 | ); 213 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 214 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 215 | GCC_WARN_UNDECLARED_SELECTOR = YES; 216 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 217 | GCC_WARN_UNUSED_FUNCTION = YES; 218 | GCC_WARN_UNUSED_VARIABLE = YES; 219 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 220 | MTL_ENABLE_DEBUG_INFO = YES; 221 | ONLY_ACTIVE_ARCH = YES; 222 | SDKROOT = iphoneos; 223 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 224 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 225 | }; 226 | name = Debug; 227 | }; 228 | 6AC539391F0645D2007D1C37 /* Release */ = { 229 | isa = XCBuildConfiguration; 230 | buildSettings = { 231 | ALWAYS_SEARCH_USER_PATHS = NO; 232 | CLANG_ANALYZER_NONNULL = YES; 233 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 234 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 235 | CLANG_CXX_LIBRARY = "libc++"; 236 | CLANG_ENABLE_MODULES = YES; 237 | CLANG_ENABLE_OBJC_ARC = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_CONSTANT_CONVERSION = YES; 240 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 241 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 242 | CLANG_WARN_EMPTY_BODY = YES; 243 | CLANG_WARN_ENUM_CONVERSION = YES; 244 | CLANG_WARN_INFINITE_RECURSION = YES; 245 | CLANG_WARN_INT_CONVERSION = YES; 246 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 247 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 248 | CLANG_WARN_UNREACHABLE_CODE = YES; 249 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 250 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 251 | COPY_PHASE_STRIP = NO; 252 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 253 | ENABLE_NS_ASSERTIONS = NO; 254 | ENABLE_STRICT_OBJC_MSGSEND = YES; 255 | GCC_C_LANGUAGE_STANDARD = gnu99; 256 | GCC_NO_COMMON_BLOCKS = YES; 257 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 258 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 259 | GCC_WARN_UNDECLARED_SELECTOR = YES; 260 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 261 | GCC_WARN_UNUSED_FUNCTION = YES; 262 | GCC_WARN_UNUSED_VARIABLE = YES; 263 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 264 | MTL_ENABLE_DEBUG_INFO = NO; 265 | SDKROOT = iphoneos; 266 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 267 | VALIDATE_PRODUCT = YES; 268 | }; 269 | name = Release; 270 | }; 271 | 6AC5393B1F0645D2007D1C37 /* Debug */ = { 272 | isa = XCBuildConfiguration; 273 | buildSettings = { 274 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 275 | INFOPLIST_FILE = TGImage/Info.plist; 276 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 277 | PRODUCT_BUNDLE_IDENTIFIER = net.targetcloud.TGImage; 278 | PRODUCT_NAME = "$(TARGET_NAME)"; 279 | SWIFT_VERSION = 3.0; 280 | }; 281 | name = Debug; 282 | }; 283 | 6AC5393C1F0645D2007D1C37 /* Release */ = { 284 | isa = XCBuildConfiguration; 285 | buildSettings = { 286 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 287 | INFOPLIST_FILE = TGImage/Info.plist; 288 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 289 | PRODUCT_BUNDLE_IDENTIFIER = net.targetcloud.TGImage; 290 | PRODUCT_NAME = "$(TARGET_NAME)"; 291 | SWIFT_VERSION = 3.0; 292 | }; 293 | name = Release; 294 | }; 295 | /* End XCBuildConfiguration section */ 296 | 297 | /* Begin XCConfigurationList section */ 298 | 6AC539231F0645D2007D1C37 /* Build configuration list for PBXProject "TGImage" */ = { 299 | isa = XCConfigurationList; 300 | buildConfigurations = ( 301 | 6AC539381F0645D2007D1C37 /* Debug */, 302 | 6AC539391F0645D2007D1C37 /* Release */, 303 | ); 304 | defaultConfigurationIsVisible = 0; 305 | defaultConfigurationName = Release; 306 | }; 307 | 6AC5393A1F0645D2007D1C37 /* Build configuration list for PBXNativeTarget "TGImage" */ = { 308 | isa = XCConfigurationList; 309 | buildConfigurations = ( 310 | 6AC5393B1F0645D2007D1C37 /* Debug */, 311 | 6AC5393C1F0645D2007D1C37 /* Release */, 312 | ); 313 | defaultConfigurationIsVisible = 0; 314 | }; 315 | /* End XCConfigurationList section */ 316 | }; 317 | rootObject = 6AC539201F0645D2007D1C37 /* Project object */; 318 | } 319 | -------------------------------------------------------------------------------- /TGImage/TGImage/TGImage/TGImage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TGImage.swift 3 | // TGImage 4 | // 5 | // Created by targetcloud on 2017/6/30. 6 | // Copyright © 2017年 targetcloud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public enum BorderAlignment { 12 | case inside 13 | case center 14 | case outside 15 | } 16 | 17 | public extension UIImage { 18 | public typealias ContextBlock = (CGContext) -> Void 19 | 20 | public class func with(width: CGFloat, height: CGFloat, block: ContextBlock) -> UIImage { 21 | return self.with(size: CGSize(width: width, height: height), block: block) 22 | } 23 | 24 | public class func with(size: CGSize, opaque: Bool = false, scale: CGFloat = 0, block: ContextBlock) -> UIImage { 25 | UIGraphicsBeginImageContextWithOptions(size, opaque, scale) 26 | let context = UIGraphicsGetCurrentContext()! 27 | block(context) 28 | let image = UIGraphicsGetImageFromCurrentImageContext() 29 | UIGraphicsEndImageContext() 30 | return image ?? UIImage() 31 | } 32 | 33 | public func with(size: CGSize, opaque: Bool = false, scale: CGFloat = 0, block: ContextBlock) -> UIImage { 34 | return self + UIImage.with(size:size,opaque:opaque,scale:scale,block:block) 35 | } 36 | 37 | public func with(_ block: ContextBlock) -> UIImage { 38 | return UIImage.with(size: self.size, opaque: false, scale: self.scale) { context in 39 | let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) 40 | self.draw(in: rect) 41 | block(context) 42 | } 43 | } 44 | 45 | public func with(color: UIColor) -> UIImage { 46 | return UIImage.with(size: self.size) { context in 47 | context.translateBy(x: 0, y: self.size.height) 48 | context.scaleBy(x: 1, y: -1) 49 | context.setBlendMode(.normal) 50 | let rect = CGRect(origin: .zero, size: self.size) 51 | context.clip(to: rect, mask: self.cgImage!) 52 | color.setFill() 53 | context.fill(rect) 54 | } 55 | } 56 | 57 | public class func size(width: CGFloat, height: CGFloat) -> TGImagePresenter { 58 | return self.size(CGSize(width: width, height: height)) 59 | } 60 | 61 | public class func size(_ size: CGSize) -> TGImagePresenter { 62 | let drawer = TGImagePresenter() 63 | drawer.size = .fixed(size) 64 | return drawer 65 | } 66 | 67 | public class func resizable() -> TGImagePresenter { 68 | let drawer = TGImagePresenter() 69 | drawer.size = .resizable 70 | return drawer 71 | } 72 | 73 | private struct AssociatedKeys { 74 | static var TGImagePositionKey = "TGImagePositionKey" 75 | } 76 | 77 | public var position: CGPoint{ 78 | get { 79 | return objc_getAssociatedObject(self, &AssociatedKeys.TGImagePositionKey) as? CGPoint ?? CGPoint.zero 80 | } 81 | set(newValue) { 82 | if self.position != newValue{ 83 | self.willChangeValue(forKey: "position") 84 | objc_setAssociatedObject(self, &AssociatedKeys.TGImagePositionKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 85 | self.didChangeValue(forKey: "position") 86 | } 87 | } 88 | } 89 | 90 | public func position(_ point:CGPoint) -> UIImage{ 91 | self.position = point 92 | return self 93 | } 94 | } 95 | 96 | extension UIColor{ 97 | public class func randomColor() -> UIColor{ 98 | return UIColor(red: CGFloat(arc4random_uniform(255))/255.0, green: CGFloat(arc4random_uniform(255))/255.0, blue: CGFloat(arc4random_uniform(255))/255.0, alpha: 1.0) 99 | } 100 | } 101 | 102 | public func + (leftImage: UIImage, rigthImage: UIImage) -> UIImage { 103 | return leftImage.with { context in 104 | 105 | let leftRect = CGRect(x: 0, y: 0, width: leftImage.size.width, height: leftImage.size.height) 106 | var rightRect = CGRect(x: 0, y: 0, width: rigthImage.size.width, height: rigthImage.size.height) 107 | 108 | if rigthImage.position.x != 0 || rigthImage.position.y != 0{ 109 | rightRect.origin.x = rigthImage.position.x 110 | rightRect.origin.y = rigthImage.position.y 111 | }else if leftRect.contains(rightRect) { 112 | rightRect.origin.x = (leftRect.size.width - rightRect.size.width) / 2 113 | rightRect.origin.y = (leftRect.size.height - rightRect.size.height) / 2 114 | } else { 115 | rightRect.size = leftRect.size 116 | } 117 | 118 | //print("\(String(describing: rigthImage.position.x )) \(String(describing: rigthImage.position.y ))") 119 | rigthImage.draw(in: rightRect) 120 | } 121 | } 122 | 123 | public func += (leftImage:inout UIImage, rigthImage: UIImage) { 124 | leftImage = leftImage + rigthImage 125 | } 126 | 127 | open class TGImagePresenter{ 128 | public enum Size { 129 | case fixed(CGSize) 130 | case resizable 131 | } 132 | 133 | fileprivate static let defaultGradientLocations: [CGFloat] = [0, 1] 134 | fileprivate static let defaultGradientFrom: CGPoint = .zero 135 | fileprivate static let defaultGradientTo: CGPoint = CGPoint(x: 0, y: 1) 136 | 137 | fileprivate var colors: [UIColor] = [.clear] 138 | fileprivate var colorLocations: [CGFloat] = defaultGradientLocations 139 | fileprivate var colorStartPoint: CGPoint = defaultGradientFrom 140 | fileprivate var colorEndPoint: CGPoint = defaultGradientTo 141 | fileprivate var borderColors: [UIColor] = [.black] 142 | fileprivate var borderColorLocations: [CGFloat] = defaultGradientLocations 143 | fileprivate var borderColorStartPoint: CGPoint = defaultGradientFrom 144 | fileprivate var borderColorEndPoint: CGPoint = defaultGradientTo 145 | fileprivate var borderWidth: CGFloat = 0 146 | fileprivate var borderAlignment: BorderAlignment = .inside 147 | fileprivate var cornerRadiusTopLeft: CGFloat = 0 148 | fileprivate var cornerRadiusTopRight: CGFloat = 0 149 | fileprivate var cornerRadiusBottomLeft: CGFloat = 0 150 | fileprivate var cornerRadiusBottomRight: CGFloat = 0 151 | 152 | fileprivate var size: Size = .resizable 153 | 154 | private static var cachedImages = [String: UIImage]() 155 | 156 | private var cacheKey: String { 157 | var attributes = [String: String]() 158 | attributes["colors"] = String(self.colors.description.hashValue) 159 | attributes["colorLocations"] = String(self.colorLocations.description.hashValue) 160 | attributes["colorStartPoint"] = String(String(describing: self.colorStartPoint).hashValue) 161 | attributes["colorEndPoint"] = String(String(describing: self.colorEndPoint).hashValue) 162 | attributes["borderColors"] = String(self.borderColors.description.hashValue) 163 | attributes["borderColorLocations"] = String(self.borderColorLocations.description.hashValue) 164 | attributes["borderColorStartPoint"] = String(String(describing: self.borderColorStartPoint).hashValue) 165 | attributes["borderColorEndPoint"] = String(String(describing: self.borderColorEndPoint).hashValue) 166 | attributes["borderWidth"] = String(self.borderWidth.hashValue) 167 | attributes["borderAlignment"] = String(self.borderAlignment.hashValue) 168 | attributes["cornerRadiusTopLeft"] = String(self.cornerRadiusTopLeft.hashValue) 169 | attributes["cornerRadiusTopRight"] = String(self.cornerRadiusTopRight.hashValue) 170 | attributes["cornerRadiusBottomLeft"] = String(self.cornerRadiusBottomLeft.hashValue) 171 | attributes["cornerRadiusBottomRight"] = String(self.cornerRadiusBottomRight.hashValue) 172 | 173 | switch self.size { 174 | case .fixed(let size): 175 | attributes["size"] = "Fixed(\(size.width), \(size.height))" 176 | case .resizable: 177 | attributes["size"] = "Resizable" 178 | } 179 | 180 | var serializedAttributes = [String]() 181 | for key in attributes.keys.sorted() { 182 | if let value = attributes[key] { 183 | serializedAttributes.append("\(key):\(value)") 184 | } 185 | } 186 | 187 | let cacheKey = serializedAttributes.joined(separator: "|") 188 | return cacheKey 189 | } 190 | 191 | open func color(_ color: UIColor) -> Self { 192 | self.colors = [color] 193 | return self 194 | } 195 | 196 | open func color(gradient: [UIColor],locations: [CGFloat] = defaultGradientLocations,from startPoint: CGPoint = defaultGradientFrom,to endPoint: CGPoint = defaultGradientTo) -> Self { 197 | self.colors = gradient 198 | self.colorLocations = locations 199 | self.colorStartPoint = startPoint 200 | self.colorEndPoint = endPoint 201 | return self 202 | } 203 | 204 | open func border(color: UIColor) -> Self { 205 | self.borderColors = [color] 206 | return self 207 | } 208 | 209 | open func border(gradient: [UIColor],locations: [CGFloat] = defaultGradientLocations,from startPoint: CGPoint = defaultGradientFrom,to endPoint: CGPoint = defaultGradientTo 210 | ) -> Self { 211 | self.borderColors = gradient 212 | self.borderColorLocations = locations 213 | self.borderColorStartPoint = startPoint 214 | self.borderColorEndPoint = endPoint 215 | return self 216 | } 217 | 218 | open func border(width: CGFloat) -> Self { 219 | self.borderWidth = width 220 | return self 221 | } 222 | 223 | open func border(alignment: BorderAlignment) -> Self { 224 | self.borderAlignment = alignment 225 | return self 226 | } 227 | 228 | open func corner(radius: CGFloat) -> Self { 229 | return self.corner(topLeft: radius, topRight: radius, bottomLeft: radius, bottomRight: radius) 230 | } 231 | 232 | open func corner(topLeft: CGFloat) -> Self { 233 | self.cornerRadiusTopLeft = topLeft 234 | return self 235 | } 236 | 237 | open func corner(topRight: CGFloat) -> Self { 238 | self.cornerRadiusTopRight = topRight 239 | return self 240 | } 241 | 242 | open func corner(bottomLeft: CGFloat) -> Self { 243 | self.cornerRadiusBottomLeft = bottomLeft 244 | return self 245 | } 246 | 247 | open func corner(bottomRight: CGFloat) -> Self { 248 | self.cornerRadiusBottomRight = bottomRight 249 | return self 250 | } 251 | 252 | open func corner(topLeft: CGFloat, topRight: CGFloat, bottomLeft: CGFloat, bottomRight: CGFloat) -> Self { 253 | return self.corner(topLeft: topLeft).corner(topRight: topRight).corner(bottomLeft: bottomLeft).corner(bottomRight: bottomRight) 254 | } 255 | 256 | open var image: UIImage { 257 | switch self.size { 258 | case .fixed(let size): 259 | return self.imageWithSize(size) 260 | case .resizable: 261 | self.borderAlignment = .inside 262 | let cornerRadius = max(self.cornerRadiusTopLeft, self.cornerRadiusTopRight,self.cornerRadiusBottomLeft, self.cornerRadiusBottomRight) 263 | let capSize = ceil(max(cornerRadius, self.borderWidth)) 264 | let imageSize = capSize * 2 + 1 265 | let image = self.imageWithSize(CGSize(width: imageSize, height: imageSize)) 266 | let capInsets = UIEdgeInsets(top: capSize, left: capSize, bottom: capSize, right: capSize) 267 | return image.resizableImage(withCapInsets: capInsets) 268 | } 269 | } 270 | 271 | private func imageWithSize(_ size: CGSize, useCache: Bool = true) -> UIImage { 272 | if let cachedImage = type(of: self).cachedImages[self.cacheKey], useCache { 273 | return cachedImage 274 | } 275 | 276 | var imageSize = CGSize(width: size.width, height: size.height) 277 | var rect = CGRect() 278 | rect.size = imageSize 279 | 280 | switch self.borderAlignment { 281 | case .inside: 282 | rect.origin.x += self.borderWidth / 2 283 | rect.origin.y += self.borderWidth / 2 284 | rect.size.width -= self.borderWidth 285 | rect.size.height -= self.borderWidth 286 | case .center: 287 | rect.origin.x += self.borderWidth / 2 288 | rect.origin.y += self.borderWidth / 2 289 | imageSize.width += self.borderWidth 290 | imageSize.height += self.borderWidth 291 | case .outside: 292 | rect.origin.x += self.borderWidth / 2 293 | rect.origin.y += self.borderWidth / 2 294 | rect.size.width += self.borderWidth 295 | rect.size.height += self.borderWidth 296 | imageSize.width += self.borderWidth * 2 297 | imageSize.height += self.borderWidth * 2 298 | } 299 | 300 | let cornerRadius = max(self.cornerRadiusTopLeft, self.cornerRadiusTopRight,self.cornerRadiusBottomLeft, self.cornerRadiusBottomRight) 301 | 302 | let image = UIImage.with(size: imageSize) { context in 303 | let path: UIBezierPath 304 | if self.cornerRadiusTopLeft == self.cornerRadiusTopRight && self.cornerRadiusTopLeft == self.cornerRadiusBottomLeft && self.cornerRadiusTopLeft == self.cornerRadiusBottomRight && self.cornerRadiusTopLeft > 0 { 305 | path = UIBezierPath(roundedRect: rect, cornerRadius: self.cornerRadiusTopLeft) 306 | } else if cornerRadius > 0 { 307 | let startAngle = CGFloat.pi 308 | let topLeftCenter = CGPoint(x: self.cornerRadiusTopLeft + self.borderWidth / 2,y: self.cornerRadiusTopLeft + self.borderWidth / 2) 309 | let topRightCenter = CGPoint(x: imageSize.width - self.cornerRadiusTopRight - self.borderWidth / 2,y: self.cornerRadiusTopRight + self.borderWidth / 2) 310 | let bottomRightCenter = CGPoint(x: imageSize.width - self.cornerRadiusBottomRight - self.borderWidth / 2,y: imageSize.height - self.cornerRadiusBottomRight - self.borderWidth / 2) 311 | let bottomLeftCenter = CGPoint(x: self.cornerRadiusBottomLeft + self.borderWidth / 2,y: imageSize.height - self.cornerRadiusBottomLeft - self.borderWidth / 2) 312 | let mutablePath = UIBezierPath() 313 | self.cornerRadiusTopLeft > 0 ? mutablePath.addArc(withCenter: topLeftCenter,radius: self.cornerRadiusTopLeft,startAngle: startAngle,endAngle: 1.5 * startAngle,clockwise: true) : mutablePath.move(to: topLeftCenter) 314 | self.cornerRadiusTopRight > 0 ? mutablePath.addArc(withCenter: topRightCenter,radius: self.cornerRadiusTopRight,startAngle: 1.5 * startAngle,endAngle: 2 * startAngle,clockwise: true) : mutablePath.addLine(to: topRightCenter) 315 | self.cornerRadiusBottomRight > 0 ? mutablePath.addArc(withCenter: bottomRightCenter,radius: self.cornerRadiusBottomRight,startAngle: 2 * startAngle,endAngle: 2.5 * startAngle,clockwise: true) : mutablePath.addLine(to: bottomRightCenter) 316 | self.cornerRadiusBottomLeft > 0 ? mutablePath.addArc(withCenter: bottomLeftCenter,radius: self.cornerRadiusBottomLeft,startAngle: 2.5 * startAngle,endAngle: 3 * startAngle,clockwise: true) : mutablePath.addLine(to: bottomLeftCenter) 317 | self.cornerRadiusTopLeft > 0 ? mutablePath.addLine(to: CGPoint(x: self.borderWidth / 2, y: topLeftCenter.y)) : mutablePath.addLine(to: topLeftCenter) 318 | path = mutablePath 319 | } 320 | else { 321 | path = UIBezierPath(rect: rect) 322 | } 323 | 324 | context.saveGState() 325 | if self.colors.count <= 1 { 326 | self.colors.first?.setFill() 327 | path.fill() 328 | } else { 329 | let colorSpace = CGColorSpaceCreateDeviceRGB() 330 | let colors = self.colors.map { $0.cgColor } as CFArray 331 | if let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: self.colorLocations) { 332 | let startPoint = CGPoint(x: self.colorStartPoint.x * imageSize.width,y: self.colorStartPoint.y * imageSize.height) 333 | let endPoint = CGPoint(x: self.colorEndPoint.x * imageSize.width,y: self.colorEndPoint.y * imageSize.height) 334 | context.addPath(path.cgPath) 335 | context.clip() 336 | context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: []) 337 | } 338 | } 339 | context.restoreGState() 340 | 341 | context.saveGState() 342 | if self.borderColors.count <= 1 { 343 | self.borderColors.first?.setStroke() 344 | path.lineWidth = self.borderWidth 345 | path.stroke() 346 | } else { 347 | let colorSpace = CGColorSpaceCreateDeviceRGB() 348 | let colors = self.borderColors.map { $0.cgColor } as CFArray 349 | if let gradient = CGGradient(colorsSpace: colorSpace, colors: colors, locations: self.borderColorLocations) { 350 | let startPoint = CGPoint(x: self.borderColorStartPoint.x * imageSize.width,y: self.borderColorStartPoint.y * imageSize.height) 351 | let endPoint = CGPoint(x: self.borderColorEndPoint.x * imageSize.width,y: self.borderColorEndPoint.y * imageSize.height) 352 | context.addPath(path.cgPath) 353 | context.setLineWidth(self.borderWidth) 354 | context.replacePathWithStrokedPath() 355 | context.clip() 356 | context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: []) 357 | } 358 | } 359 | context.restoreGState() 360 | } 361 | 362 | if useCache { 363 | type(of: self).cachedImages[self.cacheKey] = image 364 | } 365 | return image 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /TGImage/TGImage/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // TGImage 4 | // 5 | // Created by targetcloud on 2017/6/30. 6 | // Copyright © 2017年 targetcloud. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | let iv : UIImageView = UIImageView(image: UIImage.size(width: UIScreen.main.bounds.width, height: 20) 17 | .color(gradient: [.lightGray, .white], locations: [0, 1], from: CGPoint(x: 0, y: 1), to: CGPoint(x: 0, y: 0)) 18 | .border(color: .gray) 19 | .border(width: 1) 20 | .corner(radius: 5) 21 | .image) 22 | iv.frame.origin = CGPoint(x: 0, y: 20) 23 | self.view.addSubview(iv) 24 | 25 | let iv2 : UIImageView = UIImageView(image: UIImage.size(width: UIScreen.main.bounds.width, height: 34) 26 | .color(.orange) 27 | .corner(bottomLeft: 10) 28 | .corner(bottomRight: 10) 29 | .image) 30 | iv2.frame.origin = CGPoint(x: 0, y: iv.frame.maxY+5) 31 | self.view.addSubview(iv2) 32 | 33 | let iv3 : UIImageView = UIImageView(image: UIImage.size(width: 100, height: 70) 34 | .color(gradient: [UIColor.randomColor(), .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 0)) 35 | .border(color: .darkGray) 36 | .border(width: 5) 37 | .border(alignment: .outside) 38 | .corner(topLeft: 1) 39 | .corner(bottomLeft: 20) 40 | .corner(topRight: 20) 41 | .corner(bottomRight: 30) 42 | .image) 43 | iv3.frame.origin = CGPoint(x: 0, y: iv2.frame.maxY+5) 44 | self.view.addSubview(iv3) 45 | 46 | let iv4 = UIImageView(image: UIImage.size(width: 100, height: 100) 47 | .color(gradient: [.green, .blue], locations: [0, 1], from: CGPoint(x: 0, y: 1), to: CGPoint(x: 0, y: 0)) 48 | .border(gradient: [.red, .yellow], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 0)) 49 | .border(width: 5) 50 | .border(alignment: .outside) 51 | .corner(topLeft: 20) 52 | .corner(topRight: 50) 53 | .corner(bottomLeft: 50) 54 | .corner(bottomRight: 20) 55 | .image) 56 | iv4.frame.origin = CGPoint(x: 0, y: iv3.frame.maxY+5) 57 | self.view.addSubview(iv4) 58 | 59 | //let iv5 = UIImageView(image: UIImage(named: "2")!.with( { context in//左上 60 | let iv5 = UIImageView(image: UIImage(named: "2")!.with(size: CGSize(width: 50, height: 20)) { context in//(50 20)在2图的中央 61 | UIColor.red.setFill() 62 | context.fillEllipse(in: CGRect(x: 0, y: 0, width: 20, height: 20))//(20 20)根据情况确定在左上还是在中央的(50 20)限制区域 63 | }) 64 | //)//左上 65 | iv5.frame.origin = CGPoint(x: 0, y: iv4.frame.maxY) 66 | self.view.addSubview(iv5) 67 | 68 | let iv6 = UIImageView(image: ({ () -> UIImage in 69 | let background = UIImage.size(width: 120, height: 120) 70 | .color(gradient: [.black, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 0, y: 1)) 71 | .corner(radius: 13.5) 72 | .image 73 | let circle = UIImage.size(width: 106, height: 106) 74 | .color(.white) 75 | .corner(radius: 50) 76 | .image 77 | let center = UIImage.size(width: 8, height: 8) 78 | .color(.black) 79 | .corner(radius: 3) 80 | .image 81 | let clock = background + circle + center 82 | return clock.with { context in 83 | context.setLineCap(.round) 84 | UIColor.black.setStroke() 85 | context.setLineWidth(2) 86 | context.move(to: CGPoint(x: clock.size.width / 2, y: clock.size.height / 2)) 87 | context.addLine(to: CGPoint(x: clock.size.width / 2 - 5, y: 15)) 88 | context.move(to: CGPoint(x: clock.size.width / 2, y: clock.size.height / 2)) 89 | context.addLine(to: CGPoint(x: clock.size.width - 25, y: clock.size.height / 2 - 3)) 90 | context.strokePath() 91 | UIColor.red.setStroke() 92 | context.setLineWidth(1) 93 | context.move(to: CGPoint(x: clock.size.width / 2 + 8, y: clock.size.height / 2 - 7)) 94 | context.addLine(to: CGPoint(x: 26, y: clock.size.height / 2 + 35)) 95 | context.strokePath() 96 | UIColor.red.setFill() 97 | let rect = CGRect(x: clock.size.width / 2 - 1, y: clock.size.height / 2 - 1, width: 3, height: 3) 98 | context.fillEllipse(in: rect) 99 | } 100 | })()) 101 | iv6.frame.origin.y = iv5.frame.maxY 102 | self.view.addSubview(iv6) 103 | 104 | self.view.addSubview(({ () -> UIButton in 105 | let button = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 44)) 106 | button.setBackgroundImage( 107 | UIImage.resizable() 108 | .color(.lightGray) 109 | .border(gradient: [.red, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 110 | .border(width: 2) 111 | .border(alignment: .outside) 112 | .corner(radius: 8) 113 | .image, 114 | for: .normal 115 | ) 116 | button.frame.origin.y = iv6.frame.maxY+5 117 | return button 118 | })()) 119 | 120 | let topLeftCorner = UIImageView(image: 121 | ({ () -> UIImage in 122 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 22) 123 | .color(gradient: [UIColor.randomColor(), .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 124 | .corner(topLeft: 10) 125 | .image 126 | })()) 127 | topLeftCorner.frame.origin.y = self.view.bounds.height - 44 128 | self.view.addSubview(topLeftCorner) 129 | 130 | let bottomLeftCorner = UIImageView(image: 131 | ({ () -> UIImage in 132 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 22) 133 | .color(gradient: [.lightGray, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 134 | .corner(bottomLeft: 10) 135 | .image 136 | })()) 137 | bottomLeftCorner.frame.origin.y = self.view.bounds.height - 22 138 | self.view.addSubview(bottomLeftCorner) 139 | 140 | let iv7 = UIImageView(image: ({ () -> UIImage in 141 | let img = UIImage.size(width: 180, height: 50) 142 | .color(.black) 143 | .corner(radius: 5) 144 | .image 145 | let background = UIImage.size(width: 160, height: 40) 146 | .color(.white) 147 | .corner(radius: 5) 148 | .image 149 | let circle = UIImage.size(width: 8, height: 8) 150 | .color(.white) 151 | .corner(radius: 4) 152 | .image 153 | //.with(color: .red) 154 | .position(CGPoint(x: 2, y: 10)) 155 | 156 | return img + background + circle 157 | })()) 158 | iv7.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv2.frame.maxY+5) 159 | self.view.addSubview(iv7) 160 | 161 | let iv8 = UIImageView(image: 162 | ({ () -> UIImage in 163 | let circle = UIImage.size(width: 8, height: 8) 164 | .color(.white) 165 | .corner(radius: 4) 166 | .image 167 | .position(CGPoint(x: 5, y: 5)) 168 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 169 | .color(gradient: [.red, .white], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 170 | .corner(bottomRight: 20) 171 | .image + circle 172 | })()) 173 | iv8.frame.origin.x = iv7.frame.origin.x 174 | iv8.frame.origin.y = iv7.frame.maxY + 5 175 | self.view.addSubview(iv8) 176 | 177 | let iv9 = UIImageView(image: 178 | ({ () -> UIImage in 179 | let circle = UIImage.size(width: 8, height: 8) 180 | .color(.white) 181 | .corner(radius: 4) 182 | .image 183 | .position(CGPoint(x: UIScreen.main.bounds.width * 0.5 - 15, y: 5)) 184 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 185 | .color(gradient: [.white, .lightGray], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 186 | .corner(bottomLeft: 20) 187 | .image + circle 188 | })()) 189 | iv9.frame.origin.x = iv8.frame.origin.x 190 | iv9.frame.origin.y = iv8.frame.maxY + 5 191 | self.view.addSubview(iv9) 192 | 193 | let iv10 = UIImageView(image: ({ () -> UIImage in 194 | let img = UIImage.size(width: 180, height: 70) 195 | .color(.red) 196 | .corner(radius: 15) 197 | .image 198 | let circle = UIImage.size(width: 18, height: 18) 199 | .color(.white) 200 | .corner(radius: 9) 201 | .image 202 | .position(CGPoint(x: 10, y: 10)) 203 | return img + circle 204 | })()) 205 | iv10.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv9.frame.maxY+5) 206 | self.view.addSubview(iv10) 207 | 208 | //方yes 209 | let iv11 = UIImageView(image: 210 | UIImage.size(width: 27, height: 27) 211 | .border(color: .black) 212 | .border(width: 2) 213 | .corner(radius: 2) 214 | .color(.lightGray) 215 | .image 216 | .with({ context in 217 | context.setLineCap(.round) 218 | UIColor.white.setStroke() 219 | context.setLineWidth(2) 220 | context.move(to: CGPoint(x: 6, y: 12)) 221 | context.addLine(to: CGPoint(x: 9, y: 18)) 222 | context.move(to: CGPoint(x: 9, y: 18)) 223 | context.addLine(to: CGPoint(x: 21, y: 9)) 224 | context.strokePath() 225 | }) 226 | ) 227 | iv11.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv10.frame.maxY+5) 228 | self.view.addSubview(iv11) 229 | 230 | //yes 231 | let iv112 = UIImageView(image: 232 | UIImage.size(width: 27, height: 27) 233 | .corner(radius: 13.5) 234 | .color(.green) 235 | .image 236 | .with({ context in 237 | context.setLineCap(.round) 238 | UIColor.white.setStroke() 239 | context.setLineWidth(2) 240 | context.move(to: CGPoint(x: 6, y: 12)) 241 | context.addLine(to: CGPoint(x: 9, y: 18)) 242 | context.move(to: CGPoint(x: 9, y: 18)) 243 | context.addLine(to: CGPoint(x: 21, y: 9)) 244 | context.strokePath() 245 | }) 246 | ) 247 | iv112.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 30, y: iv10.frame.maxY+5) 248 | self.view.addSubview(iv112) 249 | 250 | //yes 251 | let iv113 = UIImageView(image: 252 | UIImage.size(width: 27, height: 27) 253 | .corner(radius: 13.5) 254 | .color(.lightGray) 255 | .image 256 | .with({ context in 257 | context.setLineCap(.round) 258 | UIColor.white.setStroke() 259 | context.setLineWidth(2) 260 | context.move(to: CGPoint(x: 6, y: 12)) 261 | context.addLine(to: CGPoint(x: 9, y: 18)) 262 | context.move(to: CGPoint(x: 9, y: 18)) 263 | context.addLine(to: CGPoint(x: 21, y: 9)) 264 | context.strokePath() 265 | }) 266 | ) 267 | iv113.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 60, y: iv10.frame.maxY+5) 268 | self.view.addSubview(iv113) 269 | 270 | //yes 271 | let iv114 = UIImageView(image: 272 | UIImage.size(width: 27, height: 27) 273 | .corner(radius: 13.5) 274 | .color(.white) 275 | .border(color: .lightGray) 276 | .border(width: 2) 277 | .image 278 | .with({ context in 279 | context.setLineCap(.round) 280 | UIColor.lightGray.setStroke() 281 | context.setLineWidth(2) 282 | context.move(to: CGPoint(x: 6, y: 12)) 283 | context.addLine(to: CGPoint(x: 9, y: 18)) 284 | context.move(to: CGPoint(x: 9, y: 18)) 285 | context.addLine(to: CGPoint(x: 21, y: 9)) 286 | context.strokePath() 287 | }) 288 | ) 289 | iv114.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 90, y: iv10.frame.maxY+5) 290 | self.view.addSubview(iv114) 291 | 292 | //数字 293 | let iv115 = UIImageView(image:({ () -> UIImage in 294 | let M = 30 * 0.111111 295 | return UIImage.size(width: 30, height: 30) 296 | .corner(radius: 15) 297 | .color(.green) 298 | .image 299 | .with({ context in 300 | let str:NSString = "5" 301 | str.draw(in: CGRect(x: M * (5>9 ? 2 : 2.5), y: M, width: 20, height: 20), withAttributes:[NSFontAttributeName:UIFont.boldSystemFont(ofSize: 20),NSForegroundColorAttributeName: UIColor.white]) 302 | }) 303 | })()) 304 | iv115.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 120, y: iv10.frame.maxY+5) 305 | self.view.addSubview(iv115) 306 | 307 | //返回 308 | let iv116 = UIImageView(image: 309 | UIImage.size(width: 30, height: 30) 310 | .corner(radius: 15) 311 | .color(.clear) 312 | // .border(color: .white) 313 | // .border(width: 1) 314 | .image 315 | .with({ context in 316 | context.setLineCap(.round) 317 | UIColor.white.setStroke() 318 | context.setLineWidth(2) 319 | context.move(to: CGPoint(x: 17, y: 7)) 320 | context.addLine(to: CGPoint(x: 10, y: 15)) 321 | context.move(to: CGPoint(x: 10, y: 15)) 322 | context.addLine(to: CGPoint(x: 17, y: 23)) 323 | context.strokePath() 324 | }) 325 | ) 326 | iv116.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 155, y: iv10.frame.maxY+5) 327 | self.view.addSubview(iv116) 328 | 329 | //删除 330 | let iv117 = UIImageView(image: 331 | UIImage.size(width: 20, height: 20) 332 | .color(.clear) 333 | .image 334 | .with({ context in 335 | context.setLineCap(.round) 336 | UIColor.white.setStroke() 337 | context.setLineWidth(1.5) 338 | context.move(to: CGPoint(x: 8, y: 4)) 339 | context.addLine(to: CGPoint(x: 12, y: 4)) 340 | context.move(to: CGPoint(x: 4, y: 5)) 341 | context.addLine(to: CGPoint(x: 16, y: 5)) 342 | context.move(to: CGPoint(x: 5, y: 16)) 343 | context.addLine(to: CGPoint(x: 15, y: 16)) 344 | 345 | context.move(to: CGPoint(x: 5, y: 6)) 346 | context.addLine(to: CGPoint(x: 5, y: 16)) 347 | 348 | context.move(to: CGPoint(x: 8, y: 7)) 349 | context.addLine(to: CGPoint(x: 8, y: 13)) 350 | 351 | context.move(to: CGPoint(x: 12, y: 7)) 352 | context.addLine(to: CGPoint(x: 12, y: 13)) 353 | 354 | context.move(to: CGPoint(x: 15, y: 6)) 355 | context.addLine(to: CGPoint(x: 15, y: 16)) 356 | context.strokePath() 357 | }) 358 | ) 359 | iv117.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 - 22 , y: iv10.frame.maxY+5) 360 | self.view.addSubview(iv117) 361 | 362 | //对 363 | let iv12 = UIImageView(image: ({ () -> UIImage in 364 | let M = 48 * 0.111111 365 | return UIImage.size(width: 48, height: 48) 366 | .color(gradient: [UIColor.green, UIColor.green.withAlphaComponent(0.1)], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 367 | .corner(radius: 24) 368 | .image 369 | .with({ context in 370 | context.setLineCap(.round) 371 | UIColor.white.setStroke() 372 | context.setLineWidth(2) 373 | context.move(to: CGPoint(x: M * 2, y: M * 4)) 374 | context.addLine(to: CGPoint(x: M * 3, y: M * 6)) 375 | context.move(to: CGPoint(x: M * 3, y: M * 6)) 376 | context.addLine(to: CGPoint(x: M * 7, y: M * 3)) 377 | context.strokePath() 378 | }) 379 | })()) 380 | iv12.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv11.frame.maxY+5) 381 | self.view.addSubview(iv12) 382 | 383 | //错 384 | let iv122 = UIImageView(image: ({ () -> UIImage in 385 | let M = 48 * 0.111111 386 | return UIImage.size(width: 48, height: 48) 387 | .color(gradient: [UIColor.red, UIColor.red.withAlphaComponent(0.1)], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 388 | .corner(radius: 24) 389 | .image 390 | .with({ context in 391 | context.setLineCap(.round) 392 | UIColor.white.setStroke() 393 | context.setLineWidth(2) 394 | context.move(to: CGPoint(x: M * 3, y: M * 3)) 395 | context.addLine(to: CGPoint(x: M * 6, y: M * 6)) 396 | context.move(to: CGPoint(x: M * 6, y: M * 3)) 397 | context.addLine(to: CGPoint(x: M * 3, y: M * 6)) 398 | context.strokePath() 399 | }) 400 | })()) 401 | iv122.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 50, y: iv11.frame.maxY+5) 402 | self.view.addSubview(iv122) 403 | 404 | //照相 405 | let iv123 = UIImageView(image: 406 | UIImage.size(width: 48, height: 48).border(width: 3).border(color: .white).color(UIColor(white: 0.9, alpha: 1)).corner(radius: 24).image + 407 | UIImage.size(width: 40, height: 40).color(UIColor(white: 0.95, alpha: 1) ).corner(radius: 20).image 408 | ) 409 | iv123.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5 + 100, y: iv11.frame.maxY+5) 410 | self.view.addSubview(iv123) 411 | 412 | let iv13 = UIImageView(image: ({ () -> UIImage in 413 | var container = UIImage.size(width: 180, height: 20) 414 | .color(.clear) 415 | .image 416 | for i in 0..<7{ 417 | let doti = UIImage.size(width: 20, height: 20) 418 | .color(gradient: [UIColor.randomColor(), UIColor.randomColor()], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 419 | .corner(radius: 10) 420 | .image 421 | .position(CGPoint(x: i * 20 + (i + 1) * 3, y: 0)) 422 | container = container + doti 423 | } 424 | return container 425 | })()) 426 | iv13.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv12.frame.maxY+5) 427 | self.view.addSubview(iv13) 428 | 429 | let iv14 = UIImageView(image: ({ () -> UIImage in 430 | var container = UIImage.size(width: 30, height: 120) 431 | .color(.clear) 432 | .image 433 | for i in 0..<4{ 434 | let doti = UIImage.size(width: CGFloat(30 - i * 4), height: CGFloat(30 - i * 4)) 435 | .color(gradient: [UIColor.randomColor(), UIColor.randomColor()], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 436 | .corner(radius: CGFloat(30 - i * 4) * 0.5) 437 | .image 438 | .position(CGPoint(x: i * 2, y: 30 * i + (i + 1) * 3)) 439 | container += doti 440 | } 441 | return container 442 | })()) 443 | iv14.frame.origin = CGPoint(x: UIScreen.main.bounds.width*0.5, y: iv13.frame.maxY+5) 444 | self.view.addSubview(iv14) 445 | 446 | let iv99 = UIImageView(image: 447 | ({ () -> UIImage in 448 | return UIImage.size(width: UIScreen.main.bounds.width*0.5, height: 44) 449 | .color(gradient: [.white, UIColor.randomColor().withAlphaComponent(0.5)], locations: [0, 1], from: CGPoint(x: 0, y: 0), to: CGPoint(x: 1, y: 1)) 450 | .corner(topLeft: 20) 451 | .image 452 | })()) 453 | iv99.frame.origin.x = iv8.frame.origin.x 454 | iv99.frame.origin.y = self.view.bounds.height - 44 455 | self.view.addSubview(iv99) 456 | } 457 | } 458 | 459 | --------------------------------------------------------------------------------