├── README.md ├── SDDrawingBoard.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── bnqc.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── SDDrawingBoard ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json ├── Contents.json ├── slider_thumb.imageset │ ├── Contents.json │ ├── 进度按钮@2x.png │ └── 进度按钮@3x.png ├── 圆形.imageset │ ├── Contents.json │ └── 圆形.png ├── 曲线.imageset │ ├── Contents.json │ └── 曲线.png ├── 矩形.imageset │ ├── Contents.json │ └── 矩形 (1).png └── 箭头.imageset │ ├── Contents.json │ └── 箭头.png ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── DrawViewController.h ├── DrawViewController.m ├── Info.plist ├── SDDrawView ├── SDBezierPath.h ├── SDBezierPath.m ├── SDDrawView.h └── SDDrawView.m ├── UIImage+Color.h ├── UIImage+Color.m └── main.m /README.md: -------------------------------------------------------------------------------- 1 | # SDDrawView 2 | SDDrawView is iOS DrawingBoard ,SDDrawView have a good arrow's draw way!!! welcome download SDDrawView 3 | 4 | SDDrawView 是 iOS的一个画板工具组件,简单上手~ 包含了线条、矩形、圆形、箭头.颜色设置,线条宽度设置,这里说一下SDDrawView最大的特点就是箭头 不再是以往的那种一个三角形加上一个矩形的样式 而是类似于QQ截图中的矩形,更加的圆滑,欢迎下载尝试! 5 | 6 |
7 | 8 | #### SDDrawView简介 9 | *** 10 | SDDrawView 是一款基于贝塞尔曲线的画板组件,目前样式包含线条、矩形、圆形、箭头等样式.具有调整画板颜色,线条宽度,线条颜色等基本功能.后期准备接入图片涂改,橡皮擦功能,添加文字等功能.至于为什么要做SDDrawView这样的一个三方画板组件,其实SDDrawView大部分功能和现在网上的画板组件都是类似的,是一个不折不扣的造轮子组件.其实,在网上找了很多的画板组件三方中**箭头**样式令人不是太满意显得非常的生硬,大部分是一个矩形加一个三角形组成的多边形箭头.SDDrawView的箭头样式却不同,SDDrawView箭头样式更类似于QQ截图中的箭头,更加的圆滑更加趋近于现实.接下来,看一下SDDrawView的效果演示图. 11 | 12 | ![](https://upload-images.jianshu.io/upload_images/1396375-3b48f2d68c5a9301.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 13 | 14 | 15 |
16 | 17 | #### SDDrawView快速集成 18 | *** 19 | 如何快速集成SDDrawView?非常简单,只需要把[SDDrawViewDemo](https://github.com/wang82426107/SDDrawView)下载下来,然后把Demo中的**SDDrawView**文件夹拖到你的工程中,然后如下导入头文件即可. 20 | ``` 21 | #import "SDDrawView.h" 22 | ``` 23 | SDDrawView初始化也比较简单.我们初始化一个SDDrawView对象然后添加到对应的View视图上即可. 24 | ``` 25 | //懒加载的形式初始化(可用可不用~) 26 | - (SDDrawView *)drawView{ 27 | 28 | if(_drawView == nil){ 29 | _drawView = [[SDDrawView alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | _drawView.drawViewColor = [UIColor whiteColor];//画板颜色 31 | _drawView.lineWidth = 2.0f;//线条宽度 32 | _drawView.drawStyle = DrawStyleLine;//样式 33 | _drawView.lineColor = [UIColor redColor];//线条颜色 34 | } 35 | return _drawView; 36 | 37 | } 38 | ``` 39 | 图形样式选择是一个枚举值,只需设定对应的样式,就可绘制不同的图形. 40 | ``` 41 | typedef enum : NSUInteger { 42 | DrawStyleLine, 43 | DrawStyleSquare, 44 | DrawStyleCircle, 45 | DrawStyleArrow 46 | } DrawStyle; 47 | ``` 48 | 49 | 这里说明一下**SDDrawView**所有的属性和方法. 50 | 51 | |属性或者方法|说明| 52 | |:---:|:---:| 53 | |drawViewColor|画板颜色| 54 | |lineWidth|画笔宽度| 55 | |drawStyle|绘制样式 值为DrawStyle的枚举值| 56 | |lineColor|画笔颜色| 57 | |- (void)cleanAction;|清除画板| 58 | |- (void)rollbackAction;|回退上一步| 59 | 60 | 61 |
62 | 63 | 64 | #### [实现过程博客地址传送门](https://www.jianshu.com/p/b778008c61c8) 65 | -------------------------------------------------------------------------------- /SDDrawingBoard.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E13E66BA20F43C6D004852A3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E66B920F43C6D004852A3 /* AppDelegate.m */; }; 11 | E13E66C020F43C6D004852A3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E13E66BE20F43C6D004852A3 /* Main.storyboard */; }; 12 | E13E66C220F43C6F004852A3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E13E66C120F43C6F004852A3 /* Assets.xcassets */; }; 13 | E13E66C520F43C6F004852A3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E13E66C320F43C6F004852A3 /* LaunchScreen.storyboard */; }; 14 | E13E66C820F43C6F004852A3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E66C720F43C6F004852A3 /* main.m */; }; 15 | E13E66D220F43D2B004852A3 /* SDBezierPath.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E66CF20F43D2B004852A3 /* SDBezierPath.m */; }; 16 | E13E66D320F43D2B004852A3 /* SDDrawView.m in Sources */ = {isa = PBXBuildFile; fileRef = E13E66D120F43D2B004852A3 /* SDDrawView.m */; }; 17 | E1E81DEB20F6FCE900C22ACE /* UIImage+Color.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E81DE920F6FCE900C22ACE /* UIImage+Color.m */; }; 18 | E1E81DEE20F7138900C22ACE /* DrawViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E81DED20F7138900C22ACE /* DrawViewController.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | E13E66B520F43C6D004852A3 /* SDDrawingBoard.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SDDrawingBoard.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | E13E66B820F43C6D004852A3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | E13E66B920F43C6D004852A3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | E13E66BF20F43C6D004852A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | E13E66C120F43C6F004852A3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | E13E66C420F43C6F004852A3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | E13E66C620F43C6F004852A3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | E13E66C720F43C6F004852A3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 30 | E13E66CE20F43D2B004852A3 /* SDBezierPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDBezierPath.h; sourceTree = ""; }; 31 | E13E66CF20F43D2B004852A3 /* SDBezierPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDBezierPath.m; sourceTree = ""; }; 32 | E13E66D020F43D2B004852A3 /* SDDrawView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDDrawView.h; sourceTree = ""; }; 33 | E13E66D120F43D2B004852A3 /* SDDrawView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDDrawView.m; sourceTree = ""; }; 34 | E1E81DE920F6FCE900C22ACE /* UIImage+Color.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Color.m"; sourceTree = ""; }; 35 | E1E81DEA20F6FCE900C22ACE /* UIImage+Color.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Color.h"; sourceTree = ""; }; 36 | E1E81DEC20F7138900C22ACE /* DrawViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DrawViewController.h; sourceTree = ""; }; 37 | E1E81DED20F7138900C22ACE /* DrawViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DrawViewController.m; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | E13E66B220F43C6D004852A3 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | E13E66AC20F43C6D004852A3 = { 52 | isa = PBXGroup; 53 | children = ( 54 | E13E66B720F43C6D004852A3 /* SDDrawingBoard */, 55 | E13E66B620F43C6D004852A3 /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | E13E66B620F43C6D004852A3 /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | E13E66B520F43C6D004852A3 /* SDDrawingBoard.app */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | E13E66B720F43C6D004852A3 /* SDDrawingBoard */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | E13E66B820F43C6D004852A3 /* AppDelegate.h */, 71 | E13E66B920F43C6D004852A3 /* AppDelegate.m */, 72 | E1E81DEC20F7138900C22ACE /* DrawViewController.h */, 73 | E1E81DED20F7138900C22ACE /* DrawViewController.m */, 74 | E1E81DEA20F6FCE900C22ACE /* UIImage+Color.h */, 75 | E1E81DE920F6FCE900C22ACE /* UIImage+Color.m */, 76 | E13E66D420F43D4B004852A3 /* SDDrawView */, 77 | E13E66BE20F43C6D004852A3 /* Main.storyboard */, 78 | E13E66C120F43C6F004852A3 /* Assets.xcassets */, 79 | E13E66C320F43C6F004852A3 /* LaunchScreen.storyboard */, 80 | E13E66C620F43C6F004852A3 /* Info.plist */, 81 | E13E66C720F43C6F004852A3 /* main.m */, 82 | ); 83 | path = SDDrawingBoard; 84 | sourceTree = ""; 85 | }; 86 | E13E66D420F43D4B004852A3 /* SDDrawView */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | E13E66D020F43D2B004852A3 /* SDDrawView.h */, 90 | E13E66D120F43D2B004852A3 /* SDDrawView.m */, 91 | E13E66CE20F43D2B004852A3 /* SDBezierPath.h */, 92 | E13E66CF20F43D2B004852A3 /* SDBezierPath.m */, 93 | ); 94 | path = SDDrawView; 95 | sourceTree = ""; 96 | }; 97 | /* End PBXGroup section */ 98 | 99 | /* Begin PBXNativeTarget section */ 100 | E13E66B420F43C6D004852A3 /* SDDrawingBoard */ = { 101 | isa = PBXNativeTarget; 102 | buildConfigurationList = E13E66CB20F43C6F004852A3 /* Build configuration list for PBXNativeTarget "SDDrawingBoard" */; 103 | buildPhases = ( 104 | E13E66B120F43C6D004852A3 /* Sources */, 105 | E13E66B220F43C6D004852A3 /* Frameworks */, 106 | E13E66B320F43C6D004852A3 /* Resources */, 107 | ); 108 | buildRules = ( 109 | ); 110 | dependencies = ( 111 | ); 112 | name = SDDrawingBoard; 113 | productName = SDDrawingBoard; 114 | productReference = E13E66B520F43C6D004852A3 /* SDDrawingBoard.app */; 115 | productType = "com.apple.product-type.application"; 116 | }; 117 | /* End PBXNativeTarget section */ 118 | 119 | /* Begin PBXProject section */ 120 | E13E66AD20F43C6D004852A3 /* Project object */ = { 121 | isa = PBXProject; 122 | attributes = { 123 | LastUpgradeCheck = 0940; 124 | ORGANIZATIONNAME = Dong; 125 | TargetAttributes = { 126 | E13E66B420F43C6D004852A3 = { 127 | CreatedOnToolsVersion = 9.4.1; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = E13E66B020F43C6D004852A3 /* Build configuration list for PBXProject "SDDrawingBoard" */; 132 | compatibilityVersion = "Xcode 9.3"; 133 | developmentRegion = en; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = E13E66AC20F43C6D004852A3; 140 | productRefGroup = E13E66B620F43C6D004852A3 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | E13E66B420F43C6D004852A3 /* SDDrawingBoard */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | E13E66B320F43C6D004852A3 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | E13E66C520F43C6F004852A3 /* LaunchScreen.storyboard in Resources */, 155 | E13E66C220F43C6F004852A3 /* Assets.xcassets in Resources */, 156 | E13E66C020F43C6D004852A3 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXSourcesBuildPhase section */ 163 | E13E66B120F43C6D004852A3 /* Sources */ = { 164 | isa = PBXSourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | E13E66D320F43D2B004852A3 /* SDDrawView.m in Sources */, 168 | E1E81DEE20F7138900C22ACE /* DrawViewController.m in Sources */, 169 | E13E66C820F43C6F004852A3 /* main.m in Sources */, 170 | E1E81DEB20F6FCE900C22ACE /* UIImage+Color.m in Sources */, 171 | E13E66D220F43D2B004852A3 /* SDBezierPath.m in Sources */, 172 | E13E66BA20F43C6D004852A3 /* AppDelegate.m in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin PBXVariantGroup section */ 179 | E13E66BE20F43C6D004852A3 /* Main.storyboard */ = { 180 | isa = PBXVariantGroup; 181 | children = ( 182 | E13E66BF20F43C6D004852A3 /* Base */, 183 | ); 184 | name = Main.storyboard; 185 | sourceTree = ""; 186 | }; 187 | E13E66C320F43C6F004852A3 /* LaunchScreen.storyboard */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | E13E66C420F43C6F004852A3 /* Base */, 191 | ); 192 | name = LaunchScreen.storyboard; 193 | sourceTree = ""; 194 | }; 195 | /* End PBXVariantGroup section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | E13E66C920F43C6F004852A3 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_ANALYZER_NONNULL = YES; 203 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 205 | CLANG_CXX_LIBRARY = "libc++"; 206 | CLANG_ENABLE_MODULES = YES; 207 | CLANG_ENABLE_OBJC_ARC = YES; 208 | CLANG_ENABLE_OBJC_WEAK = YES; 209 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 210 | CLANG_WARN_BOOL_CONVERSION = YES; 211 | CLANG_WARN_COMMA = YES; 212 | CLANG_WARN_CONSTANT_CONVERSION = YES; 213 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 214 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 215 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 216 | CLANG_WARN_EMPTY_BODY = YES; 217 | CLANG_WARN_ENUM_CONVERSION = YES; 218 | CLANG_WARN_INFINITE_RECURSION = YES; 219 | CLANG_WARN_INT_CONVERSION = YES; 220 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 221 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 222 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 223 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 224 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 225 | CLANG_WARN_STRICT_PROTOTYPES = YES; 226 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 227 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 228 | CLANG_WARN_UNREACHABLE_CODE = YES; 229 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 230 | CODE_SIGN_IDENTITY = "iPhone Developer"; 231 | COPY_PHASE_STRIP = NO; 232 | DEBUG_INFORMATION_FORMAT = dwarf; 233 | ENABLE_STRICT_OBJC_MSGSEND = YES; 234 | ENABLE_TESTABILITY = YES; 235 | GCC_C_LANGUAGE_STANDARD = gnu11; 236 | GCC_DYNAMIC_NO_PIC = NO; 237 | GCC_NO_COMMON_BLOCKS = YES; 238 | GCC_OPTIMIZATION_LEVEL = 0; 239 | GCC_PREPROCESSOR_DEFINITIONS = ( 240 | "DEBUG=1", 241 | "$(inherited)", 242 | ); 243 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 244 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 245 | GCC_WARN_UNDECLARED_SELECTOR = YES; 246 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 247 | GCC_WARN_UNUSED_FUNCTION = YES; 248 | GCC_WARN_UNUSED_VARIABLE = YES; 249 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 250 | MTL_ENABLE_DEBUG_INFO = YES; 251 | ONLY_ACTIVE_ARCH = YES; 252 | SDKROOT = iphoneos; 253 | }; 254 | name = Debug; 255 | }; 256 | E13E66CA20F43C6F004852A3 /* Release */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_ANALYZER_NONNULL = YES; 261 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 262 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 263 | CLANG_CXX_LIBRARY = "libc++"; 264 | CLANG_ENABLE_MODULES = YES; 265 | CLANG_ENABLE_OBJC_ARC = YES; 266 | CLANG_ENABLE_OBJC_WEAK = YES; 267 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 268 | CLANG_WARN_BOOL_CONVERSION = YES; 269 | CLANG_WARN_COMMA = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INFINITE_RECURSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 279 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 280 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 281 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 282 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 283 | CLANG_WARN_STRICT_PROTOTYPES = YES; 284 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 285 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 286 | CLANG_WARN_UNREACHABLE_CODE = YES; 287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 288 | CODE_SIGN_IDENTITY = "iPhone Developer"; 289 | COPY_PHASE_STRIP = NO; 290 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 291 | ENABLE_NS_ASSERTIONS = NO; 292 | ENABLE_STRICT_OBJC_MSGSEND = YES; 293 | GCC_C_LANGUAGE_STANDARD = gnu11; 294 | GCC_NO_COMMON_BLOCKS = YES; 295 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 296 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 297 | GCC_WARN_UNDECLARED_SELECTOR = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 299 | GCC_WARN_UNUSED_FUNCTION = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 302 | MTL_ENABLE_DEBUG_INFO = NO; 303 | SDKROOT = iphoneos; 304 | VALIDATE_PRODUCT = YES; 305 | }; 306 | name = Release; 307 | }; 308 | E13E66CC20F43C6F004852A3 /* Debug */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 312 | CODE_SIGN_STYLE = Automatic; 313 | DEVELOPMENT_TEAM = T83P3V4T3D; 314 | INFOPLIST_FILE = SDDrawingBoard/Info.plist; 315 | LD_RUNPATH_SEARCH_PATHS = ( 316 | "$(inherited)", 317 | "@executable_path/Frameworks", 318 | ); 319 | PRODUCT_BUNDLE_IDENTIFIER = com.dong.SDDrawingBoard; 320 | PRODUCT_NAME = "$(TARGET_NAME)"; 321 | TARGETED_DEVICE_FAMILY = "1,2"; 322 | }; 323 | name = Debug; 324 | }; 325 | E13E66CD20F43C6F004852A3 /* Release */ = { 326 | isa = XCBuildConfiguration; 327 | buildSettings = { 328 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 329 | CODE_SIGN_STYLE = Automatic; 330 | DEVELOPMENT_TEAM = T83P3V4T3D; 331 | INFOPLIST_FILE = SDDrawingBoard/Info.plist; 332 | LD_RUNPATH_SEARCH_PATHS = ( 333 | "$(inherited)", 334 | "@executable_path/Frameworks", 335 | ); 336 | PRODUCT_BUNDLE_IDENTIFIER = com.dong.SDDrawingBoard; 337 | PRODUCT_NAME = "$(TARGET_NAME)"; 338 | TARGETED_DEVICE_FAMILY = "1,2"; 339 | }; 340 | name = Release; 341 | }; 342 | /* End XCBuildConfiguration section */ 343 | 344 | /* Begin XCConfigurationList section */ 345 | E13E66B020F43C6D004852A3 /* Build configuration list for PBXProject "SDDrawingBoard" */ = { 346 | isa = XCConfigurationList; 347 | buildConfigurations = ( 348 | E13E66C920F43C6F004852A3 /* Debug */, 349 | E13E66CA20F43C6F004852A3 /* Release */, 350 | ); 351 | defaultConfigurationIsVisible = 0; 352 | defaultConfigurationName = Release; 353 | }; 354 | E13E66CB20F43C6F004852A3 /* Build configuration list for PBXNativeTarget "SDDrawingBoard" */ = { 355 | isa = XCConfigurationList; 356 | buildConfigurations = ( 357 | E13E66CC20F43C6F004852A3 /* Debug */, 358 | E13E66CD20F43C6F004852A3 /* Release */, 359 | ); 360 | defaultConfigurationIsVisible = 0; 361 | defaultConfigurationName = Release; 362 | }; 363 | /* End XCConfigurationList section */ 364 | }; 365 | rootObject = E13E66AD20F43C6D004852A3 /* Project object */; 366 | } 367 | -------------------------------------------------------------------------------- /SDDrawingBoard.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SDDrawingBoard.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SDDrawingBoard.xcodeproj/xcuserdata/bnqc.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SDDrawingBoard.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SDDrawingBoard/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SDDrawingBoard 4 | // 5 | // Created by bnqc on 2018/7/10. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /SDDrawingBoard/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SDDrawingBoard 4 | // 5 | // Created by bnqc on 2018/7/10. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DrawViewController.h" 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | 20 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 21 | self.window.backgroundColor = [UIColor whiteColor]; 22 | UINavigationController *rootNavigationVC = [[UINavigationController alloc] initWithRootViewController:[[DrawViewController alloc] init]]; 23 | self.window.rootViewController = rootNavigationVC; 24 | [self.window makeKeyAndVisible]; 25 | return YES; 26 | } 27 | 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application { 30 | // 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. 31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 32 | } 33 | 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application { 36 | // 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. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | 41 | - (void)applicationWillEnterForeground:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationDidBecomeActive:(UIApplication *)application { 47 | // 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. 48 | } 49 | 50 | 51 | - (void)applicationWillTerminate:(UIApplication *)application { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /SDDrawingBoard/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 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/slider_thumb.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "进度按钮@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "进度按钮@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/slider_thumb.imageset/进度按钮@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/slider_thumb.imageset/进度按钮@2x.png -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/slider_thumb.imageset/进度按钮@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/slider_thumb.imageset/进度按钮@3x.png -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/圆形.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "圆形.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/圆形.imageset/圆形.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/圆形.imageset/圆形.png -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/曲线.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "曲线.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/曲线.imageset/曲线.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/曲线.imageset/曲线.png -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/矩形.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "矩形 (1).png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/矩形.imageset/矩形 (1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/矩形.imageset/矩形 (1).png -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/箭头.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "箭头.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SDDrawingBoard/Assets.xcassets/箭头.imageset/箭头.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wang82426107/SDDrawView/7cef77bd6f7777785265465088a62fdd37f75587/SDDrawingBoard/Assets.xcassets/箭头.imageset/箭头.png -------------------------------------------------------------------------------- /SDDrawingBoard/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 | -------------------------------------------------------------------------------- /SDDrawingBoard/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 | -------------------------------------------------------------------------------- /SDDrawingBoard/DrawViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DrawViewController.h 3 | // SDDrawingBoard 4 | // 5 | // Created by bnqc on 2018/7/12. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DrawViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SDDrawingBoard/DrawViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DrawViewController.m 3 | // SDDrawingBoard 4 | // 5 | // Created by bnqc on 2018/7/12. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import "DrawViewController.h" 10 | #import "UIImage+Color.h" 11 | #import "SDDrawView.h" 12 | #define KcurrentSystemVersion [[UIDevice currentDevice] systemVersion] 13 | #define KmainHeight [UIScreen mainScreen].bounds.size.height 14 | #define KmainWidth [UIScreen mainScreen].bounds.size.width 15 | #define StatusHeight ([[UIApplication sharedApplication]statusBarFrame].size.height) 16 | #define NavigationBarHeight (44.0f) 17 | 18 | @interface DrawViewController () 19 | 20 | @property(nonatomic,strong)SDDrawView *drawView; 21 | @property(nonatomic,strong)UIButton *lineButton; 22 | @property(nonatomic,strong)UIButton *squareButton; 23 | @property(nonatomic,strong)UIButton *circleButton; 24 | @property(nonatomic,strong)UIButton *arrowButton; 25 | @property(nonatomic,strong)UISlider *lineWidthSlider;//调整线条滑块 26 | @property(nonatomic,strong)UILabel *lineWidthLabel;//调整线条宽度的Label 27 | @property(nonatomic,strong)UIButton *redButton; 28 | @property(nonatomic,strong)UIButton *greenButton; 29 | @property(nonatomic,strong)UIButton *orangeButton; 30 | 31 | @end 32 | 33 | @implementation DrawViewController 34 | 35 | - (void)viewDidLoad { 36 | 37 | [super viewDidLoad]; 38 | [self loadNavigationBarAction]; 39 | [self.view addSubview:self.lineButton]; 40 | [self.view addSubview:self.squareButton]; 41 | [self.view addSubview:self.circleButton]; 42 | [self.view addSubview:self.arrowButton]; 43 | [self.view addSubview:self.drawView]; 44 | [self.view addSubview:self.lineWidthSlider]; 45 | [self.view addSubview:self.lineWidthLabel]; 46 | [self.view addSubview:self.redButton]; 47 | [self.view addSubview:self.greenButton]; 48 | [self.view addSubview:self.orangeButton]; 49 | self.view.backgroundColor = [UIColor whiteColor]; 50 | 51 | } 52 | 53 | - (void)viewSafeAreaInsetsDidChange{ 54 | 55 | [super viewSafeAreaInsetsDidChange]; 56 | if ([KcurrentSystemVersion intValue] > 11.0) { 57 | self.additionalSafeAreaInsets = UIEdgeInsetsMake(44, 0, 0, 10); 58 | } 59 | 60 | } 61 | 62 | - (void)loadNavigationBarAction{ 63 | 64 | self.navigationItem.title = @"画板功能"; 65 | self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"清空画板" style:UIBarButtonItemStyleDone target:self action:@selector(clearDrawViewAction)]; 66 | self.navigationItem.leftBarButtonItem.tintColor = [UIColor blackColor]; 67 | self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"回退上一步" style:UIBarButtonItemStyleDone target:self action:@selector(rollbackDrawViewAction)]; 68 | self.navigationItem.rightBarButtonItem.tintColor = [UIColor blackColor]; 69 | 70 | } 71 | 72 | - (void)clearDrawViewAction{ 73 | 74 | [_drawView cleanAction]; 75 | 76 | } 77 | 78 | - (void)rollbackDrawViewAction{ 79 | 80 | [_drawView rollbackAction]; 81 | 82 | } 83 | 84 | #pragma mark - 懒加载(这种情况没毛用,习惯而已) 85 | - (UIButton *)lineButton{ 86 | 87 | if(_lineButton == nil){ 88 | _lineButton = [[UIButton alloc] initWithFrame:CGRectMake(0, StatusHeight + NavigationBarHeight, KmainWidth/4.0, 40)]; 89 | _lineButton.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1]; 90 | _lineButton.selected = YES; 91 | [_lineButton setTitle:@" 直线" forState:UIControlStateNormal]; 92 | [_lineButton setImage:[UIImage imageNamed:@"曲线"] forState:UIControlStateNormal]; 93 | [_lineButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; 94 | [_lineButton setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; 95 | [_lineButton addTarget:self action:@selector(selectLineDrawType:) forControlEvents:UIControlEventTouchUpInside]; 96 | } 97 | return _lineButton; 98 | } 99 | 100 | - (UIButton *)squareButton{ 101 | 102 | if(_squareButton == nil){ 103 | _squareButton = [[UIButton alloc] initWithFrame:CGRectMake(KmainWidth/4.0, StatusHeight + NavigationBarHeight, KmainWidth/4.0, 40)]; 104 | _squareButton.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1]; 105 | [_squareButton setTitle:@" 矩形" forState:UIControlStateNormal]; 106 | [_squareButton setImage:[UIImage imageNamed:@"矩形"] forState:UIControlStateNormal]; 107 | [_squareButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; 108 | [_squareButton setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; 109 | [_squareButton addTarget:self action:@selector(selectLineDrawType:) forControlEvents:UIControlEventTouchUpInside]; 110 | } 111 | return _squareButton; 112 | } 113 | 114 | 115 | - (UIButton *)circleButton{ 116 | 117 | if(_circleButton == nil){ 118 | _circleButton = [[UIButton alloc] initWithFrame:CGRectMake(KmainWidth/2.0, StatusHeight + NavigationBarHeight, KmainWidth/4.0, 40)]; 119 | _circleButton.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1]; 120 | [_circleButton setTitle:@" 圆形" forState:UIControlStateNormal]; 121 | [_circleButton setImage:[UIImage imageNamed:@"圆形"] forState:UIControlStateNormal]; 122 | [_circleButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; 123 | [_circleButton setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; 124 | [_circleButton addTarget:self action:@selector(selectLineDrawType:) forControlEvents:UIControlEventTouchUpInside]; 125 | } 126 | return _circleButton; 127 | } 128 | 129 | 130 | - (UIButton *)arrowButton{ 131 | 132 | if(_arrowButton == nil){ 133 | _arrowButton = [[UIButton alloc] initWithFrame:CGRectMake(KmainWidth/4.0*3, StatusHeight + NavigationBarHeight, KmainWidth/4.0, 40)]; 134 | _arrowButton.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1]; 135 | [_arrowButton setTitle:@" 箭头" forState:UIControlStateNormal]; 136 | [_arrowButton setImage:[UIImage imageNamed:@"箭头"] forState:UIControlStateNormal]; 137 | [_arrowButton setTitleColor:[UIColor lightGrayColor] forState:UIControlStateNormal]; 138 | [_arrowButton setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; 139 | [_arrowButton addTarget:self action:@selector(selectLineDrawType:) forControlEvents:UIControlEventTouchUpInside]; 140 | } 141 | return _arrowButton; 142 | } 143 | 144 | 145 | - (SDDrawView *)drawView{ 146 | 147 | if(_drawView == nil){ 148 | 149 | _drawView = [[SDDrawView alloc] initWithFrame:CGRectMake(0, StatusHeight + NavigationBarHeight + 40, KmainWidth, KmainHeight - StatusHeight - NavigationBarHeight - 40 - 40 - 60)]; 150 | _drawView.drawViewColor = [UIColor whiteColor]; 151 | _drawView.lineWidth = 2.0f; 152 | _drawView.drawStyle = DrawStyleLine; 153 | _drawView.lineColor = [UIColor redColor]; 154 | _drawView.layer.borderWidth = 1.0f; 155 | _drawView.layer.borderColor = [self hexStringToColor:@"c0c0c0"].CGColor; 156 | } 157 | return _drawView; 158 | 159 | } 160 | 161 | - (UISlider *)lineWidthSlider{ 162 | 163 | 164 | if(_lineWidthSlider == nil){ 165 | _lineWidthSlider = [[UISlider alloc] initWithFrame:CGRectMake(20, CGRectGetMaxY(_drawView.frame), KmainWidth - 40 - 60, 40)]; 166 | [_lineWidthSlider setThumbImage:[UIImage imageNamed:@"slider_thumb"] forState:UIControlStateNormal]; 167 | [_lineWidthSlider addTarget:self action:@selector(lineWidthAction:) forControlEvents:UIControlEventValueChanged]; 168 | _lineWidthSlider.minimumTrackTintColor = [self hexStringToColor:@"facc60"]; 169 | _lineWidthSlider.minimumValue = 2; 170 | _lineWidthSlider.maximumValue = 8; 171 | } 172 | return _lineWidthSlider; 173 | 174 | } 175 | 176 | - (UILabel *)lineWidthLabel{ 177 | 178 | if(_lineWidthLabel == nil){ 179 | _lineWidthLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(_lineWidthSlider.frame) + 5, CGRectGetMaxY(_drawView.frame), 55, 40)]; 180 | _lineWidthLabel.font = [UIFont systemFontOfSize:12]; 181 | _lineWidthLabel.text = @"宽度:2.0"; 182 | _lineWidthLabel.textColor = [UIColor blackColor]; 183 | } 184 | return _lineWidthLabel; 185 | 186 | } 187 | 188 | - (UIButton *)redButton{ 189 | 190 | if(_redButton == nil){ 191 | _redButton = [[UIButton alloc] initWithFrame:CGRectMake(20, CGRectGetMaxY(_lineWidthLabel.frame) + 15, KmainWidth/3.0 - 40, 30)]; 192 | _redButton.titleLabel.font = [UIFont systemFontOfSize:14]; 193 | _redButton.backgroundColor = [UIColor redColor]; 194 | _redButton.layer.cornerRadius = 4.0f; 195 | _redButton.layer.masksToBounds = YES; 196 | [_redButton setTitle:@"" forState:UIControlStateNormal]; 197 | [_redButton setTitle:@"✔️" forState:UIControlStateSelected]; 198 | [_redButton addTarget:self action:@selector(selectDrawViewColorAction:) forControlEvents:UIControlEventTouchUpInside]; 199 | _redButton.selected = YES; 200 | } 201 | return _redButton; 202 | 203 | } 204 | 205 | - (UIButton *)greenButton{ 206 | 207 | if(_greenButton == nil){ 208 | _greenButton = [[UIButton alloc] initWithFrame:CGRectMake(20 + KmainWidth/3.0 , CGRectGetMaxY(_lineWidthLabel.frame) + 15, KmainWidth/3.0 - 40, 30)]; 209 | _greenButton.titleLabel.font = [UIFont systemFontOfSize:14]; 210 | _greenButton.backgroundColor = [UIColor greenColor]; 211 | _greenButton.layer.cornerRadius = 4.0f; 212 | _greenButton.layer.masksToBounds = YES; 213 | [_greenButton setTitle:@"" forState:UIControlStateNormal]; 214 | [_greenButton setTitle:@"✔️" forState:UIControlStateSelected]; 215 | [_greenButton addTarget:self action:@selector(selectDrawViewColorAction:) forControlEvents:UIControlEventTouchUpInside]; 216 | } 217 | return _greenButton; 218 | 219 | } 220 | 221 | - (UIButton *)orangeButton{ 222 | 223 | if(_orangeButton == nil){ 224 | _orangeButton = [[UIButton alloc] initWithFrame:CGRectMake(20 + KmainWidth/3.0*2 , CGRectGetMaxY(_lineWidthLabel.frame) + 15, KmainWidth/3.0 - 40, 30)]; 225 | _orangeButton.titleLabel.font = [UIFont systemFontOfSize:14]; 226 | _orangeButton.backgroundColor = [UIColor orangeColor]; 227 | _orangeButton.layer.cornerRadius = 4.0f; 228 | _orangeButton.layer.masksToBounds = YES; 229 | [_orangeButton setTitle:@"" forState:UIControlStateNormal]; 230 | [_orangeButton setTitle:@"✔️" forState:UIControlStateSelected]; 231 | [_orangeButton addTarget:self action:@selector(selectDrawViewColorAction:) forControlEvents:UIControlEventTouchUpInside]; 232 | } 233 | return _orangeButton; 234 | 235 | } 236 | 237 | #pragma mark - 选择绘制样式(方式很low) 238 | - (void)selectLineDrawType:(UIButton *)sender{ 239 | 240 | _lineButton.selected = NO; 241 | _squareButton.selected = NO; 242 | _circleButton.selected = NO; 243 | _arrowButton.selected = NO; 244 | sender.selected = YES; 245 | 246 | if([sender isEqual: _lineButton]){ 247 | _drawView.drawStyle = DrawStyleLine; 248 | }else if([sender isEqual: _squareButton]){ 249 | _drawView.drawStyle = DrawStyleSquare; 250 | }else if([sender isEqual: _circleButton]){ 251 | _drawView.drawStyle = DrawStyleCircle; 252 | }else{ 253 | _drawView.drawStyle = DrawStyleArrow; 254 | } 255 | 256 | } 257 | 258 | #pragma mark - 修改绘制线条的宽度 259 | 260 | //设置宽度 (2.0 -8.0) 261 | - (void)lineWidthAction:(UISlider *)sender{ 262 | 263 | _drawView.lineWidth = sender.value; 264 | _lineWidthLabel.text = [NSString stringWithFormat:@"宽度:%.1f",sender.value]; 265 | 266 | } 267 | 268 | 269 | #pragma mark - 选择绘制颜色 270 | 271 | - (void)selectDrawViewColorAction:(UIButton *)sender{ 272 | 273 | _redButton.selected = NO; 274 | _greenButton.selected = NO; 275 | _orangeButton.selected = NO; 276 | sender.selected = YES; 277 | 278 | if([sender isEqual: _redButton]){ 279 | _drawView.lineColor = [UIColor redColor]; 280 | }else if([sender isEqual: _greenButton]){ 281 | _drawView.lineColor = [UIColor greenColor]; 282 | }else{ 283 | _drawView.lineColor = [UIColor orangeColor]; 284 | } 285 | 286 | } 287 | 288 | #pragma mark - 工具类(颜色) 289 | 290 | - (UIColor *)hexStringToColor:(NSString *)stringToConvert { 291 | NSString *cString = [[stringToConvert 292 | stringByTrimmingCharactersInSet: 293 | [NSCharacterSet whitespaceAndNewlineCharacterSet]] uppercaseString]; 294 | // String should be 6 or 8 characters 295 | if ([cString length] < 6) 296 | return [UIColor blackColor]; 297 | // strip 0X if it appears 298 | if ([cString hasPrefix:@"0X"]) 299 | cString = [cString substringFromIndex:2]; 300 | if ([cString hasPrefix:@"#"]) 301 | cString = [cString substringFromIndex:1]; 302 | if ([cString length] != 6) 303 | return [UIColor blackColor]; 304 | // Separate into r, g, b substrings 305 | NSRange range; 306 | range.location = 0; 307 | range.length = 2; 308 | NSString *rString = [cString substringWithRange:range]; 309 | range.location = 2; 310 | NSString *gString = [cString substringWithRange:range]; 311 | range.location = 4; 312 | NSString *bString = [cString substringWithRange:range]; 313 | // Scan values 314 | unsigned int r, g, b; 315 | [[NSScanner scannerWithString:rString] scanHexInt:&r]; 316 | [[NSScanner scannerWithString:gString] scanHexInt:&g]; 317 | [[NSScanner scannerWithString:bString] scanHexInt:&b]; 318 | return [UIColor colorWithRed:((float)r / 255.0f) 319 | green:((float)g / 255.0f) 320 | blue:((float)b / 255.0f) 321 | alpha:1.0f]; 322 | } 323 | 324 | 325 | @end 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | -------------------------------------------------------------------------------- /SDDrawingBoard/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /SDDrawingBoard/SDDrawView/SDBezierPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDBezierPath.h 3 | // SocketClinetDemo 4 | // 5 | // Created by bnqc on 2018/6/11. 6 | // Copyright © 2018年 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | typedef enum : NSUInteger { 11 | DrawStyleLine, 12 | DrawStyleSquare, 13 | DrawStyleCircle, 14 | DrawStyleArrow 15 | } DrawStyle; 16 | 17 | @interface SDBezierPath : UIBezierPath 18 | 19 | @property(nonatomic,strong) UIColor *lineColor;//绘制颜色 20 | @property(nonatomic,assign) DrawStyle drawStyle;//绘制样式 21 | 22 | @property(nonatomic,assign) CGPoint startPoint;//当是矩形或者是圆的时候,需要使用到这个属性 23 | @property(nonatomic,assign) CGPoint endPoint;//当是矩形或者是圆的时候,需要使用到这个属性 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /SDDrawingBoard/SDDrawView/SDBezierPath.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDBezierPath.m 3 | // SocketClinetDemo 4 | // 5 | // Created by bnqc on 2018/6/11. 6 | // Copyright © 2018年 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDBezierPath.h" 10 | 11 | @interface SDBezierPath(){ 12 | 13 | double KEY_POINT_LEN1; 14 | double KEY_POINT_LEN2; 15 | double KEY_POINT_LEN3; 16 | double KEY_POINT_ANGLE1; 17 | double KEY_POINT_ANGLE2; 18 | double KEY_POINT_ANGLE3; 19 | double KEY_POINT_RATIO1; 20 | double KEY_POINT_RATIO2; 21 | double KEY_POINT_RATIO3; 22 | 23 | float startX; 24 | float startY; 25 | float endX; 26 | float endY; 27 | } 28 | 29 | 30 | @end 31 | 32 | @implementation SDBezierPath 33 | 34 | 35 | - (void)setDrawStyle:(DrawStyle)drawStyle{ 36 | 37 | _drawStyle = drawStyle; 38 | if (_drawStyle == DrawStyleArrow) { 39 | 40 | //初始化箭头的相关固定值 41 | KEY_POINT_LEN1 = 70; 42 | KEY_POINT_LEN2 = 55; 43 | KEY_POINT_LEN3 = 8; 44 | KEY_POINT_ANGLE1 = 30 * M_PI/ 180; 45 | KEY_POINT_ANGLE2 = 18 * M_PI/ 180; 46 | KEY_POINT_ANGLE3 = 90 * M_PI/ 180; 47 | KEY_POINT_RATIO1 = 0.2; 48 | KEY_POINT_RATIO2 = 0.157; 49 | KEY_POINT_RATIO3 = 0.023; 50 | } 51 | } 52 | 53 | - (void)setStartPoint:(CGPoint)startPoint{ 54 | 55 | _startPoint = startPoint; 56 | startX = _startPoint.x; 57 | startY = _startPoint.y; 58 | } 59 | 60 | - (void)setEndPoint:(CGPoint)endPoint{ 61 | _endPoint = endPoint; 62 | endX = endPoint.x; 63 | endY = endPoint.y; 64 | 65 | if (_drawStyle == DrawStyleArrow) { 66 | [self removeAllPoints];//移除所有的路径点 67 | //配置箭头的6个点位 68 | double len1 = KEY_POINT_LEN1; 69 | double len2 = KEY_POINT_LEN2; 70 | double len3 = KEY_POINT_LEN3; 71 | 72 | double len = sqrt(pow((endX - startX), 2) + pow((endY - startY), 2)); 73 | if (len * KEY_POINT_RATIO1 < KEY_POINT_LEN1) { 74 | len1 = len * KEY_POINT_RATIO1; 75 | } 76 | if (len * KEY_POINT_RATIO2 < KEY_POINT_LEN2) { 77 | len2 = len * KEY_POINT_RATIO2; 78 | } 79 | if (len * KEY_POINT_RATIO3 < KEY_POINT_LEN3) { 80 | len3 = len * KEY_POINT_RATIO3; 81 | } 82 | CGPoint arrXY_11 = [self rotateVecWithPx:endX - startX py:endY - startY ang:KEY_POINT_ANGLE1 newLen:len1]; 83 | CGPoint arrXY_12 = [self rotateVecWithPx:endX - startX py:endY - startY ang:-KEY_POINT_ANGLE1 newLen:len1]; 84 | CGPoint arrXY_21 = [self rotateVecWithPx:endX - startX py:endY - startY ang:KEY_POINT_ANGLE2 newLen:len2]; 85 | CGPoint arrXY_22 = [self rotateVecWithPx:endX - startX py:endY - startY ang:-KEY_POINT_ANGLE2 newLen:len2]; 86 | CGPoint arrXY_31 = [self rotateVecWithPx:startX - endX py:startY - endY ang:KEY_POINT_ANGLE3 newLen:len3]; 87 | CGPoint arrXY_32 = [self rotateVecWithPx:startX - endX py:startY - endY ang:-KEY_POINT_ANGLE3 newLen:len3];; 88 | 89 | float x11 = endX - arrXY_11.x; 90 | float y11 = endY - arrXY_11.y; 91 | float x12 = endX - arrXY_12.x; 92 | float y12 = endY - arrXY_12.y; 93 | float x21 = endX - arrXY_21.x; 94 | float y21 = endY - arrXY_21.y; 95 | float x22 = endX - arrXY_22.x; 96 | float y22 = endY - arrXY_22.y; 97 | float x31 = startX - arrXY_31.x; 98 | float y31 = startY - arrXY_31.y; 99 | float x32 = startX - arrXY_32.x; 100 | float y32 = startY - arrXY_32.y; 101 | [self moveToPoint:endPoint]; 102 | [self addLineToPoint:CGPointMake(x11, y11)]; 103 | [self addLineToPoint:CGPointMake(x21, y21)]; 104 | [self addLineToPoint:CGPointMake(x32, y32)]; 105 | [self addLineToPoint:CGPointMake(x31, y31)]; 106 | [self addLineToPoint:CGPointMake(x22, y22)]; 107 | [self addLineToPoint:CGPointMake(x12, y12)]; 108 | 109 | } 110 | } 111 | 112 | 113 | /** 114 | * 极坐标变换 115 | */ 116 | 117 | - (CGPoint)rotateVecWithPx:(float)px py:(float)py ang:(double)ang newLen:(double)newLen{ 118 | 119 | double vx = px * cos(ang) - py * sin(ang); 120 | double vy = px * sin(ang) + py * cos(ang); 121 | double d = sqrt(vx * vx + vy * vy); 122 | vx = vx / d * newLen; 123 | vy = vy / d * newLen; 124 | return CGPointMake((float) vx, (float) vy); 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /SDDrawingBoard/SDDrawView/SDDrawView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SDDrawView.h 3 | // SocketClinetDemo 4 | // 5 | // Created by bnqc on 2018/6/11. 6 | // Copyright © 2018年 骚栋. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SDBezierPath.h" 11 | 12 | @interface SDDrawView : UIView 13 | 14 | //SDDrawView是图形绘制的View 15 | 16 | /***********通用属性**************/ 17 | 18 | @property(nonatomic,strong) UIColor *drawViewColor;//画板颜色 19 | @property(nonatomic,assign) CGFloat lineWidth;//画笔宽度 20 | @property(nonatomic,assign) DrawStyle drawStyle;//绘制样式 21 | @property(nonatomic,strong) UIColor *lineColor;//画笔颜色 22 | 23 | - (void)cleanAction;//清除画板 24 | - (void)rollbackAction;//回退上一步 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /SDDrawingBoard/SDDrawView/SDDrawView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SDDrawView.m 3 | // SocketClinetDemo 4 | // 5 | // Created by bnqc on 2018/6/11. 6 | // Copyright © 2018年 骚栋. All rights reserved. 7 | // 8 | 9 | #import "SDDrawView.h" 10 | 11 | @interface SDDrawView() 12 | 13 | @property(nonatomic,strong)NSMutableArray *pathsArray; 14 | 15 | @end 16 | 17 | @implementation SDDrawView 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame{ 20 | 21 | if (self = [super initWithFrame:frame]) { 22 | _pathsArray = [NSMutableArray arrayWithCapacity:16]; 23 | self.backgroundColor = [UIColor whiteColor]; 24 | } 25 | return self; 26 | } 27 | 28 | //清除 29 | - (void)cleanAction{ 30 | [self.pathsArray removeAllObjects]; 31 | //重绘 32 | [self setNeedsDisplay]; 33 | } 34 | 35 | //回退 36 | - (void)rollbackAction{ 37 | [self.pathsArray removeLastObject]; 38 | //重绘 39 | [self setNeedsDisplay]; 40 | } 41 | 42 | -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 43 | // 获取触摸对象 44 | UITouch *touch=[touches anyObject]; 45 | // 获取手指的位置 46 | CGPoint point=[touch locationInView:touch.view]; 47 | //当手指按下的时候就创建一条路径 48 | SDBezierPath *path=[SDBezierPath bezierPath]; 49 | path.drawStyle = _drawStyle; 50 | //设置画笔宽度 51 | if(_lineWidth<=0){ 52 | [path setLineWidth:5]; 53 | }else{ 54 | [path setLineWidth:_lineWidth]; 55 | } 56 | //设置画笔颜色 57 | [path setLineColor:_lineColor]; 58 | //设置起点 59 | switch (path.drawStyle) { 60 | case DrawStyleLine: 61 | [path moveToPoint:point]; 62 | break; 63 | case DrawStyleSquare:case DrawStyleCircle: 64 | [path moveToPoint:point]; 65 | 66 | path.startPoint = point; 67 | break; 68 | case DrawStyleArrow: 69 | path.startPoint = point; 70 | break; 71 | } 72 | // 把每一次新创建的路径 添加到数组当中 73 | [self.pathsArray addObject:path]; 74 | } 75 | 76 | 77 | -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{ 78 | // 获取触摸对象 79 | UITouch *touch=[touches anyObject]; 80 | // 获取手指的位置 81 | CGPoint point=[touch locationInView:touch.view]; 82 | // 连线的点 83 | SDBezierPath *path = self.pathsArray.lastObject; 84 | 85 | switch (path.drawStyle) { 86 | case DrawStyleLine: 87 | [path addLineToPoint:point]; 88 | break; 89 | case DrawStyleSquare:case DrawStyleCircle: 90 | path.endPoint = point; 91 | break; 92 | case DrawStyleArrow: 93 | path.endPoint = point; 94 | 95 | break; 96 | } 97 | 98 | // 重绘 99 | [self setNeedsDisplay]; 100 | } 101 | 102 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ 103 | // 连线的点 104 | SDBezierPath *path = self.pathsArray.lastObject; 105 | switch (path.drawStyle) { 106 | case DrawStyleLine:{ 107 | // 获取触摸对象 108 | UITouch *touch=[touches anyObject]; 109 | // 获取手指的位置 110 | CGPoint point=[touch locationInView:touch.view]; 111 | // 连线的点 112 | [[self.pathsArray lastObject] addLineToPoint:point]; 113 | // 重绘 114 | [self setNeedsDisplay]; 115 | 116 | }break; 117 | case DrawStyleSquare:case DrawStyleCircle: 118 | break; 119 | case DrawStyleArrow: 120 | break; 121 | } 122 | } 123 | 124 | 125 | - (void)drawRect:(CGRect)rect { 126 | // Drawing code 127 | for (SDBezierPath *path in self.pathsArray) { 128 | 129 | switch (path.drawStyle) { 130 | case DrawStyleLine: { 131 | //设置颜色 132 | [path.lineColor set]; 133 | // 设置连接处的样式 134 | [path setLineJoinStyle:kCGLineJoinRound]; 135 | // 设置头尾的样式 136 | [path setLineCapStyle:kCGLineCapRound]; 137 | //渲染 138 | [path stroke]; 139 | 140 | }break; 141 | case DrawStyleSquare:{ 142 | UIBezierPath *drawPath = [UIBezierPath bezierPathWithRect:CGRectMake(path.startPoint.x, path.startPoint.y, path.endPoint.x - path.startPoint.x, path.endPoint.y - path.startPoint.y)]; 143 | //设置宽度 144 | drawPath.lineWidth = path.lineWidth; 145 | //设置颜色 146 | [path.lineColor set]; 147 | // 设置连接处的样式 148 | [drawPath setLineJoinStyle:kCGLineJoinRound]; 149 | // 设置头尾的样式 150 | [drawPath setLineCapStyle:kCGLineCapRound]; 151 | //渲染 152 | [drawPath stroke]; 153 | 154 | }break; 155 | 156 | case DrawStyleCircle: { 157 | UIBezierPath *drawPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(path.startPoint.x, path.startPoint.y, path.endPoint.x - path.startPoint.x, path.endPoint.y - path.startPoint.y)]; 158 | //设置宽度 159 | drawPath.lineWidth = path.lineWidth; 160 | //设置颜色 161 | [path.lineColor set]; 162 | // 设置连接处的样式 163 | [drawPath setLineJoinStyle:kCGLineJoinRound]; 164 | // 设置头尾的样式 165 | [drawPath setLineCapStyle:kCGLineCapRound]; 166 | //渲染 167 | [drawPath stroke]; 168 | }break; 169 | case DrawStyleArrow: { 170 | //设置颜色 171 | [path.lineColor set]; 172 | // 设置连接处的样式 173 | [path setLineJoinStyle:kCGLineJoinMiter]; 174 | // 设置头尾的样式 175 | [path setLineCapStyle:kCGLineCapSquare]; 176 | 177 | [path fill]; 178 | }break; 179 | } 180 | } 181 | } 182 | 183 | 184 | @end 185 | -------------------------------------------------------------------------------- /SDDrawingBoard/UIImage+Color.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Color.h 3 | // UIImage+Categories 4 | // 5 | // Created by lisong on 16/9/4. 6 | // Copyright © 2016年 lisong. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (Color) 12 | 13 | /** 根据颜色生成纯色图片 */ 14 | + (UIImage *)imageWithColor:(UIColor *)color; 15 | 16 | /** 取图片某一像素的颜色 */ 17 | - (UIColor *)colorAtPixel:(CGPoint)point; 18 | 19 | /** 获得灰度图 */ 20 | - (UIImage *)convertToGrayImage; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /SDDrawingBoard/UIImage+Color.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Color.m 3 | // UIImage+Categories 4 | // 5 | // Created by lisong on 16/9/4. 6 | // Copyright © 2016年 lisong. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Color.h" 10 | 11 | @implementation UIImage (Color) 12 | 13 | /** 根据颜色生成纯色图片 */ 14 | + (UIImage *)imageWithColor:(UIColor *)color 15 | { 16 | CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); 17 | UIGraphicsBeginImageContext(rect.size); 18 | CGContextRef context = UIGraphicsGetCurrentContext(); 19 | 20 | CGContextSetFillColorWithColor(context, [color CGColor]); 21 | CGContextFillRect(context, rect); 22 | 23 | UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 24 | UIGraphicsEndImageContext(); 25 | 26 | return image; 27 | } 28 | 29 | /** 取图片某一像素的颜色 */ 30 | - (UIColor *)colorAtPixel:(CGPoint)point 31 | { 32 | if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, self.size.width, self.size.height), point)) 33 | { 34 | return nil; 35 | } 36 | 37 | NSInteger pointX = trunc(point.x); 38 | NSInteger pointY = trunc(point.y); 39 | CGImageRef cgImage = self.CGImage; 40 | NSUInteger width = self.size.width; 41 | NSUInteger height = self.size.height; 42 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 43 | int bytesPerPixel = 4; 44 | int bytesPerRow = bytesPerPixel * 1; 45 | NSUInteger bitsPerComponent = 8; 46 | unsigned char pixelData[4] = { 0, 0, 0, 0 }; 47 | CGContextRef context = CGBitmapContextCreate(pixelData, 48 | 1, 49 | 1, 50 | bitsPerComponent, 51 | bytesPerRow, 52 | colorSpace, 53 | kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 54 | CGColorSpaceRelease(colorSpace); 55 | CGContextSetBlendMode(context, kCGBlendModeCopy); 56 | 57 | CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height); 58 | CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage); 59 | CGContextRelease(context); 60 | 61 | CGFloat red = (CGFloat)pixelData[0] / 255.0f; 62 | CGFloat green = (CGFloat)pixelData[1] / 255.0f; 63 | CGFloat blue = (CGFloat)pixelData[2] / 255.0f; 64 | CGFloat alpha = (CGFloat)pixelData[3] / 255.0f; 65 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 66 | } 67 | 68 | /** 获得灰度图 */ 69 | - (UIImage *)convertToGrayImage 70 | { 71 | int width = self.size.width; 72 | int height = self.size.height; 73 | 74 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); 75 | CGContextRef context = CGBitmapContextCreate(nil,width,height,8,0,colorSpace,kCGImageAlphaNone); 76 | CGColorSpaceRelease(colorSpace); 77 | 78 | if (context == NULL) 79 | { 80 | return nil; 81 | } 82 | 83 | CGContextDrawImage(context,CGRectMake(0, 0, width, height), self.CGImage); 84 | CGImageRef contextRef = CGBitmapContextCreateImage(context); 85 | UIImage *grayImage = [UIImage imageWithCGImage:contextRef]; 86 | CGContextRelease(context); 87 | CGImageRelease(contextRef); 88 | 89 | return grayImage; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /SDDrawingBoard/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SDDrawingBoard 4 | // 5 | // Created by bnqc on 2018/7/10. 6 | // Copyright © 2018年 Dong. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------