【问题标题】:Swift: Add image to CAShapeLayerSwift:将图像添加到 CAShapeLayer
【发布时间】:2015-03-26 13:17:46
【问题描述】:

我有一个带有填充颜色的 CAShapeLayer,并且想在这个形状的中心添加一个图标:

var shape = CAShapeLayer()
shape.fillColor = UIColor(white: 0.90, alpha: 1).CGColor
var image = UIImage(named: "some_image")
shape.contents = image?.CGImage

此代码确实编译并显示灰色形状 - 但没有图像。 :(

我查看了这些帖子,但我无法像他们那样投射 CGImage。

add UIImage in CALayerDisplay an image or UIImage with a plain CALayer

还有其他方法吗?还是 id cast 的解决方法?

完整代码:

ViewController.swift

import UIKit

class ViewController: UIViewController {

    @IBOutlet var menuView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func viewDidAppear(animated: Bool) {

        let menu: CircularMenu = CircularMenu(frame: menuView.bounds, numberOfMenuItems: 4, hasProgressBar: false)
        self.menuView.addSubview(menu)
    }

}

CircularMenu.swift

import UIKit

// *** Helper methods start
func DegreesToRadians (value: Double) -> CGFloat {
    return CGFloat(value * M_PI / 180.0)
}

func RadiansToDegrees (value: Double) -> CGFloat {
    return CGFloat(value * 180.0 / M_PI)
}
// *** Helper methods end

class CircularMenu: UIControl {

    var parent: UIViewController!

    var centerButton: UIButton!
    var menuButtonShapes = [CAShapeLayer]()
    var menuButtons = [UIButton]()

    var numberOfButtons: Double = 4

    var bigSize: CGFloat = 300
    var centerButtonSize: CGFloat = 100
    var centerButtonPadding: CGFloat = 70
    let paddingBetweenButtons = 1

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    convenience init(frame: CGRect, numberOfMenuItems: Int, hasProgressBar: Bool = false) {
        self.init(frame: frame)
        self.bounds = frame

        self.bigSize = frame.width
        self.centerButtonSize = bigSize/2
        self.centerButtonPadding = bigSize/4-5

        if hasProgressBar {
            self.centerButtonSize -= 10
        }

        if numberOfMenuItems != 0 && numberOfMenuItems <= 10 {
            self.numberOfButtons = Double(numberOfMenuItems)
        }

        // Draw center button
        var centerButtonView = UIView(frame: CGRectMake(0, 0, centerButtonSize, centerButtonSize))
        centerButtonView.backgroundColor = UIColor(red: 160.0/255, green: 197.0/255, blue: 25.0/255, alpha: 1)

        centerButtonView.center = self.center;
        centerButtonView.layer.cornerRadius = centerButtonSize/2
        self.addSubview(centerButtonView)
        self.centerButton = UIButton(frame: centerButtonView.bounds)


        let degreesPerButton: Double = 360.0/numberOfButtons

        // Draw button shapes
        for (var i: Double = 1; i <= numberOfButtons; i++)
        {
            // Determine start and end radians of pizza slice
            let startAngle = DegreesToRadians(degreesPerButton*i+degreesPerButton-Double(paddingBetweenButtons))
            let endAngle = DegreesToRadians(degreesPerButton*i+Double(paddingBetweenButtons))

            // Determine center and angle of slice
            var buttonCenter = self.center;
            var offsetDirection = (startAngle - endAngle)/2 + endAngle

            // Shove slice outward to make space for inner padding
            var offsetX = cos(offsetDirection)*tan(DegreesToRadians(Double(paddingBetweenButtons)))*bigSize/2
            var offsetY = sin(offsetDirection)*tan(DegreesToRadians(Double(paddingBetweenButtons)))*bigSize/2

            buttonCenter.x += offsetX
            buttonCenter.y += offsetY

            // Create mask for outer rim of slice to a circular form (from triangle to pizza slice)
            let outerCircleRadius = bigSize/2;
            var bigCircle = UIBezierPath(arcCenter: self.center, radius: bigSize/2, startAngle: startAngle , endAngle: endAngle, clockwise: false);
            bigCircle.addLineToPoint(buttonCenter)
            bigCircle.closePath()

            // Take padding into consideration when creating mask
            let tmpBigSizeX = (bigSize+2*abs(offsetX))
            let tmpBigSizeY = (bigSize+2*abs(offsetY))

            // Create mask for inner rim of slice to a circular form (from pizza slice to donut slice)
            let smallSize = bigSize-centerButtonSize-centerButtonPadding
            let innerCircleRadius = outerCircleRadius-bigSize/2/2;
            var smallCircle = UIBezierPath(arcCenter: self.center, radius: smallSize, startAngle: 0 , endAngle: DegreesToRadians(360), clockwise: false);

            // Apply masks for everything but the donut slice shape
            var buttonShape = CAShapeLayer()
            var maskLayer = CAShapeLayer()
            var maskPath = CGPathCreateMutable();

            CGPathAddRect(maskPath, nil, CGRectMake(outerCircleRadius-tmpBigSizeX/2, outerCircleRadius-tmpBigSizeY/2, tmpBigSizeX, tmpBigSizeY));
            CGPathAddPath(maskPath, nil, smallCircle.CGPath);
            maskLayer.path = maskPath;
            maskLayer.fillRule = kCAFillRuleEvenOdd;

            buttonShape.path = bigCircle.CGPath
            buttonShape.mask = maskLayer
            buttonShape.fillColor = UIColor(white: 0.90, alpha: 1).CGColor

            // Add icons and labels to the button
            var image = UIImage(named: "menu-icon_users_grey")
            let imageSubLayer = CALayer()
            imageSubLayer.contents = image?.CGImage
            buttonShape.addSublayer(imageSubLayer)

            // Save references to both shape and button
            self.menuButtons.append(UIButton(frame: buttonShape.frame))
            self.menuButtonShapes.append(buttonShape)

            // Add shape to view
            self.layer.addSublayer(buttonShape)
        }
    }

}

感兴趣的行在自定义 UIControl 底部的注释下:

“给按钮添加图标和标签”

【问题讨论】:

  • 为什么你希望图层在填充颜色上绘制图像?尝试向该图层添加子图层并将图像添加到该图层。
  • 不,我试过了,但还是没有画出来... :(
  • 你能显示你正在使用的代码吗?没有理由不画画。对于 CALayers,您需要适当地设置边界。
  • 感谢@JackWu,如果您想在自己的项目中尝试,我上传了整个课程。 :) 希望你能帮忙!

标签: swift ios8 uiimage cgimage cashapelayer


【解决方案1】:

你有两个选择:

不太好的一个,将 UIImage 转换为一种颜色,然后将其转换为 CGColor,但是由于您的代码 sn-p 太小,我不知道什么会起作用:

let image = UIImage(named: "")
if let realImage = image {
    let color = UIColor(patternImage: realImage)
    shape.fillColor = color.CGColor
}

和推荐的一样,创建一个新层并在其内容上设置 UIImage:

let imageSubLayer = CALayer()
imageSubLayer.contents = image?.CGImage
shape.addSublayer(imageSubLayer)

我现在无法测试它,所以告诉我它是否有效。

【讨论】:

  • 没有。推荐的解决方案至少在运行 10.x 的 TViOS 上不起作用
  • 我不在 tvOS 上测试它,但在 iOS 中你需要为该 imageSublayer 设置一个框架才能工作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-03
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多