【问题标题】:How to get multiply blend mode on a plain UIView (not UIImage)如何在普通 UIView(不是 UIImage)上获得多重混合模式
【发布时间】:2013-04-30 17:15:27
【问题描述】:

我的 iPad 应用程序中有一张图片,我基本上想在它上面放置一个颜色过滤器。为此,我有一个彩色 UIView,它被遮盖到我放在图像上的特定形状。由于调整 alpha 并没有给我想要的效果,我想改用混合模式。

据我所知,您只能在图像上使用混合模式,而不能在普通视图上使用。视图的颜色是动态的,所以我不能只使用图片。

我也尝试将视图光栅化为图像,但这一切都变得像素化和奇怪或其他什么,但也许我做错了什么。

所以,基本问题是:是否可以将混合模式应用于视图?还是我应该采取完全不同的方法来实现相同的目标?

【问题讨论】:

    标签: ios uiview filter uiimage blend


    【解决方案1】:

    查看 CALayer 的 compositingFilter 的文档:https://developer.apple.com/documentation/quartzcore/calayer/1410748-compositingfilter

    在您的颜色叠加视图中,您可以将view.layer.compositingFilter 设置为CICategoryCompositeOperation 以实现与其背后的内容混合。下面是一些示例 Playground 代码,其中应用了多重混合模式来对其进行测试(将 UIImage(named: "") 替换为您自己的图像进行测试)

    import UIKit
    import PlaygroundSupport
    
    class MyViewController : UIViewController {
        override func loadView() {
    
            let mainView = UIView()
            self.view = mainView
    
            let image = UIImageView()
            image.translatesAutoresizingMaskIntoConstraints = false;
            image.image = UIImage(named: "maxresdefault.jpg")
            mainView.addSubview(image)
    
            let overlay = UIView()
            overlay.translatesAutoresizingMaskIntoConstraints = false;
            overlay.backgroundColor = .red
            overlay.layer.compositingFilter = "multiplyBlendMode"
            mainView.addSubview(overlay)
    
            mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))
            mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": view]))
    
            mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay]))
            mainView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[subview]-0-|", options: .directionLeadingToTrailing, metrics: nil, views: ["subview": overlay]))
        }
    }
    
    PlaygroundPage.current.liveView = MyViewController()
    

    【讨论】:

    • 然后呢? 1)该链接是关于使用图层的。在您的回答中,您将“图层”替换为“视图”,它当然不起作用。 2)即使我使用他们的建议 - 从您的链接中:'iOS 中的图层不支持此属性`... 否决
    • UIViews 有层
    • 我刚刚在 iPhone 6 Pus 上使用 overlay.layer.compositingFilter = "multiplyBlendMode" 运行了一个测试应用程序,效果很好!我看不到任何 iOS 支持问题。
    • 这个解决方案不再起作用了!在 iOS 13 中,设置 CALayer.compositingFilter 是无操作的。还有其他人遇到这个问题吗? (2019 年 9 月)
    【解决方案2】:

    iOS 13、Swift 5

    关键是在适当的 CALayer 上设置 compositingFilter 属性(顶部的那个 - 它与它后面的任何东西混合在一起)。 UIViews 或 CALayers 之间的颜色混合工作。你可以在这里找到混合模式CICategoryCompositeOperation。要使用过滤器,只需删除 CI 并将名称的第一个字母小写(例如,CIDivideBlendMode 变为 divideBlendMode)。这里有一些操场代码来说明:

    import UIKit
    import PlaygroundSupport
    
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 900))
    PlaygroundPage.current.liveView = view
    
    
    let heightIncrement = view.frame.height / 13
    let widthIncrement = view.frame.width / 7
    
    
    // TOP EXAMPLE (UIViews)
    
    let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2,
                                              y: heightIncrement,
                                              width: widthIncrement * 3,
                                              height: heightIncrement * 5))
    backgroundView.backgroundColor = .black
    view.addSubview(backgroundView)
    
    let overlayView1 = UIView(frame: CGRect(x: widthIncrement,
                                            y: heightIncrement * 2,
                                            width: widthIncrement * 5,
                                            height: heightIncrement))
    overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
    overlayView1.layer.compositingFilter = "darkenBlendMode"
    view.addSubview(overlayView1)
    
    let overlayView2 = UIView(frame: CGRect(x: widthIncrement,
                                            y: heightIncrement * 4,
                                            width: widthIncrement * 5,
                                            height: heightIncrement))
    overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
    overlayView2.layer.compositingFilter = "divideBlendMode"
    view.addSubview(overlayView2)
    
    
    
    
    // BOTTOM EXAMPLE (CALayers)
    
    let backgroundLayer = CALayer()
    backgroundLayer.frame = CGRect(x: widthIncrement * 2,
                                   y: heightIncrement * 7,
                                   width: widthIncrement * 3,
                                   height: heightIncrement * 5)
    backgroundLayer.backgroundColor = UIColor.black.cgColor
    view.layer.addSublayer(backgroundLayer)
    
    let overlayLayer1 = CALayer()
    overlayLayer1.frame = CGRect(x: widthIncrement,
                                 y: heightIncrement * 8,
                                 width: widthIncrement * 5,
                                 height: heightIncrement)
    overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
    overlayLayer1.compositingFilter = "darkenBlendMode"
    view.layer.addSublayer(overlayLayer1)
    
    let overlayLayer2 = CALayer()
    overlayLayer2.frame = CGRect(x: widthIncrement,
                                 y: heightIncrement * 10,
                                 width: widthIncrement * 5,
                                 height: heightIncrement)
    overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
    overlayLayer2.compositingFilter = "divideBlendMode"
    view.layer.addSublayer(overlayLayer2)
    

    结果如下:

    我确认相同的代码在 iOS 中有效。这是视图控制器代码:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
    
            let heightIncrement = view.frame.height / 13
            let widthIncrement = view.frame.width / 7
    
    
            // TOP EXAMPLE (UIViews)
    
            let backgroundView = UIView(frame: CGRect(x: widthIncrement * 2,
                                                      y: heightIncrement,
                                                      width: widthIncrement * 3,
                                                      height: heightIncrement * 5))
            backgroundView.backgroundColor = .black
            view.addSubview(backgroundView)
    
            let overlayView1 = UIView(frame: CGRect(x: widthIncrement,
                                                    y: heightIncrement * 2,
                                                    width: widthIncrement * 5,
                                                    height: heightIncrement))
            overlayView1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
            overlayView1.layer.compositingFilter = "darkenBlendMode"
            view.addSubview(overlayView1)
    
            let overlayView2 = UIView(frame: CGRect(x: widthIncrement,
                                                    y: heightIncrement * 4,
                                                    width: widthIncrement * 5,
                                                    height: heightIncrement))
            overlayView2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3)
            overlayView2.layer.compositingFilter = "divideBlendMode"
            view.addSubview(overlayView2)
    
    
    
    
            // BOTTOM EXAMPLE (CALayers)
    
            let backgroundLayer = CALayer()
            backgroundLayer.frame = CGRect(x: widthIncrement * 2,
                                           y: heightIncrement * 7,
                                           width: widthIncrement * 3,
                                           height: heightIncrement * 5)
            backgroundLayer.backgroundColor = UIColor.black.cgColor
            view.layer.addSublayer(backgroundLayer)
    
            let overlayLayer1 = CALayer()
            overlayLayer1.frame = CGRect(x: widthIncrement,
                                         y: heightIncrement * 8,
                                         width: widthIncrement * 5,
                                         height: heightIncrement)
            overlayLayer1.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
            overlayLayer1.compositingFilter = "darkenBlendMode"
            view.layer.addSublayer(overlayLayer1)
    
            let overlayLayer2 = CALayer()
            overlayLayer2.frame = CGRect(x: widthIncrement,
                                         y: heightIncrement * 10,
                                         width: widthIncrement * 5,
                                         height: heightIncrement)
            overlayLayer2.backgroundColor = UIColor.yellow.withAlphaComponent(0.3).cgColor
            overlayLayer2.compositingFilter = "divideBlendMode"
            view.layer.addSublayer(overlayLayer2)
        }
    }
    

    这是模拟器中的结果:

    【讨论】:

    • 谢谢!您能否解释一下,您是如何发现可以在 compositingFilter 属性上使用“divideBlendMode”之类的字符串,而不是“CIDivideBlendMode”之类的?在文档中有compositingFilter: Any?,我不清楚如何使用它?‍♂️
    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2012-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    相关资源
    最近更新 更多