iOS-UI之遮罩效果(2)——图片遮罩(刮刮乐效果)

iOS-UI之遮罩效果(2)——图片遮罩(刮刮乐效果)

在这里插入图片描述
在这里插入图片描述
来看看实现步骤

1.先放一张图片,再加一层遮罩

将图片放在一个背景view上作为容器,bgView的颜色就是涂层颜色

		let view = UIView()
        view.backgroundColor = .lightGray
        bgView.frame = CGRect(x: 0, y: 100, width: kScreenWidth, height: kScreenWidth * 9 / 16)
        view.addSubview(bgView)
        
        let imageView = UIImageView()
        imageView.image = UIImage(named: "underworld.jpg")
        imageView.isUserInteractionEnabled = true
        imageView.frame = bgView.bounds
        bgView.addSubview(imageView)

		let bgMaskLayer = CALayer()
        imageView.layer.mask = bgMaskLayer

效果图就是一片灰色

如果要在涂层未刮开的地方显示一个label,就一定要把label放到图片下面,这样刮开涂层的时候文字也会消失
如果是按钮的话,就要放在图片上面,并且要在刮涂层之前将按钮移除,以免挡住涂层

2.给图片添加平移手势

		// 务必要将imageView的isUserInteractionEnabled属性设置为true
		let pan = UIPanGestureRecognizer(target: self, action: #selector(panAction(_:)))
        imageView.addGestureRecognizer(pan)

手势方法

@objc func panAction(_ pan:UIPanGestureRecognizer) {
        let point = pan.location(in: imageView)
        let maskLayer = CAShapeLayer()
        maskLayer.lineWidth = 50
        maskLayer.lineCap = .round
        maskLayer.lineJoin = .round
        maskLayer.strokeColor = UIColor.lightGray.cgColor
        maskLayer.fillColor = nil
        let maskPath = UIBezierPath()
        
        switch pan.state {
        case .began:
            debugPrint("pan start")
            currentPoint = point
            maskPath.move(to: currentPoint)
        case .changed:
            debugPrint("pan -------")
            maskPath.addLine(to: point)
            currentPoint = point
        case .ended:
            debugPrint("pan end")
        case .cancelled:
            debugPrint("pan cancel")
        default:
            break
        }
        maskPath.move(to: currentPoint)
        maskPath.addLine(to: point)
        maskLayer.path = maskPath.cgPath
        bgMaskLayer.addSublayer(maskLayer)
    }

其中currentPoint是一个本类的的属性,用来记录手势划过的点

	var currentPoint = CGPoint.zero

其原理就是在平移手势的方法中初始化一个CAShapeLayer,然后通过手势将其轨迹获取到并绘制出来,然后添加到bgMaskLayer的sublayer中

到这里,刮刮乐效果已经基本实现,效果如下
在这里插入图片描述
但是,当手指滑动过快时,问题就出现了:
在这里插入图片描述
滑动过快,也许由于手势方法执行速度的问题,绘制出来的Layer不够连续,就会出现上面的结果。
在这种实现方式下我没有太好的解决办法,所以有另一种实现方式:

3.另一种实现方式:

通过重写
touchesBegan(:with:)
touchesMoved(
:with:)
touchesEnded(_:with:)
三个方法,来绘制layer

前面的准备和第一种方法类似
添加如下两个类属性

	var lastPoint = CGPoint.zero
    var isSwiping = false

重写方法

	// 这里主要是来记录起始点
	override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        isSwiping = false
        let touch = (touches as NSSet).anyObject() as! UITouch
        lastPoint = touch.location(in: imageView2)
    }
	// 绘制layer的主体,有两种方法来添加layer的path,一种是通过context,另一种是用UIBezierPath,都是为了给layer设置path
	override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        isSwiping = true
        let touch = (touches as NSSet).anyObject() as! UITouch
        let curPoint = touch.location(in: imageView2)
        
        // 两种方式添加轨迹
        
//        UIGraphicsBeginImageContext(imageView2.frame.size)
//        let context = UIGraphicsGetCurrentContext()
//        context?.move(to: lastPoint)
//        context?.addLine(to: curPoint)
//        let maskLayer = CAShapeLayer()
//        maskLayer.lineWidth = 50
//        maskLayer.lineCap = .round
//        maskLayer.lineJoin = .round
//        maskLayer.strokeColor = UIColor.lightGray.cgColor
//        maskLayer.fillColor = nil
//        maskLayer.path = context!.path
//        bgMaskLayer2.addSublayer(maskLayer)
//        context?.closePath()
        
        let maskLayer = CAShapeLayer()
        maskLayer.lineWidth = 50
        maskLayer.lineCap = .round
        maskLayer.lineJoin = .round
        maskLayer.strokeColor = UIColor.lightGray.cgColor
        maskLayer.fillColor = nil
        let maskPath = UIBezierPath()
        maskPath.move(to: lastPoint)
        maskPath.addLine(to: curPoint)
        maskLayer.path = maskPath.cgPath
        bgMaskLayer2.addSublayer(maskLayer)
        
        lastPoint = curPoint
    }
	// 起始不重写这个方法也可以实现效果,不过在单点的时候就有可能会出现无法生成layer的问题,所以可以加上这个方法
	override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if !isSwiping { // 这样写的目的是为了解决轻点时无效果的问题
            UIGraphicsBeginImageContext(imageView2.frame.size)
            let context = UIGraphicsGetCurrentContext()
            context?.move(to: lastPoint)
            context?.addLine(to: lastPoint)
            let maskLayer = CAShapeLayer()
            maskLayer.lineWidth = 50
            maskLayer.lineCap = .round
            maskLayer.lineJoin = .round
            maskLayer.strokeColor = UIColor.lightGray.cgColor
            maskLayer.fillColor = nil
            maskLayer.path = context!.path
            bgMaskLayer2.addSublayer(maskLayer)
            context?.closePath()
        }
    }

最后效果如下
在这里插入图片描述
这样就丝滑了许多
当划快了也不会出现一坨一坨的情况
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值