比如说A是一个imageView,B仅仅是一个普通的透明的view,我希望A被B盖住的部分是彩色的,而没有盖住的部分是黑白的,请问有什么实现的思路吗
业精于勤,荒于嬉;行成于思,毁于随。
可以控制A的layer.mask实现,mask即为A和B的重合区域,通过计算重合区域的rect来改变layer.mask的填充path。很多遮罩效果都是用mask实现的。
layer.mask
rect
path
我写了一份代码,你可以参考一下。直接在playground上就可以看到效果了:
import UIKit import PlaygroundSupport /// 可以拖动的View,即ViewB class DragableView:UIView { var maskLayer: CAShapeLayer? var viewThatMask: UIView? { didSet { maskLayer?.removeFromSuperlayer() maskLayer = nil if let _ = viewThatMask { self.maskLayer = CAShapeLayer() self.maskLayer?.backgroundColor = UIColor.orange.cgColor self.maskLayer?.frame = self.bounds self.layer.mask = self.maskLayer } } } override init(frame: CGRect) { super.init(frame: frame) self.isOpaque = true self.backgroundColor = .black let gesture = UIPanGestureRecognizer(target: self, action: #selector(self.panGestureEvent(_:))) self.addGestureRecognizer(gesture) } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } /// 相交部分改变的处理闭包, 参数rect是相交的区域, view是maskView var maskChangedHandler:((CGRect, UIView)->Void)? func panGestureEvent(_ gesture:UIPanGestureRecognizer) { let point = gesture.translation(in: self) if gesture.state == .changed { self.frame.origin.x += point.x self.frame.origin.y += point.y gesture.setTranslation(.zero, in: self) if let viewThatMask = self.viewThatMask, let superview = self.superview { // 两个View相交rect,以父view为参考 let rectInSuper = self.frame.intersection(viewThatMask.frame) // 转化为以图片的坐标系的rect let interRectInMask = superview.convert(rectInSuper, to: viewThatMask) if let maskChangedHandler = self.maskChangedHandler { maskChangedHandler(interRectInMask, viewThatMask) } } } } } let imageViewColorful = UIImageView(frame: CGRect(x:50, y:50, width:150, height:100)) imageViewColorful.image = UIImage(named: "dog_colorful") imageViewColorful.layer.mask = CAShapeLayer() let imageViewGray = UIImageView(frame: CGRect(x:50, y:50, width:150, height:100)) imageViewGray.image = UIImage(named: "dog_gray") let dragView = DragableView(frame: CGRect(x:50, y:200, width:200, height:200)) dragView.viewThatMask = imageViewColorful dragView.maskChangedHandler = { rect, viewA in if let maskLayer = viewA.layer.mask as? CAShapeLayer { maskLayer.path = CGPath(rect: rect, transform: nil) maskLayer.fillColor = UIColor.black.cgColor } } let view = UIView(frame: CGRect(x:0, y:0, width:400, height:640)) view.backgroundColor = .white view.addSubview(dragView) view.addSubview(imageViewGray) view.addSubview(imageViewColorful) PlaygroundPage.current.liveView = view
如果运行正常的话,可以在playground的Assistant Editor中看到如下效果:
1.计算出AB相交部分的size2.计算出彩色部分的起点3.运用贝塞尔曲线画出彩色部分4.运用CAShapeLayer将path设置为第三步的贝塞尔曲线,将layer添加到A上.
个人想法,可以试试.
可以控制A的
layer.mask
实现,mask即为A和B的重合区域,通过计算重合区域的rect
来改变layer.mask
的填充path
。很多遮罩效果都是用mask实现的。我写了一份代码,你可以参考一下。直接在playground上就可以看到效果了:
如果运行正常的话,可以在playground的Assistant Editor中看到如下效果:
1.计算出AB相交部分的size
2.计算出彩色部分的起点
3.运用贝塞尔曲线画出彩色部分
4.运用CAShapeLayer将path设置为第三步的贝塞尔曲线,将layer添加到A上.
个人想法,可以试试.