比如说A是一个imageView,B仅仅是一个普通的透明的view,我希望A被B盖住的部分是彩色的,而没有盖住的部分是黑白的,请问有什么实现的思路吗
黄舟2017-04-18 09:48:29
可以控制A的layer.mask
实现,mask即为A和B的重合区域,通过计算重合区域的rect
来改变layer.mask
的填充path
。很多遮罩效果都是用mask實現的。
我寫了一份程式碼,你可以參考一下。直接在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中看到以下效果:
大家讲道理2017-04-18 09:48:29
1.計算出AB相交部分的size
2.計算出彩色部分的起點
3.運用貝塞爾曲線畫出彩色部分
4.運用CAShapeLayer將path設置為第三步的貝塞爾曲線,將layer加到A上.
個人想法,可以試試.