Как смешать несколько UIView в iOS? - PullRequest
0 голосов
/ 02 января 2019

Я хочу смешать несколько 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....  
}

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Захват и смешивание каждый раз, когда drawRect: звучит слишком тяжело.

Кажется, что вы хотите смешать какое-то изображение с бэкэндом с помощью различных режимов смешивания и альфа.

В этом случае, вам лучше смешать весь вид и использовать 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 = ...
    }
}
0 голосов
/ 22 января 2019

Вы не можете смешивать представления таким образом; у них есть отдельные иерархии слоев, которые разрешаются независимо. Переместите градиент и текст на объекты 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()
        }
    }
}

Вы не получите правильный ответ, если попытаетесь найти свою собственную логику.

Используя контекст, вы можете использовать жест и все остальное.

...