普通版本完成的锯齿很严重 但是Ios系统中仅CGContextClearRect 并不存在cyclo等方法。 网上查了一些资料。 发现还是利用到了CG 中的Mask来实现
效果图:

这种效果可以自定义画笔的粗细等相关设置,不会像普通模式中出现比较严重的锯齿。

具体分析如下:
     1.获取需要隐藏View的layer的CGImageRef用于后面配合掩码
     2.开辟符合1的CGImageRef的CFMutableDataRef空间 给下面的掩码BitmapContext使用
     3.通过CFMutableDataRef获得CGDataProviderRef (maskCreate用到)
     3.BitmapContextCreate
     4.BitmapContext填充黑色 并且设置画笔相关(白色,宽度,线帽(cap))
     5.CGImageMaskCreate 将CGDataProviderRef  传入 则得到CGImageRef指向的是刚才创建BitmapContext。改变BitmapContext 则此CGImageRef内容也会改变
     6.CGImageCreateWithMask - 通过Mask的CGImageRef创建CGImageRef 此CGImageRef随 Maskde CGImageRef变化(所以 BitmapContext改变 Mask改变 mask掩码后的CGImageRef改变)
     7.释放

8.手指触摸时,根据上一个CGPoint 和此次的CGPoint 给bitmapContext新增path 并且绘制。然后调用【self setNeedsDisplay】,在重绘中(-drawRect) 重新获取通过mask后的CGImageRef 获取最新的UIImage
     9.将最新的UIImage drawRect到界面

代码:
//
//  PLLScrathView.h
//  PLLScratchViewDemo
//
//  Created by liu poolo on 14-7-31.
//  Copyright (c) 2014年 liu poolo. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface PLLScratchView : UIView
@property (nonatomic,assign) float sizeBrush;
-(void)setHideView:(UIView*) hideView;
@end

//
//  PLLScrathView.m
//  PLLScratchViewDemo
//
//  Created by liu poolo on 14-7-31.
//  Copyright (c) 2014年 liu poolo. All rights reserved.
//

#import "PLLScratchView.h"
@interface PLLScratchView(){
    CGContextRef _contextMask;//maskContext 用户touch 改变的context
    CGImageRef _scratchCGImg;//CGimageRef 封装_contextMask 图片信息 _contextMask改变 跟着改变 直到 调用生成UIImage
    CGPoint currPonit;
    CGPoint prePoint;
}
@end

@implementation PLLScratchView
@synthesize sizeBrush;
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setOpaque:NO];
        //设置透明 如果不透明就没法看到下一层了
        self.sizeBrush=10.0f;
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    [super drawRect:rect];
    UIImage* imageToDraw=[UIImage imageWithCGImage:_scratchCGImg];
    [imageToDraw drawInRect:self.frame];
}
//setSizeBrush before setHideView
-(void)setHideView:(UIView*) hideView{
    CGColorSpaceRef colorSpace=CGColorSpaceCreateDeviceGray();
    CGFloat scale = [UIScreen mainScreen].scale;
   
    //获得当前传入View的CGImage
    UIGraphicsBeginImageContextWithOptions(hideView.bounds.size, NO, 0);
    hideView.layer.contentsScale=scale;
    [hideView.layer renderInContext:UIGraphicsGetCurrentContext()];
    CGImageRef hideCGImg=UIGraphicsGetImageFromCurrentImageContext().CGImage;
    UIGraphicsEndImageContext();
   
    //绘制Bitmap掩码
    size_t width=CGImageGetWidth(hideCGImg);
    size_t height=CGImageGetHeight(hideCGImg);
   
    CFMutableDataRef pixels;
    pixels=CFDataCreateMutable(NULL, width*height);
    //创建一个可变的dataRef 用于bitmap存储记录
    _contextMask = CGBitmapContextCreate(CFDataGetMutableBytePtr(pixels), width, height , 8, width, colorSpace, kCGImageAlphaNone);
   
    //数据提供者
    CGDataProviderRef dataProvider=CGDataProviderCreateWithCFData(pixels);
   
    //填充黑色背景 mask中黑色范围为显示内容 白色为不显示
    CGContextSetFillColorWithColor(_contextMask, [UIColor blackColor].CGColor);
    CGContextFillRect(_contextMask, self.frame);
   
    CGContextSetStrokeColorWithColor(_contextMask, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(_contextMask, self.sizeBrush);
    CGContextSetLineCap(_contextMask, kCGLineCapRound);
   
    CGImageRef mask=CGImageMaskCreate(width, height, 8, 8, width, dataProvider, nil, NO);
    _scratchCGImg=CGImageCreateWithMask(hideCGImg, mask);

CGImageRelease(mask);
    CGColorSpaceRelease(colorSpace);
   
}

-(void)scratchViewFrom:(CGPoint)startPoint toEnd:(CGPoint)endPoint{
    float scale=[UIScreen mainScreen].scale;
    //CG的Y与UI的是反的 UI的y0在左上角 CG在左下
    CGContextMoveToPoint(_contextMask, startPoint.x*scale, (self.frame.size.height-startPoint.y)*scale);
    CGContextAddLineToPoint(_contextMask, endPoint.x*scale,(self.frame.size.height-endPoint.y)*scale);
    CGContextStrokePath(_contextMask);
    [self setNeedsDisplay];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesMoved:touches withEvent:event];
    UITouch *touch=[touches anyObject];
    currPonit=[touch locationInView:self];
    prePoint=[touch previousLocationInView:self];
    [self scratchViewFrom:prePoint toEnd:currPonit];
}

-(void)toucheseEnd:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    UITouch *touch=[touches anyObject];
    currPonit=[touch locationInView:self];
    prePoint=[touch previousLocationInView:self];
    [self scratchViewFrom:prePoint toEnd:currPonit];
}

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesCancelled:touches withEvent:event];
}

@end

  • 大小: 566.6 KB

[ios]ios-Demo4脱衣服/刮奖app-专业的更多相关文章

  1. iOS 制作发布证书,发布到App Store

    ---恢复内容开始--- 1.登陆 iOS Dev Center 选择进入iOS Provisioning Portal. 2.在 iOS Provisioning Portal中,点击App IDs ...

  2. Xamarin.iOS - 利用Settings插件与EAIntroView制作App的欢迎界面

    Xamarin.iOS - 利用Settings插件与EAIntroView制作App的欢迎界面 关于欢迎界面 很多App第一次启动都会有一个欢迎界面,欢迎界面往往决定这用户对App的第一映像,所以欢 ...

  3. iOS利用Application Loader打包提交到App Store时遇到错误The filename 未命名.ipa in the package contains an invalid character(s). The valid characters are:A-Z ,a-z,0-9,dash,period,underscore,but the name cannot start w

    iOS利用Application Loader打包提交到App Store时遇到错误: The filename 未命名.ipa in the package contains an invalid ...

  4. iOS自定义弹出视图、收音机APP、图片涂鸦、加载刷新、文件缓存等源码

    iOS精选源码 一款优秀的 聆听夜空FM 源码 zhPopupController 简单快捷弹出自定义视图 WHStoryMaker搭建美图(贴纸,涂鸦,文字,滤镜) iOS cell高度自适应 有加 ...

  5. iOS remote debug & Android remote debug & Chrome & APP

    iOS remote debug & Android remote debug & Chrome & APP iOS remote debugging 如何在 iOS 真机上调 ...

  6. IOS小组件(8):App与Widget数据共享

    引言   Widget是一个迷你版的App,IOS有沙盒机制,不同App之间无法直接共享数据.组件和主App之间其实就是不同App的关系,所以也无法通过userdefaults.standard来传数 ...

  7. Android项目刮刮奖详解扩展篇——开源刮刮奖View的制作

    Android项目刮刮奖详解(四) 前言 我们已经成功实现了刮刮奖的功能了,本期是扩展篇,我们把这个View直接定义成开源控件,发布到JitPack上,以后有需要也可以直接使用,关于自定义控件的知识, ...

  8. Android项目刮刮奖详解(三)

    Android项目刮刮奖详解(二) 前言 上一期我们已经实现了一个简易的刮刮卡功能,这一期我们来将其完善一下 目标 将刮刮奖的宽高改为合适高度 将刮刮奖位置居中 将信息层的图片换成文字(重点) 实现 ...

  9. 简单入门canvas - 通过刮奖效果来学习

    一 .前言 一直在做PC端的前端开发,从互联网到行业软件.最近发现移动端已经成为前端必备技能了,真是不能停止学习.HTML5新增的一些东西,canvas是用的比较多也比较复杂的一个,简单的入门了一下, ...

随机推荐

  1. 洛谷P1472 奶牛家谱 Cow Pedigrees

    P1472 奶牛家谱 Cow Pedigrees 102通过 193提交 题目提供者该用户不存在 标签USACO 难度普及+/提高 提交  讨论  题解 最新讨论 暂时没有讨论 题目描述 农民约翰准备 ...

  2. No.010 Regular Expression Matching

    10. Regular Expression Matching Total Accepted: 89193 Total Submissions: 395441 Difficulty: Hard Imp ...

  3. eclipse+maven+jetty环境下修改了文件需要重启才能修改成功

    遇到这种情况,需要在类库文件夹中修改配置文件(C:\.m2\repository\org\mortbay\jetty\jetty\6.1.22) 在以上路径下添加如下路径的压缩文件中的两个文件即可 路 ...

  4. 织梦DedeCMS列表摘要 description 长度控制方法

    [field:description /]标签如何限制字数? [field:description function='cn_substr(@me,80)'/] DedeCMS 里的所有标记都支持这样 ...

  5. 关于module_param()宏

    在用户态下编程可以通过main()的来传递命令行参数,而编写一个内核模块则通过module_param () module_param宏是Linux 2.6内核中新增的,该宏被定义在include/l ...

  6. Oracle 查询字段在什么表

    -- 查询字段在什么表 select * from all_tab_cols t where t.column_name='ABC'; -- 查询字段在什么表并且 判断是否是主键 select * f ...

  7. leetcode 121

    121. Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of ...

  8. 在MFC程序中使用AnyCAD图形控件

    AnyCAD图形控件有.Net版本和C++两个版本,使用C++要比C#稍微繁杂一点.SDK中提供了针对MFC的文档视图的封装,只需改一下几个基类即可. 准备 VS2010 下载C++版本的AnyCAD ...

  9. c#文本文件写入

      string err = "Hellod world";             FileStream fs = null;             string filePa ...

  10. linux禁止tty终端登陆

    修改文件/etc/pam.d/system-auth #%PAM-1.0# This file is auto-generated.# User changes will be destroyed t ...