Github倉庫地址
前言
這是一個簡單卻功能強大的刮刮樂檢視,幾行程式碼就可以實現刮刮樂效果,而且效能良好。下面有美女福利喲,相信我,你會喜歡的??
相信大家都買過彩票刮刮樂,總是會抱著中大獎的情況去刮,希望自己是最幸運的那一個,刮中五百萬,抱得美人歸,從此走上人生巔峰。但現實往往是你口袋裡面的幾十塊零錢,幾分鐘就被消費殆盡了? 許多APP也整合了這一功能,比如用支付寶線下支付後就有刮刮樂。雖然刮中的都是些沒多大用的優惠券,但總是會吸引人去刮一刮,萬一中了大獎呢?
實現效果
多說無益,先來看看實現的效果吧
彩票刮刮樂
美女刮刮樂
參照了一個叫做“撕掉她的衣服”APP,效果非常sexy,有沒有一種心跳加快,血脈膨脹的感覺。(相信大家迫不及待想要體驗一下了,點選fir.im/JXScratchVi…,通過safari開啟該連結,安裝之後信任證書,就可以快速體驗了)相信我在空白處,雙擊一下,你會發現新大陸?
調研
在網上搜尋了一番,方案基本上就是這種:連結。 核心程式碼:
-(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圖層遮罩
原理
如圖所示,只要使用者滑動的時候,更新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