zoukankan      html  css  js  c++  java
  • [ios]ios-Demo4脱衣服/刮奖app-专业

    普通版本完成的锯齿很严重 但是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
  • 相关阅读:
    【关键字】
    【选择结构语句:switch】
    【数据类型】
    【接口】
    【抽象类和接口的区别】
    【访问权限】
    【内部类】
    【方法】
    【this 关键字】
    【Static】
  • 原文地址:https://www.cnblogs.com/lovewx/p/4200991.html
Copyright © 2011-2022 走看看