iOS 繪圖使用總結

上一篇介紹了動畫相關的 api,本篇涉及的就是如何把圖形畫出來了,之前也做過不少相關的畫圖工作,但都比較簡單少量,也沒有刻意的去比較或者直接就是接入了第三方庫去實現...工作需要實現大量的 K線繪制以及各種狀態變更,因此總結一下方便查閱,提升工作效率.

image.png

iOS提供了兩套繪圖的框架,UIBezierPathCore Graphics.

  • UIBezierPath是UIKit中的一個關于圖形繪制的類,其實是對Core Graphics框架關于path(CGPathRef數據類型的封裝)的進一步封裝,語法就是 OC 范.
  • Core Graphics也被稱作QuartZ或QuartZ 2D,更接近底層,功能更強大, 提供的都是C語言的函數接口.

Core Graphics

在繪圖之前,我們先需要搞清楚下面幾個概念:

  1. CGContextRef
    圖形上下文,可以理解為畫布/畫板,我們要畫畫首先需要一個載體吧,比如電腦繪圖我們會創建一個空白畫布,生活中畫畫我們會先準備好畫板,否則是無法進行繪制的.
    通常我們通過以下2種方法來獲取這個context:
  • drawRect:(CGRect)rect:
    重寫UIView的drawRect:方法,調用UIGraphicsGetCurrentContext()即可獲得圖形上下文,在其他地方調用獲得的圖形上下文總是nil,因為在drawRect之前,系統會往棧里面壓入一個valid的CGContextRef.
    ps(*):drawRect:方法在view第一次顯示的時候會自動調用(如果不設置 frame, 那么默認的第一次也不會調用),當你手動重畫這個View時,不能手動顯示調用,必須通過調用setNeedsDisplay或者setNeedsDisplayInRect,讓系統自動調該方法.
    ps:drawLayer:(CALayer*)layer inContext:(CGContextRef)ctx要注意圖層代理對象的設定,具體可以參考iOS 繪圖教程的第三種繪圖形式.

  • UIGraphicsBeginImageContextWithOptions(<#CGSize size#>, <#BOOL opaque#>, <#CGFloat scale#>)
    -- CGSize size:指定將來創建出來的view的大小;
    -- BOOL opaque:設置透明YES代表透明,NO代表不透明;
    -- CGFloat scale:代表縮放,0代表不縮放.
    如果想在drawRect之外獲得context怎么辦?那只能自己創建位圖上下文了.
    調用UIGraphicsBeginImageContextWithOptions函數就可獲得用來處理圖片的圖形上下文,利用該上下文,你就可以在其上進行繪圖,并生成圖片.調用UIGraphicsGetImageFromCurrentImageContext函數可從當前上下文中獲取一個UIImage對象.記住在你所有的繪圖操作后別忘了調用UIGraphicsEndImageContext函數關閉圖形上下文(類似于數據庫的打開與關閉)。UIGraphicsBeginImageContextWithOptionsUIGraphicsEndImageContext成對出現,類似的 api 還有很多,也可以嵌套.

  1. CGContextSaveGState/CGContextRestoreGState
    CGContextSaveGState用于記錄和CGContextRestoreGState用于恢復已存儲的繪圖上下文.
    獲取圖形上下文之后,這時你開始畫圖的下一步準備工作,比如定畫筆的顏色,文本的顏色,字體的大小/型號,然后開始作畫.當你畫到一半的時候,你需要更改這些配置,也就是用特定的顏色/字體等繪制一個特殊的圖形,完成之后又回到最初的圖形.
    是不是有點繞...
    @舉個栗子:
    我要畫三根線,先畫一根寬度為2的紅線,然后畫一根寬度為5的黃線,最后再畫一根寬度為2的紅線.
- (void)drawRect:(CGRect)rect {

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //第一條線
    CGContextSetStrokeColorWithColor(ctx, [UIColor redColor].CGColor);
    CGContextSetLineWidth(ctx, 2.0f);
    CGContextMoveToPoint(ctx, 10, 30);
    CGContextAddLineToPoint(ctx, 10, 100);
    CGContextStrokePath(ctx);

    //第二條線
    CGContextSaveGState(ctx); //   ----- 看這里
    CGContextSetStrokeColorWithColor(ctx, [UIColor yellowColor].CGColor);
    CGContextSetLineWidth(ctx, 5.0f);
    CGContextMoveToPoint(ctx, 50, 30);
    CGContextAddLineToPoint(ctx, 50, 100);
    CGContextStrokePath(ctx);
    CGContextRestoreGState(ctx); // ---- 看這里
    
    //第三條線
    CGContextMoveToPoint(ctx, 110, 30);
    CGContextAddLineToPoint(ctx, 110, 100);
    CGContextStrokePath(ctx);
}

大家可以試試,如果把上面代碼標記了"看這里"的兩句刪掉,會是什么結果?

631504601986_.pic.jpg

加上這兩句才是正確的:
621504601986_.pic.jpg

可以看到,CGContextSaveGState存儲下來了當前紅色和寬度為2的線條狀態,然后切換顏色到黃色和5寬度的狀態畫線(你也可以畫圈/畫矩形, LZ 我偷懶),然后在CGContextRestoreGState恢復到了紅色和默認的線條狀態進行畫,這個就是存儲當前繪制狀態的意思.
總結:所以這2個 api 可以理解為,保存當前的上下文拷貝,變化一個樣子出去玩耍一下,結束之后又通過之前保存的拷貝復位.


3.UIGraphicsPushContext/UIGraphicsPopContext
UIGraphicsPushContext用于完全更改圖形上下文和UIGraphicsPopContext恢復之前的圖形上下文.
UI開頭的 api 也可以看出,它的使用與 UIKit 繪圖相關聯.

  • 假設你正在當前圖形上下文中繪制 A,這時想要在位圖上下文中繪制完全不同的B并且使用UIKit來進行任意繪圖,這時你需要切換到一個全新的繪圖上下文中并且想要保存當前的圖形上下文,包括所有已經繪制的內容,那么就需要調用UIGraphicsPushContext來將圖形上下文入棧.
  • 等繪制完B后,再調用UIGraphicsPopContext將之前的圖形上下文出棧.

ps(*):這種情況只會在要使用UIKit在新的位圖上下文中繪圖時才會發生,只要你使用的是Core Graphics繪制,就不需要去執行上下文入棧和出棧,Core Graphics函數將上下文視作參數。引用iOS --- CoreGraphics中三種繪圖context切換方式的區別總結的一句話:繪圖context切換的關鍵是:要看切換新的繪圖context后,是要繼續使用CoreGraphics繪制圖形,還是要使用UIKit。

4.常用的一些 API

- (void)test {
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    // 設置畫線的起點 為 (50,30)
    CGContextMoveToPoint(ctx, 50, 30);
    // 繪制直線連線, 從起點延伸到 (10,100)
    CGContextAddLineToPoint(ctx, 10, 100);
    // 繪制矩形 從(50,30)開始, 寬度高度均為50
    CGContextAddRect(ctx, CGRectMake(50, 30, 50, 50));
    // 繪制/渲染圖形
    CGContextStrokePath(ctx); // stroke 是描線 ,而 fill 是填充,單純線條下 fill 不會工作
    CGContextFillPath(ctx); // 填充
    // 設置線條的寬度
    CGContextSetLineWidth(ctx, 5.0f);
    // 設置線條顏色 -- 注意與 fill 的區別
    CGContextSetStrokeColorWithColor(ctx, [UIColor yellowColor].CGColor);
    [[UIColor yellowColor] setStroke];
    // 設置填充顏色
    CGContextSetFillColorWithColor(ctx, [UIColor yellowColor].CGColor);
    [[UIColor yellowColor] setFill];
    /** 線條交匯處樣式
        kCGLineJoinMiter——尖角
        kCGLineJoinBevel——平角
        kCGLineJoinRound——圓形
     **/
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    // 繪制虛線,第二個參數為初始跳過幾個點開始繪制,第三個參數為一個CGFloat數組,指定你繪制的樣式,繪幾個點跳幾個點(下面為繪10個點,跳過5個,最后一個參數是上個參數數組元素的個數。
    CGContextSetLineDash(ctx, 0, (CGFloat[]){10, 5}, 2);
    // 默認系統會繪制填充這個矩形內部的最大橢圓,若矩形為正方形,則為圓
    CGContextAddEllipseInRect(ctx, CGRectMake(40, 180, 240, 120));
    // 畫切線弧,是說從 起點(50,30)到(100,80)畫一條線,然后再從(100,80)到(130,150)畫一條線,從這兩條線(無限延伸的)和 半徑 50 可以確定一條弧,
    CGContextAddArcToPoint(ctx,100,80,130,150,50);
    /** 繪制圓弧,餅狀圖() -- 畫圓的時候可通過 線條寬度 來實現中間空心圓效果
    void CGContextAddArc (
                          CGContextRef c,
                          CGFloat x, //  圓心點坐標的x和y
                          CGFloat y,
                          CGFloat radius, // 半徑
                          CGFloat startAngle, //  繪制起始點的弧度值,一般在IOS繪圖里都使用弧度這個概念 #define RADIANS(x) ((x)*(M_PI)/180)  // 角度轉弧度
                          CGFloat endAngle, // 繪制終點的弧度值
                          int clockwise       // 1為順時針,0為逆時針。
                          );
     **/
    CGContextAddArc(ctx, 100, 100, 10, ((60.0)*(M_PI)/180), ((270.0)*(M_PI)/180), 0);
    
    /* 裁剪當前路徑 -- 參照: http://blog.sina.com.cn/s/blog_b876b8ab0102v6gb.html */
    // 使用非零繞數規則。
    CGContextClip(ctx);
    // 使用奇偶規則。
    CGContextEOClip(ctx);
    //CGContextClipToRect
    //CGContextClipToRects
    //CGContextGetClipBoundingBox
    //CGContextClipToMask
    /* 裁剪當前路徑 */
    
    /* 構造路徑 -- 類似于后面的要講的 UIBezierPath */
    // 創建一個 path 對象
    CGMutablePathRef path = CGPathCreateMutable();
    // 將路徑加入到圖形上下文中
    CGContextAddPath(ctx, path);
    // 制作具體路線 -- 上面兩步其實可以省略
    CGPathMoveToPoint(path, NULL, 10, 10);
    CGPathAddLineToPoint(path, NULL, 100, 100);
    CGPathMoveToPoint(path, NULL, 20, 20);
    CGPathAddLineToPoint(path, NULL, 200, 200);
    // 渲染/繪制,并且可以設置繪制的類型
    /*CGPathDrawingMode是填充方式,枚舉類型
     kCGPathFill:只有填充(非零纏繞數填充),不繪制邊框
     kCGPathEOFill:奇偶規則填充(多條路徑交叉時,奇數交叉填充,偶交叉不填充)
     kCGPathStroke:只有邊框
     kCGPathFillStroke:既有邊框又有填充
     kCGPathEOFillStroke:奇偶填充并繪制邊框
     */
    CGContextDrawPath(ctx, kCGPathFillStroke);  // 等價于 CGContextStrokePath + CGContextFillPath
    // 釋放資源 -- ARC 并不能處理這類的資源管理,必須手動釋放
    CGPathRelease(path);
    /* 構造路徑 -- 類似于后面的要講的 UIBezierPath */
    
    // 封閉路徑,不需要一定設置路徑的終點,可以主動關閉
    /*
     1.起始與終點重合的直線、弧和曲線并不自動閉合路徑,我們必須調用CGContextClosePath來閉合路徑。
     2.Quartz的一些函數將路徑的子路徑看成是閉合的。這些函數顯示地添加一條直線來閉合 子路徑,如同調用了CGContextClosePath函數。
     3.在閉合一條子路徑后,如果程序再添加直線、弧或曲線到路徑,Quartz將在閉合的子路徑的起點開始創建一個子路徑。
     */
    CGContextClosePath(ctx);
    // 明確閉合路徑
    CGPathCloseSubpath(path);
    // 設置陰影 -- 參數依此是:圖形上下文,偏移量(CGSize),模糊值,陰影顏色
    CGContextSetShadowWithColor(ctx, CGSizeMake(10, 10), 20.0f, [[UIColor grayColor] CGColor]);
    
    /* 繪制漸變色效果 -- 亦可以 CAGradientLayer 鏈接:https://zsisme.gitbooks.io/ios-/content/chapter6/cagradientLayer.html*/
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    // 創建一個漸變的色值 1:顏色空間 2:漸變的色數組 3:位置數組,如果為NULL,則為平均漸變,否則顏色和位置一一對應 4:位置的個數
    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, (CGFloat[]){
        // 如果想知道一個顏色比如[UIColor purpleColor]具體構成 -> CGColorGetComponents([UIColor purpleColor].CGColor); 返回一個數組,包括R,G,B以及alpha的值
        0.3, 0.2, 0.2, 1.0,
        0.1, 0.5, 0.2, 1.0,
        0.6, 0.2, 0.7, 1.0
    }, (CGFloat[]){
        0.0, 0.5, 1.0
    }, 3);
    // 繪制漸變, 顏色的0對應start點,顏色的1對應end點,第四個參數是定義漸變是否超越起始點和終止點
    CGContextDrawLinearGradient(ctx, gradient, CGPointMake(100, 300), CGPointMake(220, 480), 0);
    /* 輻射漸變 有興趣的可以去玩一哈...
     void CGContextDrawRadialGradient(
     CGContextRef context,
     CGGradientRef gradient, //先創造一個CGGradientRef,顏色是白,黑,location分別是0,1
     CGPoint startCenter, // 白色的起點(中心圓點)
     CGFloat startRadius, // 起點的半徑,這個值多大,中心就是多大一塊純色的白圈
     CGPoint endCenter, // 白色的終點(可以和起點一樣,不一樣的話就像探照燈一樣從起點投影到這個終點,按照你的意圖應該和startCenter一樣
     CGFloat endRadius, //終點的半徑, 按照你的意圖應該就是從中心到周邊的長
     CGGradientDrawingOptions options //應該是 kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation
     );
     */
    // 釋放資源
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
    /* 繪制漸變色效果 */
    
    // 繪制二次貝塞爾曲線
    CGContextMoveToPoint(ctx, 20, 100);//移動到起始位置
    /*
     c:圖形上下文
     cpx:控制點x坐標
     cpy:控制點y坐標
     x:結束點x坐標
     y:結束點y坐標
     */
    CGContextAddQuadCurveToPoint(ctx, 160, 0, 300, 100);
    
    // 繪制三次貝塞爾曲線
    CGContextMoveToPoint(ctx, 20, 500);
    /*
     c:圖形上下文
     cp1x:第一個控制點x坐標
     cp1y:第一個控制點y坐標
     cp2x:第二個控制點x坐標
     cp2y:第二個控制點y坐標
     x:結束點x坐標
     y:結束點y坐標
     */
    CGContextAddCurveToPoint(ctx, 80, 300, 240, 500, 300, 300);
    // 檢測當前的路徑是否包含指定的點
    bool isExit = CGContextPathContainsPoint(ctx, CGPointMake(100, 100), kCGPathFill);
    // 題外話..
    [@"繪制字符串" drawAtPoint:CGPointMake(0, 0) withAttributes:@{NSFontAttributeName : [UIFont systemFontOfSize:[UIFont systemFontSize]]}];
}

ps(*):輔助點 ---------------------------------------------

UIBezierPath+CAShapeLayer

前面介紹過,UIBezierPath是對CGPathRef數據類型的封裝.在 drawRect :中,無須獲取圖形上下文,直接用UIBezierPath創建路徑來繪制,比如:

- (void)drawRect:(CGRect)rect{
     // 顏色
    [[UIColor orangeColor] set];
    UIBezierPath* path = [UIBezierPath bezierPath];
    path.lineWidth     = 5.f;
    // 起點
    [path moveToPoint:CGPointMake(10, 100)];
    // 繪制線條
    [path addLineToPoint:CGPointMake(100, 20)];
    // 繪制渲染
    [path stroke];
}

不過,一般,UIBezierPath配合CAShapeLayer一起使用.UIBezierPath給CAShapeLayer提供路徑,CAShapeLayer在提供的路徑中進行渲染,繪制出了Shape.
使用CAShapeLayer有以下一些優點:

  • 渲染快速.CAShapeLayer使用了硬件加速,繪制同一圖形會比用Core Graphics快很多。
  • 高效使用內存.一個CAShapeLayer不需要像普通CALayer一樣創建一個寄宿圖形,所以無論有多大,都不會占用太多的內存.
  • 不會被圖層邊界剪裁掉.一個CAShapeLayer可以在邊界之外繪制。你的圖層路徑不會像在使用Core Graphics的普通CALayer一樣被剪裁掉.
  • 不會出現像素化。當你給CAShapeLayer做3D變換時,它不像一個有寄宿圖的普通圖層一樣變得像素化.

CAShapeLayer繼承自CALayer,常用屬性:

    path:CGPathRef類型,配合 UIBezierPath 的 path
    fillColor:填充path的顏色,或無填充。默認為不透明黑色。動畫的。
    strokeColor:繪制的線條的顏色。
    fillRule:填充path的規則。非零和偶奇。同CGPathDrawingMode
    lineCap:線端點類型,同CGContextSetLineJoin
    lineDashPattern:線性模版,這是一個NSNumber的數組,索引從1開始記,奇數位數值表示實線長度,偶數位數值表示空白長度。
    lineDashPhase:線型模版的起始位置。
    lineJoin:線拐點類型。kCALineJoinMiter-尖的,kCALineJoinRound-圓弧,kCALineJoinBevel-梯形
    lineWidth:線寬
    miterLimit:最大斜接長度。斜接長度指的是在兩條線交匯處和外交之間的距離。只有lineJoin屬性為kCALineJoinMiter時miterLimit才有效。邊角的角度越小,斜接長度就會越大。為了避免斜接長度過長,我們可以使用miterLimit屬性。如果斜接長度超過miterLimit的值,邊角會以lineJoin的“bevel”即kCALineJoinBevel類型來顯示。
    strokeStart和strokeEnd:部分繪線,都是0.0~1.0的取值范圍.經常被用來制作動畫效果。

再來看看UIBezierPath:是不是跟之前的 CG 很像

    // 創建基本路徑
    + (instancetype)bezierPath;
    // 創建矩形路徑
    + (instancetype)bezierPathWithRect:(CGRect)rect;
    // 創建橢圓路徑
    + (instancetype)bezierPathWithOvalInRect:(CGRect)rect;
    // 創建圓角矩形
    + (instancetype)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius; // rounds all corners with the same horizontal and vertical radius
    // 創建指定位置圓角的矩形路徑
    + (instancetype)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
    // 創建弧線路徑
    + (instancetype)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
    // 通過CGPath創建
    + (instancetype)bezierPathWithCGPath:(CGPathRef)CGPath;

    // 與之對應的CGPath,可賦值給 CAShapeLayer 的 path
    @property(nonatomic) CGPathRef CGPath;
    // 是否為空
    @property(readonly,getter=isEmpty) BOOL empty;
    // 整個路徑相對于原點的位置及寬高
    @property(nonatomic,readonly) CGRect bounds;
    // 當前畫筆位置
    @property(nonatomic,readonly) CGPoint currentPoint;
    // 線寬
    @property(nonatomic) CGFloat lineWidth;
    // 終點類型,同 CAShapeLayer
    @property(nonatomic) CGLineCap lineCapStyle;
    // 線條拐點的類型, 同 CAShapeLayer
    @property(nonatomic) CGLineJoin lineJoinStyle;
    // 兩條線交匯處內角和外角之間的最大距離, 同 CAShapeLayer
    @property(nonatomic) CGFloat miterLimit;
    // 繪線的精細程度,默認為0.6,數值越大,需要處理的時間越長
    @property(nonatomic) CGFloat flatness;
    // 決定使用even-odd(奇偶)或者non-zero(非零環繞)規則
    @property(nonatomic) BOOL usesEvenOddFillRule;
    // 反方向繪制path
    - (UIBezierPath *)bezierPathByReversingPath;
    // 設置畫筆起始點
    - (void)moveToPoint:(CGPoint)point;
    // 從當前點到指定點繪制直線
    - (void)addLineToPoint:(CGPoint)point;
    // 添加弧線, 同 CG
    - (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise NS_AVAILABLE_IOS(4_0);
    // 添加二次貝塞爾曲線, 同 CG
    - (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
    // 添加三次貝塞爾曲線, 同 CG
    - (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
    // 閉合路徑,得到封閉圖形
    - (void)closePath;
    // 移除所有的點,刪除所有的subPath
    - (void)removeAllPoints;
    // 將bezierPath添加到當前path
    - (void)appendPath:(UIBezierPath *)bezierPath;
    // 填充
    - (void)fill;
    // 繪制/渲染,描繪線條
    - (void)stroke;
    // 在這以后的圖形繪制超出當前路徑范圍則不可見
    - (void)addClip;

參考鏈接

iOS 繪圖教程
iOS核心動畫教程之CAShapeLayer
CoreGraphics之CGContextSaveGState與UIGraphicsPushContext
iOS --- CoreGraphics中三種繪圖context切換方式的區別
iOS開發系列--打造自己的“美圖秀秀”
關于CAShapeLayer
iOS繪圖 - UIBezierPath水波
動畫黃金搭檔:CADisplayLink & CAShapeLayer

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容

  • Core Graphics Framework是一套基于C的API框架,使用了Quartz作為繪圖引擎。它提供了低...
    ShanJiJi閱讀 1,561評論 0 20
  • 原文地址:http://www.cocoachina.com/industry/20140115/7703.htm...
    默默_David閱讀 6,131評論 0 1
  • 目錄: 主要繪圖框架介紹 CALayer 繪圖 貝塞爾曲線-UIBezierPath CALayer子類 補充:i...
    Ryan___閱讀 1,692評論 1 9
  • winnn閱讀 204評論 0 0
  • 文學作品翻譯:張愛玲-《寫什么》英譯_英漢翻譯素材 - 可可英語 2016年10月1日 1、翻譯變成每天一句,都沒...
    123逍遙游閱讀 609評論 0 1