Quartz2D詳解

Quartz2D 簡介及用途

  • Quartz 2D 是一個二維繪圖引擎,同時支持iOS和Mac系統,Quartz2D的API是純C語言的來自于Core Graphics框架

  • Quartz 2D 能完成的工作:
    1 繪制圖層:線條,三角形,矩形,圓,弧,扇形等
    2 繪制文字
    3 繪制圖片
    4 讀取生成PDF
    5 截圖,裁剪圖片
    6 自定義UI控件

  • Quartz 2D實力
    1 裁剪圖片
    2 涂鴉、畫板
    3 手勢解鎖
    4 折線圖、餅狀圖、柱狀圖

  • 通常在我們面對比較復雜,個性化的UI需求時,通常利用Quartz 2D通過自定義View的方法繪制出我們需要的UI

圖形上下文

  • 如何利用Quartz 2D技術自定義繪制View
    1 首先,得有圖形上下文,因為它能保存繪圖信息,并且決定著繪制到什么地方去
    2 其次,那個圖形上下文必須跟view相關聯,才能將內容繪制到view上面

  • 自定義View的步驟
    1 新建一個類,繼承自UIView
    2 實現- (void)drawRect:(CGRect)rect方法,然后在這個方法中

    • 取得跟當前view相關聯的圖形上下文
    • 繪制相應的圖形內容
    • 利用圖形上下文將繪制的所有內容渲染顯示到view上面

drawRect:方法

  • 只有在在drawRect:方法中才能取得跟view相關聯的圖形上下文
  • 當view第一次顯示到屏幕上時(被加到UIWindow上顯示出來)調用
  • 手動調用view的setNeedsDisplay或者setNeedsDisplayInRect:時
  • 注意手動 [self drawRect] 是無效的寫法

繪圖方法介紹

  • 畫圖步驟
    1 獲取上下文
    2 創建路徑(描述路徑)
    3 把路徑添加到上下文
    4 渲染上下文
  • 畫直線(方法一)
-(void)drawRect:(CGRect)rect{
    //1.獲取圖形上下文
    //目前我們所用的上下文都是以UIGraphics
    //CGContextRef Ref :引用 CG 目前使用到的類型和函數一般都是CG開頭
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    //2.描述路徑
    //創建路徑
    CGMutablePathRef path = CGPathCreateMutable();
    
    //設置起點
    //path 給那個路徑設置起點
    
    CGPathMoveToPoint(path, NULL, 50, 50);
    
    //添加一根線到某個點
    CGPathAddLineToPoint(path, NULL, 200, 200);
    
    //3.把路徑添加到上下文
    
    CGContextAddPath(ctx, path);
    
    //4.渲染上下文
    
    CGContextStrokePath(ctx);

}
  • 畫直線(方法二)
-(void)drawRect:(CGRect)rect{
    //獲取上下文 自動創建路徑
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //描述路徑
    //設置起點
    CGContextMoveToPoint(ctx, 50, 50);
    
    CGContextAddLineToPoint(ctx, 200, 200);
    //渲染上下文
    CGContextStrokePath(ctx);

}
  • 畫直線(方法三)
-(void)drawRect:(CGRect)rect{

    //UIKIT 封裝的繪圖功能
    //貝斯曲線
    //創建路徑
    UIBezierPath * path = [UIBezierPath bezierPath];
    
    //設置起點
    [path moveToPoint:CGPointMake(50, 50)];
    //添加一個線到某個點
    [path addLineToPoint:CGPointMake(100, 100)];
    //繪制路徑
    
    [path stroke];
}
  • 設直線的狀態
原生設置線的狀態
-(void)drawRect:(CGRect)rect{
    //畫兩根線
    //獲取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //描述路徑
    //設置起點
    CGContextMoveToPoint(ctx, 50, 100);
    
    CGContextAddLineToPoint(ctx, 100, 100);
    //默認下一個線的起點就是上一根線的重點 不用重新設置
    CGContextAddLineToPoint(ctx, 100, 150);
    
    //設置繪圖狀態 在渲染之前
    //color
    [[UIColor greenColor] setStroke];
    
    //線寬
    CGContextSetLineWidth(ctx, 10);
    //鏈接樣式
    /**
     *kCGLineJoinMiter,切角
     *kCGLineJoinRound,圓角
     *kCGLineJoinBevel
     */
    CGContextSetLineJoin(ctx, kCGLineJoinRound);
    //    kCGLineCapButt,
    //    kCGLineCapRound,
    //    kCGLineCapSquare
    //設置頂角樣式
    CGContextSetLineCap(ctx, kCGLineCapRound);
    
    //渲染上下文
    CGContextStrokePath(ctx);

}

  • 貝斯曲線(貝瑟爾曲線)
//貝斯 畫線 設置線的狀態
-(void)drawRect:(CGRect)rect{
    //貝斯曲線設置圖形上下文狀態
    //為了方便管理狀態 最好一個線對應一個路徑
    UIBezierPath * path = [UIBezierPath bezierPath];
    //設置起點
    [path moveToPoint:CGPointMake(50, 100)];
    //設置終點
    [path addLineToPoint:CGPointMake(100, 100)];
    //線寬
    path.lineWidth = 10;
    //繪制
    [path stroke];
    
    UIBezierPath * path1 = [UIBezierPath bezierPath];
    
    [path1 moveToPoint:CGPointMake(100, 100)];
    
    [path1 addLineToPoint:CGPointMake(100, 150)];
    
    path1.lineWidth = 5;
    
    [path1 stroke];

}
  • 畫曲線
-(void)drawRect:(CGRect)rect{
    //繪制曲線
    //獲取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //描述路徑
    //設置起點
    CGContextMoveToPoint(ctx, 50, 100);
    
    //cpx cpy 控制點的橫縱坐標和終點坐標
    CGContextAddQuadCurveToPoint(ctx, 75, 50, 100, 100);
    
    CGContextStrokePath(ctx);

}
  • 畫圖形

    • 圓角矩形
//圓角矩形
       UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(10, 10, 100, 100) cornerRadius:50];
    
        //[path stroke];
        //填充(必須是一個封閉路徑)
        [path fill];
  • 橢圓
      //橢圓
          UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(50, 50, 50, 100)];
        //填充(必須是一個封閉路徑)
         [path fill];
  • 畫一個圓弧
//畫一個圓弧
       //    Center 圓心
//    startAngle 起點
//    半徑radius
//    endAngle 弧度
//    clockwise 順時針 逆時針
        UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:50 startAngle:0 endAngle:M_PI clockwise:YES];
        [path stroke];
  • 畫扇形
//畫扇形
       UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(100, 100) radius:50 startAngle:0 endAngle:M_PI_2 clockwise:YES];
    //添加一根線到圓心
    [path addLineToPoint:CGPointMake(100, 100)];
    //關閉路徑
//        [path closePath];
    //渲染
    //    [path stroke];
    //默認關閉路徑
    [path fill];
  • 畫餅狀圖
//畫餅狀圖
- (void)drawRect:(CGRect)rect {

    NSArray * arr = @[@(25),@(25),@(50)];
    
    NSArray * colorArr = @[
                           [UIColor redColor],
                           [UIColor purpleColor],
                           [UIColor greenColor]
                           ];

    CGFloat radius = rect.size.width*0.5;
    
    CGPoint center = CGPointMake(radius, radius);
    
    CGFloat startAngle = 0;
    CGFloat angle = 0;
    CGFloat endAngle = 0;

    for (int i = 0; i <arr.count; i++) {
  
        startAngle = endAngle;
        
        angle = [arr[i] doubleValue]/100.0 * M_PI * 2;
        
        endAngle = startAngle + angle;
          
        UIBezierPath * path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES];
        
        [path addLineToPoint:center];
        
        UIColor * color = colorArr[i];
        
        [color set];
        
        [path fill];

    }

}
  • 畫柱狀圖
- (void)drawRect:(CGRect)rect {

    NSArray * arr = @[@(25),@(25),@(50)];
    NSArray * colorArr = @[
                           [UIColor redColor],
                           [UIColor purpleColor],
                           [UIColor greenColor]
                           ];

    CGFloat x = 0;
    CGFloat y = 0;
    CGFloat w = 0;
    CGFloat h = 0;
    for (int i = 0 ; i<arr.count; i++) {
        
        w = rect.size.width/ (2* arr.count-1);
        x = 2 * w * i;
        h = [arr[i] doubleValue]/100.0 *rect.size.height;
        y = rect.size.height - h;
        
        UIBezierPath * path = [UIBezierPath bezierPathWithRect:CGRectMake(x, y, w, h)];
        
        UIColor * color = colorArr[i];
        
        [color set];
        
        [path fill];

    }
      
}

  • 繪制文字
//繪制文字
-(void)drawRect:(CGRect)rect{

    NSString * text = @"嘿嘿嘿嘿嘿嘿嘿";
    
    NSMutableDictionary * textDict = [NSMutableDictionary dictionary];
    //設置字體顏色
    textDict[NSForegroundColorAttributeName] = [UIColor redColor];
    //設置字體大小
    textDict[NSFontAttributeName]  = [UIFont systemFontOfSize:30];
    //設置字體空心顏色和寬度
    textDict[NSStrokeWidthAttributeName] = @(3);
    
    textDict[NSStrokeColorAttributeName] = [UIColor yellowColor];
    
    //創建shadow
    NSShadow * shadow = [[NSShadow alloc]init];
    shadow.shadowColor = [UIColor greenColor];
    shadow.shadowOffset = CGSizeMake(4, 4);
    textDict[NSShadowAttributeName] = shadow;
    //繪制文字 不會換行
    //[text drawAtPoint:CGPointZero withAttributes:textDict];
    //可以換行
    [text drawInRect:self.bounds withAttributes:textDict];

}

  • 繪制圖片
- (void)drawRect:(CGRect)rect {
  
    // 超出裁剪區域的內容全部裁剪掉
    // 注意:裁剪必須放在繪制之前
    UIRectClip(CGRectMake(0, 0, 50, 50));
    
    UIImage *image = [UIImage imageNamed:@"001"];
    //繪圖
    // 默認繪制的內容尺寸跟圖片尺寸一樣大
    //    [image drawAtPoint:CGPointZero];
    //圖片在rect內展示
    //    [image drawInRect:rect];
    // 圖片平鋪
    [image drawAsPatternInRect:rect];
    
}
  • 矩陣操作
-(void)drawRect:(CGRect)rect{

    //獲得上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //設置路徑
    UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, rect.size.width, rect.size.height/2)];
    
    [[UIColor redColor] set];
    
    //上下文的矩陣操作
    //矩陣操作必須在添加路徑之前
    //向下平移
    CGContextTranslateCTM(ctx, 50, 50);
    //縮放
    CGContextScaleCTM(ctx, 0.5, 0.5);
    //旋轉
    CGContextRotateCTM(ctx, M_PI_4);

    //把路徑添加到上下文
    CGContextAddPath(ctx, path.CGPath);
    //渲染上下文
    CGContextFillPath(ctx);

}

位圖上下文

  • 圖片水印
    • 有時候防止自己的圖片被盜圖,經常在圖片右下角加上自己的水印


      水印.jpeg
//創建一個imageview
    UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 558)];
    imageView.center = self.view.center;
    [self.view addSubview:imageView];

    UIImage * image = [UIImage imageNamed:@"小黃人"];
    //圖片加水印
    //繪制圖片到新的圖片上 需要用到位圖上下文
    //位圖上下文回去方式跟layer上下文不一樣,位圖上下文需要我們手動創建
    //開啟一個位圖上下文,注意位圖上下文跟view無關,所以不需要在drawRect方法中實現
    //size:位圖上下文的尺寸(新圖片的尺寸)
    //opaque:不透明度 YES不透明,NO透明,通常都是透明的上下文
    //scale通常不需要縮放上下文,取值為0 表示不縮放
    UIGraphicsBeginImageContextWithOptions(image.size, NO, 0);
    //1繪制原生圖片
    [image drawAtPoint:CGPointZero];
    //2給原生圖片添加文字水印
    NSString * str = @"黑黑";
    //創建字典屬性
    NSMutableDictionary * textDic = [NSMutableDictionary dictionary];
    textDic[NSForegroundColorAttributeName] = [UIColor purpleColor];
    textDic[NSFontAttributeName] = [UIFont boldSystemFontOfSize:20];
    [str drawAtPoint:CGPointMake(200, 528) withAttributes:textDic];
    //3生成一張圖片 (從上下文中獲取)
    UIImage * imageWater = UIGraphicsGetImageFromCurrentImageContext();
    //關閉上下文
    UIGraphicsEndImageContext();
    imageView.image = imageWater;
  • 圖片裁剪
    • APP中常見的圓形頭像,以及,頭像上的一層圓形的圈圈


      圖片裁剪.jpeg
//創建一個imageview
    UIImageView * imageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 200, 200)];
    imageView.center = self.view.center;
    [self.view addSubview:imageView];
    //加載圖片
    UIImage * image = [UIImage imageNamed:@"阿貍頭像"];
    //圖片寬高
    CGFloat imageWH = image.size.width;
    //設置圓環的寬度
    CGFloat border = 1;
    //圓形的寬高
    CGFloat ovalWH = imageWH + 2 * border;
    //1開啟個上下文
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(ovalWH, ovalWH), NO, 0);
    //2畫大圓
    UIBezierPath * path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, ovalWH, ovalWH)];
    [[UIColor redColor] set];
    [path fill];
    //3設置裁剪區域(小圓)
    UIBezierPath * clipPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(border, border, imageWH, imageWH)];
    //進行裁剪
    [clipPath addClip];
    //4繪制圖片
    [image drawAtPoint:CGPointMake(border, border)];
    //5獲取圖片
    UIImage * clipImage = UIGraphicsGetImageFromCurrentImageContext();
    //6關閉上下文
    UIGraphicsEndImageContext();
    imageView.image = clipImage;
  • 屏幕截屏功能
    • 截取的是一個View的layer層 并不是一個圖片,要與圖片截取區分
//開啟一個位圖上下文
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
    //拿到上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //把控件上的圖層渲染到上下文
    [self.view.layer renderInContext:ctx];
    //不能用下面這個方法 layer 只能渲染
    //    [self.view.layer drawInContext:ctx];
    //生成一張圖片
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
  • 圖片截取
    • 滑動手指出現矩形截圖框

    • 截圖時.jpeg
    • 松開手指截圖成功

    • 截圖后.jpeg
    • 截取的是imageView的layer層與上面的方法區分

    • 在imageView上添加pan手勢

    • 觸發方法

-(void)pan:(UIPanGestureRecognizer *)pan{
CGPoint endP = CGPointZero;
    if(pan.state == UIGestureRecognizerStateBegan){
        
        //獲取手指最開始的觸摸點
        CGPoint startP = [pan locationInView:self.view];
        self.startP = startP;
        
    }else if (pan.state == UIGestureRecognizerStateChanged){
        
        endP = [pan locationInView:self.view];
        
        CGFloat w = endP.x -self.startP.x;
        CGFloat h = endP.y - self.startP.y;
        //獲取截圖
        CGRect clipRect = CGRectMake(self.startP.x, self.startP.y, w, h);
        //創建view 黑色半透明
        self.clipView.frame = clipRect;
        
    }else if (pan.state == UIGestureRecognizerStateEnded){
        
        //開啟一個原圖一樣大的位圖上下文
        UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0);
        //設置裁剪區域
        UIBezierPath * clipPath = [UIBezierPath bezierPathWithRect:self.clipView.frame];
        //進行裁剪
        [clipPath addClip];
        //獲取上下文
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        //繪制圖片
        [self.imageView.layer renderInContext:ctx];
        //從上下文獲取裁剪區域
        UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
        self.imageView.image = image;
        //        self.imageView.backgroundColor = [UIColor redColor];
        
        UIGraphicsEndImageContext();
        //截取的view設置為nil
        [_clipView removeFromSuperview];
        _clipView = nil; 
    }
}
  • 圖片擦除
    • 兩張類似圖片重疊防止,一張完整的圖片在上,另一張被擦除一部分的圖片在下,通過位圖上下文擦除上面的圖片漏出下面的完整的圖片造成假象。
  • 擦除前(害羞的美女)
  • 擦除前.jpeg
  • 擦除后(想不想繼續扒光她)
  • 擦除后.jpeg
  • 在上面的圖片添加一個pan手勢,實現pan的觸發方法
-(void)pan:(UIPanGestureRecognizer *)pan{
CGPoint curP = [pan locationInView:self.view];
    CGFloat wh = 50;
    CGFloat x = curP.x - 0.5 * wh;
    CGFloat y = curP.y - 0.5 * wh; 
    CGRect rect = CGRectMake(x, y, wh, wh);
    //開啟上下文
    UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
    //獲取上下文
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    //把上面那張控件的layer渲染上去
    [self.imageA.layer renderInContext:ctx];
    //擦除圖片
    CGContextClearRect(ctx, rect);
    //上下文中拿到圖片一張圖片
    UIImage * image = UIGraphicsGetImageFromCurrentImageContext();    
    self.imageA.image = image;
    //關閉上下文
    UIGraphicsEndImageContext();
}
  • 手勢解鎖
    • 示例

    • 手勢解鎖.jpeg
    • 自定義一個九宮格布局按鈕的view,分別這是button的normal和selected背景圖片

    • view添加一個pan手勢

    • pan觸發的方法中實現

-(void)pan:(UIPanGestureRecognizer *)pan{
//時刻記錄手指當前的位置
    self.fingerPoint = [pan locationInView:self];
    for (UIButton * btn in self.subviews) {
        //如果手指的位置在btn的范圍內 且這個按鈕沒有被選中過
        if (CGRectContainsPoint(btn.frame, self.fingerPoint) && (!btn.selected)) {
            //改變按鈕狀態為選中
            btn.selected = YES;
            //加入選中數組中
            [self.selectsBtn addObject:btn];
        }    
    }
    //滑動結束后重置狀態
    if (pan.state == UIGestureRecognizerStateEnded) {    
        // 創建可變字符串
        NSMutableString *strM = [NSMutableString string];
        // 保存輸入密碼
        for (UIButton *btn in self.selectsBtn) {     
            [strM appendFormat:@"%ld",btn.tag];
        }
        //記錄密碼
        NSLog(@"%@",strM);
        // 還原界面
        // 取消所有按鈕的選中
//        [self.selectsBtn makeObjectsPerformSelector:@selector(setSelected:) withObject:@(NO)];
        //講所有選中的按鈕狀態改變
        [self.selectsBtn enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            UIButton * btn = obj;
            btn.selected=NO;
        }];
        // 清除畫線,把選中按鈕清空
        [self.selectsBtn removeAllObjects];
  
    }
    [self setNeedsDisplay];
}
  • 畫板
    • 一個簡單的畫板示例
畫板.jpeg
  • 每個pan事件觸發begin時創建一個路徑,加載到數組中保存
-(void)pan:(UIPanGestureRecognizer *)pan{
//獲得手指的位置
    CGPoint fingerPoint = [pan locationInView:self];
    //pan 開始時
    if (pan.state == UIGestureRecognizerStateBegan) {
    
        //繼承UIBezierPath,增加一個保存顏色的屬性
        MyBezierPath * path = [MyBezierPath bezierPath];
        //設置線寬
        path.lineWidth = self.lineWidth;
        //設置顏色
        path.pathColor = self.pathColor;
         //設置起點
        [path moveToPoint:fingerPoint];
        self.path = path;
        //講路徑加入到數組中保存
        [self.paths addObject:path];
    }
    //滑動時 通過手指位置改變進行連線
    [self.path addLineToPoint:fingerPoint];
    //重新繪制
    [self setNeedsDisplay];
}
  • 實現drawRect方法,遍歷數組中保存的每條路徑,進行繪圖
-(void)drawRect:(CGRect)rect{
    //遍歷保存的路徑
    for (MyBezierPath * path in self.paths) {
        if ([path isKindOfClass:[UIImage class]]) {
            //如果是圖片繪制圖片
            UIImage * image = (UIImage *)path;            
            [image drawAtPoint:CGPointZero];           
        }else{
        //不是圖片連線          
            [path.pathColor set];         
            [path stroke];
        }
    }
}
  • 小功能即對保存路徑的數組進行操作重繪調用drawRect即可
//清空
-(void)clear{
    //清楚路徑數組
    [self.paths removeAllObjects];
    [self setNeedsDisplay];
}
//撤銷
-(void)undo{
    //刪除最后路徑數組最后一個元素
    [self.paths removeLastObject];
    [self setNeedsDisplay];
}
//橡皮擦
-(void)eraser{
    //一條白色的路徑,橡皮假象
    self.pathColor = [UIColor whiteColor];
}

Demo地址(https://github.com/heiheiLqq/Quartz-2D-Demo

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

推薦閱讀更多精彩內容

  • Quartz2D以及drawRect的重繪機制字數1487 閱讀21 評論1 喜歡1一、什么是Quartz2D Q...
    PurpleWind閱讀 786評論 0 3
  • Quartz2D 簡介 Quartz2D是二維(平面)的繪圖引擎(經包裝的函數庫,方便開發者使用。也就是說蘋果幫我...
    iOS_Cqlee閱讀 636評論 0 2
  • 什么是Quartz2D? 簡單來說,Quartz2D是用C語言封裝的二維繪圖引擎,同時支持iOS和Mac系統,利用...
    enoughpower閱讀 743評論 1 2
  • 第一步:先科普一下基礎知識: Core Graphics是基于C的API,可以用于一切繪圖操作 Core Grap...
    真愛要有你才完美閱讀 2,460評論 0 1
  • 不知是否這個清晰的名字信息給了顧妍說第一句話的底氣和勇氣。“你叫什么名字?”在一如往常的課間,顧妍以這種明知顧問的...
    果二閱讀 267評論 0 1