gpt4 book ai didi

swift - 应用于图层的 CATransform3DRotate 不起作用

转载 作者:搜寻专家 更新时间:2023-11-01 07:14:00 25 4
gpt4 key购买 nike

请问为什么 CATransform3DRotate 对我的图层不起作用,图像上的蓝色图层。

enter image description here

我有自定义 View ,我在其中绘制自然 View ,我想为更改月相设置动画,这将在白色圆圈层内完成,作为其 mask 。我想在这里应用 3DRotation 是个好主意,但出于某种原因,即使没有动画它也不起作用,请问我做错了什么?

    func drawMoonPhase(inRect rect:CGRect, inContext context: CGContext) {

let moonShape = UIBezierPath(ovalIn: rect)
moonShape.lineWidth = 4.0
UIColor.white.setStroke()
moonShape.stroke()
moonShape.close()

let moonLayer = CAShapeLayer()
moonLayer.path = moonShape.cgPath
moonLayer.opacity = 0
self.layer.addSublayer(moonLayer)

let circlePath = UIBezierPath(ovalIn: rect)
UIColor.blue.setFill()
circlePath.fill()
circlePath.close()

let circleShape = CAShapeLayer()
circleShape.path = circlePath.cgPath
circleShape.opacity = 0

var transform = CATransform3DIdentity
transform.m34 = -1 / 500.0

transform = CATransform3DRotate(transform, (CGFloat(Double.pi * 0.3)), 0, 1, 0)
circleShape.transform = transform

moonLayer.mask = circleShape

提前致谢

编辑:也许我想要清楚,我想要的效果如下: enter image description here

最佳答案

变换发生在图层的 anchor 周围,默认情况下 anchor 位于中心。因此,它正在发生的事情是形状围绕自身旋转,导致没有可见的结果。 :)

在此图层布局中,您应该做的是使用 cos 和 sin 数学函数来确定月亮的 x 和 y 位置。

如果您需要更多见解,请告诉我,我很乐意提供帮助。

另请注意,您不需要 2 个 shapeLayer 即可获得带有白色描边的蓝色月亮。 CAShapeLayer 具有填充和描边属性,因此您可以简化代码。

基于这里的新信息是我的新答案:

我无法通过使用变换获得很好的效果,所以我决定手动编写 mask 。这是结果:

/**
Draw a mask based on the moon phase progress.

- parameter rect: The rect where the mon will be drawn
- parameter progress: The progress of the moon phase. This value must be between 0 and 1
*/
func moonMask(in rect: CGRect, forProgress progress: CGFloat)->CALayer {
let path = CGMutablePath()
let center = CGPoint(x: rect.midX, y: rect.midY)
path.move(to: CGPoint(x: rect.midX, y: 0))

let relativeProgress = (max(min(progress, 1), 0) - 0.5) * 2
let radius = rect.width/2

let tgX = rect.midX+(relativeProgress * (radius*4/3))
path.addCurve(to: CGPoint(x: rect.midX, y: rect.maxY), control1: CGPoint(x: tgX, y: 0), control2: CGPoint(x: tgX, y: rect.maxY))
path.addArc(center: center, radius: rect.width/2, startAngle: .pi/2, endAngle: .pi*3/2, clockwise: false)
//path.closeSubpath()

let mask = CAShapeLayer()
mask.path = path
mask.fillColor = UIColor.black.cgColor

return mask
}

上面的函数绘制了一个可以用作 moonLayer mask 的整形器。该层将根据您将在函数中传递的进度参数绘制,其中 1 是满月,0 是新月。

您可以将所有内容放在一起以获得所需的效果,并且如果需要,您可以提取路径创建代码来制作漂亮的动画。

我希望这应该能回答您的问题。为了快速测试,我写了这个 Playground :

import UIKit

let rect = CGRect(origin: .zero, size: CGSize(width: 200, height: 200))

let view = UIView(frame: rect)
view.backgroundColor = .black
let layer = view.layer

/**
Draw a mask based on the moon phase progress.

- parameter rect: The rect where the mon will be drawn
- parameter progress: The progress of the moon phase. This value must be between 0 and 1
*/
func moonMask(in rect: CGRect, forProgress progress: CGFloat)->CALayer {
let path = CGMutablePath()
let center = CGPoint(x: rect.midX, y: rect.midY)
path.move(to: CGPoint(x: rect.midX, y: 0))

let relativeProgress = (max(min(progress, 1), 0) - 0.5) * 2
let radius = rect.width/2

let tgX = rect.midX+(relativeProgress * (radius*4/3))
path.addCurve(to: CGPoint(x: rect.midX, y: rect.maxY), control1: CGPoint(x: tgX, y: 0), control2: CGPoint(x: tgX, y: rect.maxY))
path.addArc(center: center, radius: rect.width/2, startAngle: .pi/2, endAngle: .pi*3/2, clockwise: false)
//path.closeSubpath()

let mask = CAShapeLayer()
mask.path = path
mask.fillColor = UIColor.white.cgColor

return mask
}

let moonLayer = CAShapeLayer()
moonLayer.path = UIBezierPath(ovalIn: rect).cgPath
moonLayer.fillColor = UIColor.clear.cgColor
moonLayer.strokeColor = UIColor.white.cgColor
moonLayer.lineWidth = 2
moonLayer.shadowColor = UIColor.white.cgColor
moonLayer.shadowOpacity = 1
moonLayer.shadowRadius = 10
moonLayer.shadowPath = moonLayer.path
moonLayer.shadowOffset = .zero

layer.addSublayer(moonLayer)

let moonPhase = moonMask(in: rect, forProgress: 0.3)
moonPhase.shadowColor = UIColor.white.cgColor
moonPhase.shadowOpacity = 1
moonPhase.shadowRadius = 10
moonPhase.shadowPath = moonLayer.path
moonPhase.shadowOffset = .zero

layer.addSublayer(moonPhase)

view

enter image description here

关于swift - 应用于图层的 CATransform3DRotate 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43282661/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com