iOS 实现刮刮乐

废话开篇:利用 openCV 简单实现一下刮刮乐效果

一、实现效果

刮刮封面和奖项图片

image.png

实现效果

屏幕录制2022-01-18 下午3.36.40.gif

二、步骤分析

1、选取刮刮乐封面并进行置灰处理,并添加到 UIImageView 上。

2、UIImageView 添加 UIPanGestureRecognizer 手势。

3、监听手势 CGPoint 位置,进行封面触点约定范围内进行奖项图片像素置换。

三、外部调用 WSLScratch 刮刮类


    //刮刮乐展示view
    UIView * scratchView = [[UIView alloc] initWithFrame:CGRectMake(0, 200, self.view.frame.size.width, self.view.frame.size.width)];
    [self.view addSubview:scratchView];

    //一等奖图片
    NSString * bundleImage = [[NSBundle mainBundle] pathForResource:@"ydj" ofType:@"jpeg"];
    UIImage * image = [UIImage imageWithContentsOfFile:bundleImage];
    self.scratch = [[WSLScratch alloc] init];
    //开始处理
    [self.scratch scratchWithImage:image showView:scratchView];
复制代码

四、WSLScratch 刮刮类代码

1、WSLScratch.h

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

NS_ASSUME_NONNULL_BEGIN

@interface WSLScratch : NSObject

//奖项图片、展示showView
- (void)scratchWithImage:(UIImage *)image showView:(UIView *)showView;

@end

复制代码
2、WSLScratch.m
#ifdef __cplusplus
#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/ios.h> // Mat 和 UIImage互转
#endif

#import "WSLScratch.h"

//命名空间
using namespace cv;

@interface WSLScratch()
{
    Mat _originalImage;
    Mat _scratchCover;
}

@end

@implementation WSLScratch

- (void)scratchWithImage:(UIImage *)image showView:(UIView *)showView
{
    if (!image || !showView) {
        return;
    }
    //保存原图
    UIImageToMat(image, _originalImage);
    UIImageView * imageView = [[UIImageView alloc] initWithFrame:showView.bounds];
    [showView addSubview:imageView];
    //封面
    NSString * bundleImage = [[NSBundle mainBundle] pathForResource:@"gxfc" ofType:@"jpeg"];
    UIImage * scratchCoverImage = [UIImage imageWithContentsOfFile:bundleImage];
    imageView.image = [self scratchCoverImage:scratchCoverImage];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    //手势处理
    UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action: @selector(panAction:)];
    imageView.userInteractionEnabled = YES;
    [imageView addGestureRecognizer:pan];
}

//刮刮乐封置灰处理
- (UIImage *)scratchCoverImage:(UIImage *)image
{
    Mat img;
    UIImageToMat(image, img);
    Mat showImg(cvRound(img.rows), cvRound(img.cols), CV_8UC1 );
    //置灰处理
    cvtColor(img, showImg, COLOR_BGR2GRAY);
    //保存灰度处理矩阵
    _scratchCover = showImg;
    UIImage * showImage = MatToUIImage(_scratchCover);
    return showImage;
}

//刮一刮
- (UIImage *)beginScratchWithPoint:(CGPoint)point onView:(UIView *)onView
{
    Mat showImg(cvRound(_originalImage.rows), cvRound(_originalImage.cols), CV_8UC1 );
    cvtColor(_originalImage, showImg, COLOR_BGR2RGB);
    Mat scratchShowImg(cvRound(_scratchCover.rows), cvRound(_scratchCover.cols), CV_8UC1 );

    cvtColor(_scratchCover, scratchShowImg, COLOR_BGR2RGB);
    int panWith = 30;
    int startX = floor(scratchShowImg.cols * point.x / onView.frame.size.width);
    startX = startX - panWith < 0 ? 0 : startX - panWith;
    int startY = floor(scratchShowImg.rows * point.y / onView.frame.size.height);
    
    startY = startY - panWith < 0 ? 0 : startY - panWith;
    for (int x = startX; x < startX + panWith; x ++) {

        for (int y = startY; y < startY + panWith; y ++) {
        
            int b = scratchShowImg.at<Vec3b>(y,x)[0];
            int g = scratchShowImg.at<Vec3b>(y,x)[1];
            int r = scratchShowImg.at<Vec3b>(y,x)[2];
            
            //奖项原图色值获取
            b = showImg.at<Vec3b>(y,x)[0];
            g = showImg.at<Vec3b>(y,x)[1];
            r = showImg.at<Vec3b>(y,x)[2];
            
            //灰色封面色值替换
            scratchShowImg.at<Vec3b>(y,x)[0] = b;
            scratchShowImg.at<Vec3b>(y,x)[1] = g;
            scratchShowImg.at<Vec3b>(y,x)[2] = r;
        }
    }
    cvtColor(scratchShowImg, _scratchCover, cv::COLOR_BGR2RGB, 3);
    UIImage * showImage = MatToUIImage(_scratchCover);
    return showImage;
}

- (void)panAction:(UIPanGestureRecognizer *)sender
{
    switch (sender.state) {
        case UIGestureRecognizerStateChanged:
        {
            CGPoint currentPoint = [sender locationInView:sender.view];
            UIImageView * imageView = (UIImageView *)sender.view;
            imageView.image = [self beginScratchWithPoint:currentPoint onView:sender.view];
        }
            break;
        default:
            break;
    }
}
@end
复制代码

五、总结与思考

简单的刮刮乐效果就完成了,个人总结随笔,大神勿笑[抱拳][抱拳][抱拳]

猜你喜欢

转载自juejin.im/post/7054452621980991496