封装CoreGraphics的API简化绘图操作

简介:

封装CoreGraphics的API简化绘图操作

 

效果

 

说明

1. 将CoreGraphics的API接口抽象为对象,让绘图变得简单易懂

2. 简化常用的绘制操作

3. 源码长期更新

 

源码

https://github.com/YouXianMing/CGContextObject



//
//  CGContextObject.h
//  DrawRect
//
//  Created by YouXianMing on 15/7/2.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import "RGBColor.h"
#import "GradientColor.h"
@class CGContextObject;


typedef void(^CGContextObjectDrawBlock_t)(CGContextObject *contextObject);


@interface CGContextObject : NSObject

/**
 *  操作句柄
 */
@property (nonatomic)          CGContextRef   context;

/**
 *  线头样式
 */
@property (nonatomic)          CGLineCap      lineCap;

/**
 *  线条宽度
 */
@property (nonatomic)          CGFloat        lineWidth;

/**
 *  线条颜色
 */
@property (nonatomic, strong)  RGBColor      *strokeColor;

/**
 *  填充颜色
 */
@property (nonatomic, strong)  RGBColor      *fillColor;

/**
 *  由context进行初始化
 *
 *  @param context 绘制句柄
 *
 *  @return 绘制对象
 */
- (instancetype)initWithCGContext:(CGContextRef)context;

#pragma mark - 绘制操作流程
/**
 *  开始path
 */
- (void)beginPath;

/**
 *  关闭path
 */
- (void)closePath;

/**
 *  线条绘制
 */
- (void)strokePath;

/**
 *  填充绘制
 */
- (void)fillPath;

/**
 *  线条绘制 + 填充绘制
 */
- (void)strokeAndFillPath;

/**
 *  绘制线条用block (beginPath + closePath + 你绘制的代码 + strokePath)
 *
 *  @param block 绘制用block
 */
- (void)drawStrokeBlock:(CGContextObjectDrawBlock_t)block;

/**
 *  填充区域用block (beginPath + closePath + 你绘制的代码 + fillPath)
 *
 *  @param block 填充用block
 */
- (void)drawFillBlock:(CGContextObjectDrawBlock_t)block;

/**
 *  绘制加填充
 *
 *  @param block 绘制加填充用block
 */
- (void)drawStrokeAndFillBlock:(CGContextObjectDrawBlock_t)block;

/**
 *  绘制线条用block (beginPath + closePath + 你绘制的代码 + strokePath)
 *
 *  @param block     绘制用block
 *  @param closePath 是否关闭曲线
 */
- (void)drawStrokeBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath;

/**
 *  填充区域用block (beginPath + closePath + 你绘制的代码 + fillPath)
 *
 *  @param block     绘制用block
 *  @param closePath 是否关闭曲线
 */
- (void)drawFillBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath;

/**
 *  绘制加填充
 *
 *  @param block     绘制用block
 *  @param closePath 是否关闭曲线
 */
- (void)drawStrokeAndFillBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath;

#pragma mark - 绘制图片API

- (void)drawImage:(UIImage *)image atPoint:(CGPoint)point;
- (void)drawImage:(UIImage *)image atPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;
- (void)drawImage:(UIImage *)image inRect:(CGRect)rect;
- (void)drawImage:(UIImage *)image inRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha;
- (void)drawImage:(UIImage *)image asPatternInRect:(CGRect)rect;

#pragma mark - 保存操作

/**
 *  将当前设置存取到栈区中(入栈操作)
 */
- (void)saveStateToStack;

/**
 *  从栈区中取出之前保存的设置(出栈操作)
 */
- (void)restoreStateFromStack;

#pragma mark - 图形绘制API
/**
 *  移动到起始点
 *
 *  @param point 起始点
 */
- (void)moveToStartPoint:(CGPoint)point;

/**
 *  添加一个点(与上一个点直线相连)
 *
 *  @param point 点
 */
- (void)addLineToPoint:(CGPoint)point;

/**
 *  添加二次贝塞尔曲线
 *
 *  @param point    结束点
 *  @param pointOne 控制点1
 *  @param pointTwo 控制点2
 */
- (void)addCurveToPoint:(CGPoint)point controlPointOne:(CGPoint)pointOne controlPointTwo:(CGPoint)pointTwo;

/**
 *  添加一次贝塞尔曲线
 *
 *  @param point        结束点
 *  @param controlPoint 控制点
 */
- (void)addQuadCurveToPoint:(CGPoint)point controlPoint:(CGPoint)controlPoint;

/**
 *  在指定的区域填充彩色的矩形(此为直接绘制)
 *
 *  @param rect          指定的区域
 *  @param gradientColor 渐变色对象
 */
- (void)drawLinearGradientAtClipToRect:(CGRect)rect gradientColor:(GradientColor *)gradientColor;

#pragma mark - 
/**
 *  添加一个矩形
 *
 *  @param rect
 */
- (void)addRect:(CGRect)rect;

/**
 *  在给定的矩形中绘制椭圆
 *
 *  @param rect
 */
- (void)addEllipseInRect:(CGRect)rect;

/**
 *  将string绘制在指定的点上
 *
 *  @param string     字符串
 *  @param point      点
 *  @param attributes 富文本设置(可以为空)
 */
- (void)drawString:(NSString *)string atPoint:(CGPoint)point withAttributes:(NSDictionary *)attributes;

/**
 *  将string绘制在制定的区域
 *
 *  @param string     字符串
 *  @param rect       区域
 *  @param attributes 富文本设置(可以为空)
 */
- (void)drawString:(NSString *)string inRect:(CGRect)rect withAttributes:(NSDictionary *)attributes;

/**
 *  将富文本绘制在制定的点上
 *
 *  @param string 富文本
 *  @param point  点
 */
- (void)drawAttributedString:(NSAttributedString *)string atPoint:(CGPoint)point;

/**
 *  将富文本绘制在制定的矩形中
 *
 *  @param string 富文本
 *  @param rect   矩形
 */
- (void)drawAttributedString:(NSAttributedString *)string inRect:(CGRect)rect;

@end


//
//  CGContextObject.m
//  DrawRect
//
//  Created by YouXianMing on 15/7/2.
//  Copyright (c) 2015年 YouXianMing. All rights reserved.
//

#import "CGContextObject.h"

@interface CGContextObject ()

@end

@implementation CGContextObject

- (instancetype)initWithCGContext:(CGContextRef)context {
    
    self = [super init];
    if (self) {
        
        self.context = context;
    }
    
    return self;
}

- (void)moveToStartPoint:(CGPoint)point {
    
    if (_context) {
        CGContextMoveToPoint(_context, point.x, point.y);
    }
}

- (void)addLineToPoint:(CGPoint)point {
    
    if (_context) {
        CGContextAddLineToPoint(_context, point.x, point.y);
    }
}

- (void)addCurveToPoint:(CGPoint)point controlPointOne:(CGPoint)pointOne controlPointTwo:(CGPoint)pointTwo {

    if (_context) {
        CGContextAddCurveToPoint(_context, pointOne.x, pointOne.y, pointTwo.x, pointTwo.y, point.x, point.y);
    }
}

- (void)addQuadCurveToPoint:(CGPoint)point controlPoint:(CGPoint)controlPoint {
    
    if (_context) {
        CGContextAddQuadCurveToPoint(_context, controlPoint.x, controlPoint.y, point.x, point.y);
    }
}

- (void)drawLinearGradientAtClipToRect:(CGRect)rect gradientColor:(GradientColor *)gradientColor {
    
    [self saveStateToStack];
    
    
    if (_context) {
        
        CGContextClipToRect(_context, rect);
        
        CGContextDrawLinearGradient(_context,
                                    gradientColor.gradientRef,
                                    gradientColor.gradientStartPoint,
                                    gradientColor.gradientEndPoint, kCGGradientDrawsBeforeStartLocation);
    }
    
    
    [self restoreStateFromStack];
}

- (void)addRect:(CGRect)rect {

    if (_context) {
        CGContextAddRect(_context, rect);
    }
}

- (void)addEllipseInRect:(CGRect)rect {
    
    if (_context) {
        CGContextAddEllipseInRect(_context, rect);
    }
}

- (void)drawString:(NSString *)string atPoint:(CGPoint)point withAttributes:(NSDictionary *)attributes {

    [string drawAtPoint:point withAttributes:attributes];
}

- (void)drawString:(NSString *)string inRect:(CGRect)rect withAttributes:(NSDictionary *)attributes {

    [string drawInRect:rect withAttributes:attributes];
}

- (void)drawAttributedString:(NSAttributedString *)string atPoint:(CGPoint)point {

    [string drawAtPoint:point];
}

- (void)drawAttributedString:(NSAttributedString *)string inRect:(CGRect)rect {

    [string drawInRect:rect];
}

- (void)beginPath {
    
    if (_context) {
        CGContextBeginPath(_context);
    }
}

- (void)closePath {

    if (_context) {
        CGContextClosePath(_context);
    }
}

- (void)strokePath {

    if (_context) {
        CGContextStrokePath(_context);
    }
}

- (void)fillPath {

    if (_context) {
        CGContextFillPath(_context);
    }
}

- (void)strokeAndFillPath {

    if (_context) {
        CGContextDrawPath(_context, kCGPathFillStroke);
    }
}

- (void)drawStrokeBlock:(CGContextObjectDrawBlock_t)block {

    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    [self closePath];
    
    [self strokePath];
}

- (void)drawFillBlock:(CGContextObjectDrawBlock_t)block {
    
    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    [self closePath];
    
    [self fillPath];
}

- (void)drawStrokeAndFillBlock:(CGContextObjectDrawBlock_t)block {

    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    [self closePath];
    
    [self strokeAndFillPath];
}

- (void)drawStrokeBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath {

    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    if (closePath) {
        [self closePath];
    }
    
    [self strokePath];
}

- (void)drawFillBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath {

    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    if (closePath) {
        [self closePath];
    }
    
    [self fillPath];
}

- (void)drawStrokeAndFillBlock:(CGContextObjectDrawBlock_t)block closePath:(BOOL)closePath {

    [self beginPath];
    
    __weak CGContextObject *weakSelf = self;
    
    block(weakSelf);
    
    if (closePath) {
        [self closePath];
    }
    
    [self strokeAndFillPath];
}

- (void)drawImage:(UIImage *)image atPoint:(CGPoint)point {

    [image drawAtPoint:point];
}

- (void)drawImage:(UIImage *)image atPoint:(CGPoint)point blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha {

    [image drawAtPoint:point blendMode:blendMode alpha:alpha];
}

- (void)drawImage:(UIImage *)image inRect:(CGRect)rect {

    [image drawInRect:rect];
}

- (void)drawImage:(UIImage *)image inRect:(CGRect)rect blendMode:(CGBlendMode)blendMode alpha:(CGFloat)alpha {

    [image drawInRect:rect blendMode:blendMode alpha:alpha];
}

- (void)drawImage:(UIImage *)image asPatternInRect:(CGRect)rect {

    [image drawAsPatternInRect:rect];
}

- (void)saveStateToStack {
    
    if (_context) {
        CGContextSaveGState(_context);
    }
}

- (void)restoreStateFromStack {
    
    if (_context) {
        CGContextRestoreGState(_context);
    }
}

#pragma mark - 重写setter,getter方法
@synthesize strokeColor = _strokeColor;
- (void)setStrokeColor:(RGBColor *)strokeColor {

    if (_context) {
        
        _strokeColor = strokeColor;
        CGContextSetRGBStrokeColor(_context, strokeColor.red, strokeColor.green, strokeColor.blue, strokeColor.alpha);
    }
}
- (RGBColor *)strokeColor {

    return _strokeColor;
}

@synthesize fillColor = _fillColor;
- (void)setFillColor:(RGBColor *)fillColor {
    
    if (_context) {
        
        _fillColor = fillColor;
        CGContextSetRGBFillColor(_context, fillColor.red, fillColor.green, fillColor.blue, fillColor.alpha);
    }
}
- (RGBColor *)fillColor {
    
    return _fillColor;
}

@synthesize lineWidth = _lineWidth;
- (void)setLineWidth:(CGFloat)lineWidth {
    
    if (_context) {
        
        _lineWidth = lineWidth;
        CGContextSetLineWidth(_context, lineWidth);
    }
}
- (CGFloat)lineWidth {
    
    return _lineWidth;
}

@synthesize lineCap = _lineCap;
- (void)setLineCap:(CGLineCap)lineCap {
    
    if (_context) {
    
        _lineCap = lineCap;
        CGContextSetLineCap(_context, lineCap);
    }
    
}
- (CGLineCap)lineCap {

    return _lineCap;
}

@end

细节

目录
相关文章
|
4月前
|
缓存 测试技术 API
API的封装步骤流程
API封装流程是一个系统化的过程,旨在将内部功能转化为可复用的接口供外部调用。流程包括明确需求、设计接口、选择技术和工具、编写代码、测试、文档编写及部署维护。具体步骤为确定业务功能、数据来源;设计URL、请求方式、参数及响应格式;选择开发语言、框架和数据库技术;实现数据连接、业务逻辑、错误处理;进行功能、性能测试;编写详细文档;部署并持续维护。通过这些步骤,确保API稳定可靠,提高性能。
|
4月前
|
API PHP
ThinkPHP 通用的API格式封装
本文介绍了在ThinkPHP框架中如何统一封装API返回格式的方法,包括创建状态码枚举类、编写统一格式化函数以及在BaseController和Error控制器中重写`__call`方法来处理不存在的方法或控制器调用,以实现统一的错误处理和返回格式。
ThinkPHP 通用的API格式封装
|
3月前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!
|
5月前
|
人工智能 Serverless API
AI 创业及变现新思路:零门槛 AI 绘图,定制 ComfyUI Serverless API 应用
为了帮助用户高效率、低成本应对企业级复杂场景,本文介绍 ComfyUI API Serverless 版解决方案,通过使用该方案,用户可以充分利用 ComfyUI +Serverless 技术优势快速开发上线 AI 绘画应用,期待为广大开发者 AI 绘画创业及变现提供思路。
|
6月前
|
开发框架 缓存 NoSQL
基于SqlSugar的数据库访问处理的封装,在.net6框架的Web API上开发应用
基于SqlSugar的数据库访问处理的封装,在.net6框架的Web API上开发应用
|
6月前
|
存储 开发框架 前端开发
基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理
基于SqlSugar的开发框架循序渐进介绍(10)-- 利用axios组件的封装,实现对后端API数据的访问和基类的统一封装处理
|
6月前
|
开发框架 前端开发 JavaScript
循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
循序渐进VUE+Element 前端应用开发(13)--- 前端API接口的封装处理
|
6月前
|
文字识别 小程序 安全
印刷文字识别操作报错合集之微信小程序调用API时路径总是返回不对,该如何处理
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
6月前
|
文字识别 前端开发 API
印刷文字识别操作报错合集之通过HTTPS连接到OCR服务的API时报错,该如何处理
在使用印刷文字识别(OCR)服务时,可能会遇到各种错误。例如:1.Java异常、2.配置文件错误、3.服务未开通、4.HTTP错误码、5.权限问题(403 Forbidden)、6.调用拒绝(Refused)、7.智能纠错问题、8.图片质量或格式问题,以下是一些常见错误及其可能的原因和解决方案的合集。
|
6月前
|
开发框架 JSON 前端开发
利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理
利用过滤器Filter和特性Attribute实现对Web API返回结果的封装和统一异常处理