美文网首页收藏ios
iOS滑块拼图验证

iOS滑块拼图验证

作者: yyggzc521 | 来源:发表于2019-03-03 18:38 被阅读434次
    滑动拼图.png

    实现过程

    1. 初始化UI
    [self addSubview:({//背景图片
            self.imageViewBG.frame = CGRectMake(margin, CGRectGetMaxY(self.tipLabel.frame)+margin, self.width-margin*2, imageHeight);
            self.imageViewBG.contentMode =  UIViewContentModeScaleAspectFill;
            self.imageViewBG.clipsToBounds = YES;
            self.imageViewBG;
        })];
    
    //添加右侧遮罩层,并绘制路径
     UIBezierPath *path = getCodePath();
        
        [self.imageViewBG addSubview:({
            self.maskView.frame = CGRectMake(self.randomPoint.x, self.randomPoint.y, codeSize, codeSize);
            
            self.maskLayer.frame = CGRectMake(0, 0, codeSize, codeSize);
            self.maskLayer.path = path.CGPath;
            self.maskLayer.strokeColor = [UIColor whiteColor].CGColor;
            [self.maskView.layer addSublayer:self.maskLayer];
            
            self.maskView;
        })];
    
    //添加左侧可滑动图片,并绘制路径
    UIImage * thumbImage = [self.imageViewBG.image dw_SubImageWithRect:self.maskView.frame];
        thumbImage = [thumbImage dw_ClipImageWithPath:path mode:(DWContentModeScaleToFill)];
        [self.imageViewBG addSubview:({
            self.moveImage.frame = CGRectMake(0, self.randomPoint.y-offset, codeSize+offset, codeSize+offset);
            self.moveImage.image = thumbImage;
            self.moveImage;
        })];
    
    [self addSubview:({//滑杆
            self.slider.frame = CGRectMake(margin, CGRectGetMaxY(self.imageViewBG.frame) + margin, self.width-margin*2, 30);
            [self.slider addTarget:self action:@selector(buttonAction:forEvent:) forControlEvents:UIControlEventAllTouchEvents];
            self.slider.minimumTrackTintColor = [UIColor colorWithRed:247/256.0 green:63/256.0 blue:94/256.0 alpha:1.0];
            self.slider.maximumTrackTintColor = [UIColor colorWithRed:251/256.0 green:88/256.0 blue:96/256.0 alpha:1.0];
            UIImage *tempImage = [UIImage imageNamed:@"SliderImage"];
            tempImage = [tempImage imageScaleToSize:CGSizeMake(30, 30)];
            [self.slider setThumbImage:tempImage forState:UIControlStateNormal];
            [self.slider setThumbImage:tempImage forState:UIControlStateHighlighted];
            self.slider;
        })];
    

    绘制滑块贝塞尔曲线

    static inline UIBezierPath* getCodePath() {
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(0, 0)];
        [path addLineToPoint:CGPointMake(codeSize*0.5-offset,0)];
        [path addQuadCurveToPoint:CGPointMake(codeSize*0.5+offset, 0) controlPoint:CGPointMake(codeSize*0.5, -offset*2)];
        [path addLineToPoint:CGPointMake(codeSize, 0)];
       
        [path addLineToPoint:CGPointMake(codeSize,codeSize*0.5-offset)];
        [path addQuadCurveToPoint:CGPointMake(codeSize, codeSize*0.5+offset) controlPoint:CGPointMake(codeSize+offset*2, codeSize*0.5)];
        [path addLineToPoint:CGPointMake(codeSize, codeSize)];
        
        [path addLineToPoint:CGPointMake(codeSize*0.5+offset,codeSize)];
        [path addQuadCurveToPoint:CGPointMake(codeSize*0.5-offset, codeSize) controlPoint:CGPointMake(codeSize*0.5, codeSize-offset*2)];
        [path addLineToPoint:CGPointMake(0, codeSize)];
        
        [path addLineToPoint:CGPointMake(0,codeSize*0.5+offset)];
        [path addQuadCurveToPoint:CGPointMake(0, codeSize*0.5-offset) controlPoint:CGPointMake(0+offset*2, codeSize*0.5)];
        [path addLineToPoint:CGPointMake(0, 0)];
        
        [path stroke];
        return path;
    }
    

    监听滑竿滑动并改变左侧可移动图片的frame

    - (void)buttonAction:(UISlider*)slider forEvent:(UIEvent *)event{
        UITouchPhase phase = event.allTouches.anyObject.phase;
        if (phase == UITouchPhaseBegan) {
            dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
            self.seconds = 0;
            timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, global);
            dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
            dispatch_source_set_event_handler(timer, ^{
                self.seconds+=0.1;
                NSLog(@"%.1f",self.seconds);
            });
            dispatch_resume(timer);
        }
        else if(phase == UITouchPhaseEnded){
            if (timer) {
                dispatch_source_cancel(timer);
            }
            
            CGFloat x = self.maskView.frame.origin.x;
            if (fabs(self.moveImage.frame.origin.x-x)<=5.00) {
                [self.layer addAnimation:successAnimal() forKey:@"successAnimal"];
                [self showToast:YES];
            }else{
                [self.layer addAnimation:failAnimal() forKey:@"failAnimal"];
                [self defaultSlider];
                [self showToast:NO];
            }
        }else if (phase == UITouchPhaseMoved){
            if (slider.value>self.width-margin*2-codeSize) {
                slider.value = self.width-margin*2-codeSize;
                return;
            }
            [self changeMoveImageFrameWithVlue:slider.value];
            
        }
    }
    
    //设置默认的滑动
    - (void)defaultSlider{
        self.slider.value = 0;
        [self changeMoveImageFrameWithVlue:self.slider.value];
    }
    
    //图片位置随着Slider滑动改变frame
    - (void)changeMoveImageFrameWithVlue:(CGFloat)value{
        CGRect rect = self.moveImage.frame;
        CGFloat x = value * (self.imageViewBG.frame.size.width)-(value*codeSize);
        rect.origin.x = x;
        self.moveImage.frame = rect;
    }
    

    成功和失败的动画及提示

    //成功动画
    static inline CABasicAnimation *successAnimal(){
        CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        animation.duration = 0.2;
        animation.autoreverses = YES;
        animation.fromValue = @1;
        animation.toValue = @0;
        animation.removedOnCompletion = YES;
        return animation;
    }
    
    //失败动画
    static inline CABasicAnimation *failAnimal(){
        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
        [animation setDuration:0.08];
        animation.fromValue = @(-M_1_PI/16);
        animation.toValue = @(M_1_PI/16);
        animation.repeatCount = 2;
        animation.autoreverses = YES;
        return animation;
    }
    
    //成功的操作
    - (void)showToast:(BOOL)success {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            __weak WMZCodeView *codeView = self;
            NSString *tip = @"";
            if (self.seconds>0) {
                tip = [NSString stringWithFormat:@"耗时%.1fs",self.seconds];
            }
            UIAlertController *alert = [UIAlertController alertControllerWithTitle:success ? @"验证成功" : @"验证失败" message:tip preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                if (codeView.block) {
                    codeView.block(success);
                }
                [codeView refreshAction];
            }];
            [alert addAction:action];
            [[self getCurrentVC] presentViewController:alert animated:YES completion:nil];
        });
       
    }
    

    http://code.cocoachina.com/view/137862
    https://www.jianshu.com/p/93d83018e5cd
    https://github.com/AlbertXYZ/PuzzleVerify
    https://github.com/wsl2ls/YanZhengCode
    https://www.jianshu.com/p/a7021d87864b
    https://github.com/zekunyan/TTGPuzzleVerify
    https://github.com/kang558/eros-plugin-ios-TencentCaptcha
    自定义滑杆样式

    相关文章

      网友评论

        本文标题:iOS滑块拼图验证

        本文链接:https://www.haomeiwen.com/subject/olexuqtx.html