• Stars
    star
    111
  • Rank 307,020 (Top 7 %)
  • Language
    Swift
  • License
    MIT License
  • Created almost 6 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

一个万能的刮刮乐控件。无论是UILabel、UIImageView,还是自定义视图,只要是UIView都可以用来刮。代码简单,功能强大,你值得拥有!

JXScratchView

一个万能的刮刮乐控件。无论是UILabel、UIImageView,还是自定义视图,只要是UIView都可以用来刮。代码简单,功能强大,你值得拥有!

彩票刮刮乐.png

前言

这是一个简单却功能强大的刮刮乐视图,几行代码就可以实现刮刮乐效果,而且性能良好。下面有美女福利哟,相信我,你会喜欢的😍😍

相信大家都买过彩票刮刮乐,总是会抱着中大奖的情况去刮,希望自己是最幸运的那一个,刮中五百万,抱得美人归,从此走上人生巅峰。但现实往往是你口袋里面的几十块零钱,几分钟就被消费殆尽了😂 许多APP也集成了这一功能,比如用支付宝线下支付后就有刮刮乐。虽然刮中的都是些没多大用的优惠券,但总是会吸引人去刮一刮,万一中了大奖呢😎

实现效果

多说无益,先来看看实现的效果吧

彩票刮刮乐

彩票刮刮乐.gif

美女刮刮乐

美女刮刮乐.gif

参照了一个叫做“撕掉她的衣服”APP,效果非常sexy,有没有一种心跳加快,血脉膨胀的感觉。

调研

在网上搜索了一番,方案基本上就是这种:链接。 核心代码:

-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    // 触摸任意位置
    UITouch *touch = touches.anyObject;
    // 触摸位置在图片上的坐标
    CGPoint cententPoint = [touch locationInView:self.imageView];
    // 设置清除点的大小
    CGRect  rect = CGRectMake(cententPoint.x, cententPoint.y, 20, 20);
    // 默认是去创建一个透明的视图
    UIGraphicsBeginImageContextWithOptions(self.imageView.bounds.size, NO, 0);
    // 获取上下文(画板)
    CGContextRef ref = UIGraphicsGetCurrentContext();
    // 把imageView的layer映射到上下文中
    [self.imageView.layer renderInContext:ref];
    // 清除划过的区域
    CGContextClearRect(ref, rect);
    // 获取图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    // 结束图片的画板, (意味着图片在上下文中消失)
    UIGraphicsEndImageContext();
    
    self.imageView.image = image;
}

缺点很明显: 1、画笔是矩形的,看着很难受; 2、绘画的核心代码用了CoreGraphics,每次移动都要重新开启一个context上下文,绘制image,对CPU的性能有很大的消耗。点击该链接,详细了解CAShapeLayer比CG的优势 所以,我想了一个骚技巧,用CAShapeLayer作为mask来实现该效果。点击该链接,了解mask图层遮罩

原理

图层解释.png 如图所示,只要用户滑动的时候,更新contentView的maskLayer的path,就可以实现刮刮乐的效果了。代码如下:

  • 初始化
/// 指定初始化器
    ///
    /// - Parameters:
    ///   - contentView: 内容视图,比如彩票的奖品详情内容。(需要隐藏起来的内容)
    ///   - maskView: 遮罩视图
    public init(contentView: UIView, maskView: UIView) {
        super.init(frame: CGRect.zero)

        scratchMaskView = maskView
        self.addSubview(scratchMaskView)

        scratchContentView = contentView
        self.addSubview(scratchContentView)

        maskLayer = CAShapeLayer()
        maskLayer.strokeColor = UIColor.red.cgColor
        maskLayer.lineWidth = strokeLineWidth
        maskLayer.lineCap = strokeLineCap
        scratchContentView?.layer.mask = maskLayer

        maskPath = UIBezierPath()
    }
  • 绘画核心代码
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {
            return
        }
        let point = touch.location(in: scratchContentView)
        maskPath.move(to: point)
    }

    open override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {
            return
        }
        let point = touch.location(in: scratchContentView)
        maskPath.addLine(to: point)
        maskPath.move(to: point)
        maskLayer.path = maskPath.cgPath
    }
  • 获取已经刮了多少百分比,比如用户刮了70%的时候,就显示全部。
//获取透明像素占总像素的百分比
    private func getAlphaPixelPercent(img: UIImage) -> Float {
        //计算像素总个数
        let width = Int(img.size.width)
        let height = Int(img.size.height)
        let bitmapByteCount = width * height

        //得到所有像素数据
        let pixelData = UnsafeMutablePointer<UInt8>.allocate(capacity: bitmapByteCount)
        let colorSpace = CGColorSpaceCreateDeviceGray()
        let context = CGContext(data: pixelData,
                                width: width,
                                height: height,
                                bitsPerComponent: 8,
                                bytesPerRow: width,
                                space: colorSpace,
                                bitmapInfo: CGBitmapInfo(rawValue:
                                    CGImageAlphaInfo.alphaOnly.rawValue).rawValue)!
        let rect = CGRect(x: 0, y: 0, width: width, height: height)
        context.clear(rect)
        context.draw(img.cgImage!, in: rect)


        //计算透明像素个数
        var alphaPixelCount = 0
        for x in 0...Int(width) {
            for y in 0...Int(height) {
                if pixelData[y * width + x] == 0 {
                    alphaPixelCount += 1
                }
            }
        }

        free(pixelData)

        return Float(alphaPixelCount) / Float(bitmapByteCount)
    }
    //展示全部
    open func showContentView() {
        self.scratchContentView.layer.mask = nil
    }

使用

  • 彩票刮刮乐示例代码
        let contentView = UILabel()
        contentView.backgroundColor = UIColor.white
        contentView.textAlignment = .center
        contentView.font = UIFont.systemFont(ofSize: 25)
        contentView.text = "恭喜你刮中500万"
        contentView.numberOfLines = 0

        let maskView = UIView()
        maskView.backgroundColor = UIColor.lightGray

        let ratio = self.bounds.size.width/400
        scratchView = JXScratchView(contentView: contentView, maskView: maskView)
        scratchView.delegate = self
        scratchView.strokeLineWidth = 25
        scratchView.strokeLineCap = kCALineCapRound
        scratchView.frame = CGRect(x: 33*ratio, y: 140*ratio, width: 337*ratio, height: 154*ratio)
        addSubview(scratchView)
  • 指定使用JXScratchView的public init(contentView: UIView, maskView: UIView)初始化器,只需要传入UIView及其子类就可以了。
  • strokeLineCap属性设置stroke形状,默认kCALineCapRound
  • strokeLineWidth属性设置stroke线宽,默认20
  • 遵从JXScratchViewDelegate,实现func scratchView(scratchView: JXScratchView, didScratched percent: Float)代理方法,就可以实时获取刮刮乐的百分比。
  • 建议新建一个UIView,把JXScratchView封装进去,可以参考JXScratchTicketView

喜欢就star一下❤️

More Repositories

1

JXCategoryView

A powerful and easy to use category view (segmentedcontrol, segmentview, pagingview, pagerview, pagecontrol) (腾讯新闻、今日头条、QQ音乐、网易云音乐、京东、爱奇艺、腾讯视频、淘宝、天猫、简书、微博等所有主流APP分类切换滚动视图)
Objective-C
6,026
star
2

JXPagingView

类似微博主页、简书主页等效果。多页面嵌套,既可以上下滑动,也可以左右滑动切换页面。支持HeaderView悬浮、支持下拉刷新、上拉加载更多。
Objective-C
2,824
star
3

JXSegmentedView

A powerful and easy to use segmented view (segmentedcontrol, pagingview, pagerview, pagecontrol, categoryview) (腾讯新闻、今日头条、QQ音乐、网易云音乐、京东、爱奇艺、腾讯视频、淘宝、天猫、简书、微博等所有主流APP分类切换滚动视图)
Swift
2,596
star
4

JXPageListView

高仿闲鱼、转转、京东、中央天气预报等主流APP列表底部分页滚动视图
Objective-C
421
star
5

JXMarqueeView

A powerful and easy to use marquee view.
Swift
365
star
6

JXBottomSheetView

A useful and gesture interaction BottomSheetView!
Swift
256
star
7

JXTheme

A powerful and lightweight and customization theme/skin library for iOS 9+ in swift. 主题、换肤、暗黑模式
Swift
243
star
8

JXPatternLock

An easy-to-use, powerful, customizable pattern lock view in swift. 图形解锁/手势解锁 / 手势密码 / 图案密码 / 九宫格密码
Swift
219
star
9

JXMovableCellTableView

The custom tableView which can start moving the cell with a long press gesture.
Objective-C
188
star
10

JXPopupView

一个轻量级的自定义视图弹出框架
Swift
139
star
11

StackUI

StackUI just like SwiftUI
Swift
117
star
12

JXWeChatFloatView

高仿微信文章悬浮球
Swift
100
star
13

JXBottomSheetTableView

A highly packaged, easy to use custom bottom sheet UITableView.
Swift
48
star
14

JXExcel

一个轻量级的表视图
Swift
31
star
15

JXTableViewZoomHeaderImageView

一般app的个人资料页面都会有个头图,并且随着上下滚动的时候,图片有个移动和缩放的效果。
Objective-C
29
star
16

ModelAdapter

Simple JSON Object mapping and SQLite3 written in Swift
Swift
26
star
17

JXCaptain

像美国队长一样威猛的应用调试工具箱!
Swift
22
star
18

JXFileBrowserController

The debug sandbox browser for sharing.
Swift
22
star
19

JXGradientKit

常用控件背景渐变色Kit
Swift
19
star
20

JXLayerAutoLayout

优雅的实现CALayer AutoLayout
Objective-C
19
star
21

SQLiteValueExtension

SQLiteValueExtension for SQLite.swift
Swift
14
star
22

JXParallaxCell

用于滚动scrollview的时候,cell中的图片,或者其他控件,有一个视差滚动的效果
Objective-C
14
star
23

JXTransition

自定义转场动画
Objective-C
11
star
24

JXBorderCellll

一个有边框的基类cell
Objective-C
11
star
25

JXInterview

Interview for iOSer
10
star
26

XPackage

自己常用的一些工具
Objective-C
4
star
27

30DaysChallenge

There may be a miracle happen if you insist 30 days challenge!
Objective-C
3
star
28

JXExampleImages

示例图片资源
2
star
29

JXKit

JXKit for iOS
Swift
1
star
30

OnePiece

Swift
1
star
31

JXRomanticAlbum

谁说程序员不浪漫?我们可以用代码表白!Who says programmers aren't romantic? We can use the code to express love!
Swift
1
star