【问题标题】:How to blend multiple UIView in iOS?如何在 iOS 中混合多个 UIView?
【发布时间】:2019-05-28 20:49:11
【问题描述】:

我想混合多个 UIView,使其可以平滑移动、旋转和调整大小。

我已经使用下面的代码实现了这一点,但它不如 PicsArt 和 SnapSeed 等其他应用程序流畅。

- (void)drawRect:(CGRect)rect {
   // Drawing code

   [super drawRect:rect];

   UIImage *viewImage = [self captureView:self.superview withFrame:self.frame];

   [viewImage drawInRect:rect];

   [self.imageToBlend drawInRect:rect blendMode:self.blendMode alpha:self.alphaBlend];

  // Other code....  
}

【问题讨论】:

  • 我想我没有得到你的问题,你为什么不使用 CGAffineTransform?如果您在托管视图上应用旋转、平移,它会自动在其中混合子视图,Core Animation 将硬件加速一切

标签: ios objective-c uiview blend


【解决方案1】:

您不能以这种方式混合视图;它们具有独立解析的单独层层次结构。移动 CALayer 对象上的渐变和文本并混合它们(或在同一视图中手动绘制它们)。例如:

class MyView: UIView {
    let gradientLayer: CAGradientLayer = {
        let gradientLayer = CAGradientLayer()
        gradientLayer.colors = [UIColor.red.cgColor,
                                UIColor.blue.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0)
        gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        return gradientLayer
    }()

    let textLayer: CATextLayer = {
        let textLayer = CATextLayer()
        let astring = NSAttributedString(string: "Text Example",
                                         attributes: [.font: UIFont(name: "MarkerFelt-Wide", size: 60)!])
        textLayer.string = astring
        textLayer.alignmentMode = kCAAlignmentCenter
        textLayer.bounds = astring.boundingRect(with: CGSize(width: .max, height: .max),
                                                options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
        return textLayer
    }()

    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            gradientLayer.bounds = bounds
            gradientLayer.render(in: context)

            context.saveGState()
            context.setBlendMode(.softLight)

            context.translateBy(x: center.x - textLayer.bounds.width / 2,
                                y: center.y - textLayer.bounds.height / 2)

            textLayer.position = center
            textLayer.render(in: context)
            context.restoreGState()
        }
    }
}

你不会通过搜索尝试你自己的逻辑得到正确的答案。

通过使用上下文,您可以使用手势和所有其他方式。

【讨论】:

    【解决方案2】:

    每次当drawRect: 听起来太重时进行捕捉和混合。

    您似乎想用各种混合模式和 alpha 将一些图像混合到其后端。

    在这种情况下,您最好混合整个视图,并使用view.layer.mask 仅显示混合结果的蒙版区域。

    因此您只需移动、旋转和调整view.layer.mask 的大小,无需捕捉或混合。它应该更快。

    类似的东西。

    class MyView: UIImageView {
        var backendImage: UIImage?
        var blendImage: UIImage?
        var blendMode: CGBlendMode = .normal
        var alphaBlend: Float = 0.5
    
        func setup(backend: UIView) {
            self.backendImage = self.captureView(backend)
            self.image = self.createBlendImage()
            self.layer.mask = self.createMask()
        }
    
        func captureView(view: UIView) -> UIImage {
            // capture view
        }
    
        func createBlendImage() -> UIImage {
            // prepare ImageContext, draw two image, get image, and so on...
        }
    
        func createMask() -> CALayer {
            let mask = CAShapeLayer()
            // setup the shape of mask
        }
    
        func moveMask(origin: CGPoint, scale: Float, rotation: Float) {
            // change mask
            self.layer.mask.frame = ...
            self.layer.mask.transform = ...
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 2015-03-06
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 2013-04-30
      • 2010-11-26
      • 2019-03-02
      相关资源
      最近更新 更多